From b8ef944c4888d745ef5e22418cbf7e3dec8cce43 Mon Sep 17 00:00:00 2001 From: yihao Date: Wed, 4 Mar 2026 15:05:14 +0800 Subject: [PATCH 1/6] Rename nunjucks patches to ts --- .../{context-overrides-frame.js => context-overrides-frame.ts} | 0 packages/core/src/patches/nunjucks/{index.js => index.ts} | 0 .../core/src/patches/nunjucks/{load-event.js => load-event.ts} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/core/src/patches/nunjucks/{context-overrides-frame.js => context-overrides-frame.ts} (100%) rename packages/core/src/patches/nunjucks/{index.js => index.ts} (100%) rename packages/core/src/patches/nunjucks/{load-event.js => load-event.ts} (100%) diff --git a/packages/core/src/patches/nunjucks/context-overrides-frame.js b/packages/core/src/patches/nunjucks/context-overrides-frame.ts similarity index 100% rename from packages/core/src/patches/nunjucks/context-overrides-frame.js rename to packages/core/src/patches/nunjucks/context-overrides-frame.ts diff --git a/packages/core/src/patches/nunjucks/index.js b/packages/core/src/patches/nunjucks/index.ts similarity index 100% rename from packages/core/src/patches/nunjucks/index.js rename to packages/core/src/patches/nunjucks/index.ts diff --git a/packages/core/src/patches/nunjucks/load-event.js b/packages/core/src/patches/nunjucks/load-event.ts similarity index 100% rename from packages/core/src/patches/nunjucks/load-event.js rename to packages/core/src/patches/nunjucks/load-event.ts From 2838211e4ef6f4f7dcf483053bff62166267c68d Mon Sep 17 00:00:00 2001 From: yihao Date: Wed, 4 Mar 2026 16:33:26 +0800 Subject: [PATCH 2/6] Migrate nunjucks patches to typescript created module augmentation in .d.ts files for components patches, with types inferred by studying the usage in the node_modules src files. added tsc compiled .js files to .gitignore and prevent .d.ts files from being ignored Ignore compiled js and patched ts from linting --- .eslintignore | 1 + .gitignore | 3 + .../nunjucks/context-overrides-frame.ts | 141 ++++---- packages/core/src/patches/nunjucks/index.ts | 4 +- .../core/src/patches/nunjucks/load-event.ts | 35 +- .../patches/nunjucks/nunjucks-internals.d.ts | 320 ++++++++++++++++++ .../patches/nunjucks/nunjucks-submodules.d.ts | 123 +++++++ 7 files changed, 554 insertions(+), 73 deletions(-) create mode 100644 packages/core/src/patches/nunjucks/nunjucks-internals.d.ts create mode 100644 packages/core/src/patches/nunjucks/nunjucks-submodules.d.ts diff --git a/.eslintignore b/.eslintignore index 3f16c9af8d..4ecf195e5b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -20,6 +20,7 @@ packages/core/src/lib/markdown-it/highlight/*.js packages/core/src/lib/markdown-it/plugins/**/*.js packages/core/src/lib/markdown-it/utils/*.js packages/core/src/Page/*.js +packages/core/src/patches/nunjucks/*.js packages/core/src/plugins/**/*.js packages/core/src/Site/*.js packages/core/src/utils/*.js diff --git a/.gitignore b/.gitignore index 9e363394d6..0b7a0fa93a 100644 --- a/.gitignore +++ b/.gitignore @@ -104,10 +104,13 @@ packages/core/test/unit/**/*.js packages/core/index.js packages/core/src/lib/progress/*.js +packages/core/src/patches/nunjucks/*.js # --- packages/core end --- # Manual type definitions need to be included !packages/cli/src/lib/live-server/index.d.ts +!packages/core/src/patches/nunjucks/nunjucks-internals.d.ts +!packages/core/src/patches/nunjucks/nunjucks-submodules.d.ts # Nx for Lerna .nx/cache diff --git a/packages/core/src/patches/nunjucks/context-overrides-frame.ts b/packages/core/src/patches/nunjucks/context-overrides-frame.ts index 8cf53f33d2..edf0067faa 100644 --- a/packages/core/src/patches/nunjucks/context-overrides-frame.ts +++ b/packages/core/src/patches/nunjucks/context-overrides-frame.ts @@ -13,20 +13,32 @@ The **only** changes are delimited with a // CHANGE HERE comment */ +/* linting is disabled for this file to keep the patch close to the source */ /* eslint-disable */ -const runtime = require('nunjucks/src/runtime'); -const { - Environment, Template, lib, compiler, nodes, -} = require('nunjucks'); -const { Obj } = require('nunjucks/src/object'); -const globalRuntime = runtime; +import * as runtimeTypes from 'nunjucks/src/runtime'; +import { Environment, Template, lib, compiler, nodes } from 'nunjucks'; +import { Obj } from 'nunjucks/src/object'; + +// We need a mutable reference to the runtime module so we can monkey-patch +// Frame and contextOrFrameLookup. ESM namespace imports (import * as ...) are +// frozen objects, so we fall back to require() which returns the original mutable exports. +// eslint-disable-next-line @typescript-eslint/no-var-requires +const globalRuntime: typeof runtimeTypes & Record = require('nunjucks/src/runtime'); const MB_CTX_KEY = '_markBindReserved'; +/** + * Replacement for nunjucks' internal callbackAsap which is not exported. + * Schedules a callback to run asynchronously via queueMicrotask. + */ +function callbackAsap(cb: Function, err: any, res?: any) { + queueMicrotask(() => { cb(err, res); }); +} + -Environment.prototype.render = function render(name, ctx, cb) { +Environment.prototype.render = function render(this: Environment, name: any, ctx: any, cb?: any) { if (lib.isFunction(ctx)) { cb = ctx; ctx = null; @@ -44,8 +56,8 @@ Environment.prototype.render = function render(name, ctx, cb) { } } - var syncResult = null; - this.getTemplate(name, function (err, tmpl) { + var syncResult: any = null; + this.getTemplate(name, function (err: any, tmpl: any) { if (err && cb) { callbackAsap(cb, err); } else if (err) { @@ -57,7 +69,7 @@ Environment.prototype.render = function render(name, ctx, cb) { return syncResult; }; -Environment.prototype.renderString = function renderString(src, ctx, opts, cb) { +(Environment.prototype as any).renderString = function renderString(this: Environment, src: any, ctx: any, opts?: any, cb?: any) { if (lib.isFunction(opts)) { cb = opts; opts = {}; @@ -73,14 +85,19 @@ Environment.prototype.renderString = function renderString(src, ctx, opts, cb) { } opts = opts || {}; - var tmpl = new Template(src, this, opts.path); + var tmpl = new Template(src, this as any, opts.path); return tmpl.render(ctx, cb); }; // Unfortunately the Context class isn't exposed so we can't patch it directly. // So we import methods that use it and let them use this custom implementation instead class Context extends Obj { - init(ctx, blocks, env) { + env: any; + ctx!: Record; + blocks!: Record; + exported!: string[]; + + init(ctx: any, blocks: any, env: any) { // Has to be tied to an environment so we can tap into its globals. this.env = env || new Environment(); @@ -90,12 +107,12 @@ class Context extends Obj { this.blocks = {}; this.exported = []; - lib.keys(blocks).forEach(name => { + lib.keys(blocks).forEach((name: string) => { this.addBlock(name, blocks[name]); }); } - lookup(name) { + lookup(name: string) { // This is one of the most called functions, so optimize for // the typical case where the name isn't in the globals if (name in this.env.globals && !(name in this.ctx)) { @@ -106,13 +123,13 @@ class Context extends Obj { } // CHANGE HERE - new method - lookupMbVariable(name) { + lookupMbVariable(name: string) { return MB_CTX_KEY in this.ctx ? this.ctx[MB_CTX_KEY][name] : undefined; } - setVariable(name, val) { + setVariable(name: string, val: any) { this.ctx[name] = val; } @@ -120,13 +137,13 @@ class Context extends Obj { return this.ctx; } - addBlock(name, block) { + addBlock(name: string, block: Function) { this.blocks[name] = this.blocks[name] || []; this.blocks[name].push(block); return this; } - getBlock(name) { + getBlock(name: string) { if (!this.blocks[name]) { throw new Error('unknown block "' + name + '"'); } @@ -134,7 +151,7 @@ class Context extends Obj { return this.blocks[name][0]; } - getSuper(env, name, block, frame, runtime, cb) { + getSuper(env: any, name: string, block: Function, frame: any, runtime: any, cb: Function) { var idx = lib.indexOf(this.blocks[name] || [], block); var blk = this.blocks[name][idx + 1]; var context = this; @@ -146,12 +163,12 @@ class Context extends Obj { blk(env, context, frame, runtime, cb); } - addExport(name) { + addExport(name: string) { this.exported.push(name); } getExported() { - var exported = {}; + var exported: Record = {}; this.exported.forEach((name) => { exported[name] = this.ctx[name]; }); @@ -160,7 +177,13 @@ class Context extends Obj { } class Frame { - constructor(parent, isolateWrites) { + variables: Record; + parent: Frame | null | undefined; + topLevel: boolean; + isolateWrites: boolean | undefined; + imports?: Set; + + constructor(parent?: Frame, isolateWrites?: boolean) { this.variables = {}; this.parent = parent; this.topLevel = false; @@ -171,12 +194,12 @@ class Frame { // CHANGE HERE // Additional parameter isImport - set(name, val, resolveUp, isImport) { + set(name: string, val: any, resolveUp?: boolean, isImport?: boolean) { // Allow variables with dots by automatically creating the // nested structure var parts = name.split('.'); - var obj = this.variables; - var frame = this; + var obj: any = this.variables; + var frame: Frame | undefined = this; // CHANGE HERE // flag imports, so we can exclude them from Compiler#compileSymbol @@ -204,7 +227,7 @@ class Frame { obj[parts[parts.length - 1]] = val; } - get(name) { + get(name: string) { var val = this.variables[name]; if (val !== undefined) { return val; @@ -213,7 +236,7 @@ class Frame { } // CHANGE HERE - additional parameter checkIfIsImport, used for compileSymbol - lookup(name, checkIfIsImport) { + lookup(name: string, checkIfIsImport?: boolean): any { var p = this.parent; var val = this.variables[name]; if (val !== undefined) { @@ -228,16 +251,16 @@ class Frame { return p && p.lookup(name); } - resolve(name, forWrite) { - var p = (forWrite && this.isolateWrites) ? undefined : this.parent; + resolve(name: string, forWrite?: boolean): Frame | undefined { + var p: Frame | null | undefined = (forWrite && this.isolateWrites) ? undefined : this.parent; var val = this.variables[name]; if (val !== undefined) { return this; } - return p && p.resolve(name); + return p ? p.resolve(name) : undefined; } - push(isolateWrites) { + push(isolateWrites?: boolean) { return new Frame(this, isolateWrites); } @@ -245,9 +268,9 @@ class Frame { return this.parent; } } -runtime.Frame = Frame; +globalRuntime.Frame = Frame; -compiler.Compiler.prototype.compileImport = function compileImport(node, frame) { +compiler.Compiler.prototype.compileImport = function compileImport(this: compiler.Compiler, node: any, frame: any) { const target = node.target.value; const id = this._compileGetTemplate(node, frame, false, false); this._addScopeLevel(); @@ -267,7 +290,7 @@ compiler.Compiler.prototype.compileImport = function compileImport(node, frame) } } -compiler.Compiler.prototype.compileFromImport = function compileFromImport(node, frame) { +compiler.Compiler.prototype.compileFromImport = function compileFromImport(this: compiler.Compiler, node: any, frame: any) { const importedId = this._compileGetTemplate(node, frame, false, false); this._addScopeLevel(); @@ -276,7 +299,7 @@ compiler.Compiler.prototype.compileFromImport = function compileFromImport(node, this._makeCallback(importedId)); this._addScopeLevel(); - node.names.children.forEach((nameNode) => { + node.names.children.forEach((nameNode: any) => { var name; var alias; var id = this._tmpid(); @@ -306,7 +329,7 @@ compiler.Compiler.prototype.compileFromImport = function compileFromImport(node, }); } -compiler.Compiler.prototype.compileSymbol = function compileSymbol(node, frame) { +compiler.Compiler.prototype.compileSymbol = function compileSymbol(this: compiler.Compiler, node: any, frame: any) { var name = node.value; // CHANGE HERE // returns undefined if it is an import @@ -319,7 +342,7 @@ compiler.Compiler.prototype.compileSymbol = function compileSymbol(node, frame) } }; -runtime.contextOrFrameLookup = function contextOrFrameLookup(context, frame, name) { +globalRuntime.contextOrFrameLookup = function contextOrFrameLookup(context: any, frame: any, name: string) { // CHANGE HERE - always look up MarkBind variables first var mbVar = context.lookupMbVariable(name); if (mbVar !== undefined) { @@ -335,7 +358,7 @@ runtime.contextOrFrameLookup = function contextOrFrameLookup(context, frame, nam */ // No modifications, redefined only to redirect the Context class to our custom implementation -Template.prototype.render = function render(ctx, parentFrame, cb) { +Template.prototype.render = function render(this: Template, ctx?: any, parentFrame?: any, cb?: any) { var _this6 = this; if (typeof ctx === 'function') { @@ -354,8 +377,8 @@ Template.prototype.render = function render(ctx, parentFrame, cb) { try { this.compile(); - } catch (e) { - var err = lib._prettifyError(this.path, this.env.opts.dev, e); + } catch (e: any) { + var err = lib._prettifyError(this.path, this.env.opts.dev!, e); if (cb) { return callbackAsap(cb, err); @@ -367,9 +390,9 @@ Template.prototype.render = function render(ctx, parentFrame, cb) { var context = new Context(ctx || {}, this.blocks, this.env); var frame = parentFrame ? parentFrame.push(true) : new Frame(); frame.topLevel = true; - var syncResult = null; + var syncResult: any = null; var didError = false; - this.rootRenderFunc(this.env, context, frame, globalRuntime, function (err, res) { + this.rootRenderFunc(this.env, context, frame, globalRuntime, function (err: any, res: any) { // TODO: this is actually a bug in the compiled template (because waterfall // tasks are both not passing errors up the chain of callbacks AND are not // causing a return from the top-most render function). But fixing that @@ -380,7 +403,7 @@ Template.prototype.render = function render(ctx, parentFrame, cb) { } if (err) { - err = lib._prettifyError(_this6.path, _this6.env.opts.dev, err); + err = lib._prettifyError(_this6.path, _this6.env.opts.dev!, err); didError = true; } @@ -402,7 +425,7 @@ Template.prototype.render = function render(ctx, parentFrame, cb) { }; // No modifications, redefined only to redirect the Context class to our custom implementation -Template.prototype.getExported = function getExported(ctx, parentFrame, cb) { +(Template.prototype as any).getExported = function getExported(this: Template, ctx?: any, parentFrame?: any, cb?: any) { // eslint-disable-line consistent-return if (typeof ctx === 'function') { cb = ctx; @@ -429,7 +452,7 @@ Template.prototype.getExported = function getExported(ctx, parentFrame, cb) { frame.topLevel = true; // Run the rootRenderFunc to populate the context with exported vars var context = new Context(ctx || {}, this.blocks, this.env); - this.rootRenderFunc(this.env, context, frame, globalRuntime, function (err) { + this.rootRenderFunc(this.env, context, frame, globalRuntime, function (err: any) { if (err) { cb(err, null); } else { @@ -439,14 +462,14 @@ Template.prototype.getExported = function getExported(ctx, parentFrame, cb) { }; // No modifications, redefined only to redirect the Context class to our custom implementation -compiler.Compiler.prototype._compileMacro = function _compileMacro(node, frame) { - var args = []; - var kwargs = null; +compiler.Compiler.prototype._compileMacro = function _compileMacro(this: compiler.Compiler, node: any, frame: any) { + var args: any[] = []; + var kwargs: any = null; var funcId = 'macro_' + this._tmpid(); var keepFrame = (frame !== undefined); // Type check the definition of the args - node.args.children.forEach((arg, i) => { + node.args.children.forEach((arg: any, i: number) => { if (i === node.args.children.length - 1 && arg instanceof nodes.Dict) { kwargs = arg; } else { @@ -455,17 +478,17 @@ compiler.Compiler.prototype._compileMacro = function _compileMacro(node, frame) } }); - const realNames = [...args.map((n) => `l_${n.value}`), 'kwargs']; + const realNames = [...args.map((n: any) => `l_${n.value}`), 'kwargs']; // Quoted argument names - const argNames = args.map((n) => `"${n.value}"`); - const kwargNames = ((kwargs && kwargs.children) || []).map((n) => `"${n.key.value}"`); + const argNames = args.map((n: any) => `"${n.value}"`); + const kwargNames = ((kwargs && kwargs.children) || []).map((n: any) => `"${n.key.value}"`); // We pass a function to makeMacro which destructures the // arguments so support setting positional args with keywords // args and passing keyword args as positional args // (essentially default values). See runtime.js. - let currFrame; + let currFrame: any; if (keepFrame) { currFrame = frame.push(true); } else { @@ -485,14 +508,14 @@ compiler.Compiler.prototype._compileMacro = function _compileMacro(node, frame) // Expose the arguments to the template. Don't need to use // random names because the function // will create a new run-time scope for us - args.forEach((arg) => { + args.forEach((arg: any) => { this._emitLine(`frame.set("${arg.value}", l_${arg.value});`); currFrame.set(arg.value, `l_${arg.value}`); }); // Expose the keyword arguments if (kwargs) { - kwargs.children.forEach((pair) => { + kwargs.children.forEach((pair: any) => { const name = pair.key.value; this._emit(`frame.set("${name}", `); this._emit(`Object.prototype.hasOwnProperty.call(kwargs, "${name}")`); @@ -517,7 +540,7 @@ compiler.Compiler.prototype._compileMacro = function _compileMacro(node, frame) } // No modifications, redefined only to redirect the Context class to our custom implementation -compiler.Compiler.prototype.compileRoot = function compileRoot(node, frame) { +compiler.Compiler.prototype.compileRoot = function compileRoot(this: compiler.Compiler, node: any, frame: any) { if (frame) { this.fail('compileRoot: root node can\'t have frame'); } @@ -536,11 +559,11 @@ compiler.Compiler.prototype.compileRoot = function compileRoot(node, frame) { this.inBlock = true; - const blockNames = []; + const blockNames: string[] = []; const blocks = node.findAll(nodes.Block); - blocks.forEach((block, i) => { + blocks.forEach((block: any, i: number) => { const name = block.name.value; if (blockNames.indexOf(name) !== -1) { @@ -558,7 +581,7 @@ compiler.Compiler.prototype.compileRoot = function compileRoot(node, frame) { this._emitLine('return {'); - blocks.forEach((block, i) => { + blocks.forEach((block: any, i: number) => { const blockName = `b_${block.name.value}`; this._emitLine(`${blockName}: ${blockName},`); }); diff --git a/packages/core/src/patches/nunjucks/index.ts b/packages/core/src/patches/nunjucks/index.ts index f801400a88..ae4ca1efe5 100644 --- a/packages/core/src/patches/nunjucks/index.ts +++ b/packages/core/src/patches/nunjucks/index.ts @@ -1,2 +1,2 @@ -require('./load-event'); -require('./context-overrides-frame'); +import './load-event'; +import './context-overrides-frame'; diff --git a/packages/core/src/patches/nunjucks/load-event.ts b/packages/core/src/patches/nunjucks/load-event.ts index 032ac3b509..3708d27aa4 100644 --- a/packages/core/src/patches/nunjucks/load-event.ts +++ b/packages/core/src/patches/nunjucks/load-event.ts @@ -8,14 +8,18 @@ Changes are delimited with a // CHANGE HERE comment */ -const { Environment, Template, lib } = require('nunjucks'); - +/* linting is disabled for this file to keep the patch close to the source */ /* eslint-disable */ +import { Environment, Template, lib } from 'nunjucks'; +import { handleError } from 'nunjucks/src/runtime'; + +/* eslint-disable @typescript-eslint/no-this-alias */ + var noopTmplSrc = { type: 'code', obj: { - root: function root(env, context, frame, runtime, cb) { + root: function root(env: any, context: any, frame: any, runtime: any, cb: Function) { try { cb(null, ''); } catch (e) { @@ -25,11 +29,18 @@ var noopTmplSrc = { } }; -Environment.prototype.getTemplate = function getTemplate(name, eagerCompile, parentName, ignoreMissing, cb) { +(Environment.prototype as any).getTemplate = function getTemplate( + this: Environment, + name: any, + eagerCompile?: any, + parentName?: any, + ignoreMissing?: any, + cb?: any, +) { var _this3 = this; var that = this; - var tmpl = null; + var tmpl: Template | null = null; if (name && name.raw) { // this fixes autoescape for templates referenced in symbols @@ -63,7 +74,7 @@ Environment.prototype.getTemplate = function getTemplate(name, eagerCompile, par Object.entries(loader.pathsToNames).forEach(([fullPath, templateName]) => { if (name === templateName) { // Emit the load event - this.emit('load', name, { + (this as any).emit('load', name, { src: tmpl, path: fullPath, // we only need this noCache: loader.noCache @@ -89,9 +100,9 @@ Environment.prototype.getTemplate = function getTemplate(name, eagerCompile, par } } - var syncResult; + var syncResult: Template | undefined; - var createTemplate = function createTemplate(err, info) { + var createTemplate = function createTemplate(err: any, info: any) { if (!info && !err && !ignoreMissing) { err = new Error('template not found: ' + name); } @@ -108,7 +119,7 @@ Environment.prototype.getTemplate = function getTemplate(name, eagerCompile, par var newTmpl; if (!info) { - newTmpl = new Template(noopTmplSrc, _this3, '', eagerCompile); + newTmpl = new Template(noopTmplSrc as any, _this3, '', eagerCompile); } else { newTmpl = new Template(info.src, _this3, info.path, eagerCompile); @@ -124,8 +135,8 @@ Environment.prototype.getTemplate = function getTemplate(name, eagerCompile, par } }; - lib.asyncIter(this.loaders, function (loader, i, next, done) { - function handle(err, src) { + lib.asyncIter(this.loaders, function (loader: any, i: number, next: () => void, done: Function) { + function handle(err: any, src: any) { if (err) { done(err); } else if (src) { @@ -146,4 +157,4 @@ Environment.prototype.getTemplate = function getTemplate(name, eagerCompile, par } }, createTemplate); return syncResult; -} \ No newline at end of file +} diff --git a/packages/core/src/patches/nunjucks/nunjucks-internals.d.ts b/packages/core/src/patches/nunjucks/nunjucks-internals.d.ts new file mode 100644 index 0000000000..567fdaefd1 --- /dev/null +++ b/packages/core/src/patches/nunjucks/nunjucks-internals.d.ts @@ -0,0 +1,320 @@ +/** + * Module augmentations for nunjucks internals used by MarkBind patches. + * + * @types/nunjucks only covers the public API surface. These patches need access + * to internal classes (Frame, Compiler, Context, Obj) and sub-modules + * (nunjucks/src/runtime, nunjucks/src/object) that are not typed. + * + * Typed against nunjucks v3.2.4 (runtime internals used by the patches only). + */ + +// This export makes the file a module, turning 'declare module' blocks below +// into module augmentations (merged with existing declarations) rather than +// ambient module declarations (which would replace existing declarations). +export {}; + +// --------------------------------------------------------------------------- +// Sub-module: nunjucks/src/runtime +// --------------------------------------------------------------------------- +declare module 'nunjucks/src/runtime' { + + export class Frame { + variables: Record; + parent: Frame | null | undefined; + topLevel: boolean; + isolateWrites: boolean | undefined; + + /** Set of imported names — added by the MarkBind patch */ + imports?: Set; + + constructor(parent?: Frame, isolateWrites?: boolean); + + /** + * Set a variable in this frame. + * @param name Dot-separated variable name (e.g. "a.b.c") + * @param val Value to set + * @param resolveUp If true, walk up the frame chain and set on the first frame that owns the name + * @param isImport MarkBind patch extension — flags the variable as an import + */ + set(name: string, val: any, resolveUp?: boolean, isImport?: boolean): void; + + /** Get a variable from this frame only (no parent walk). */ + get(name: string): any; + + /** + * Look up a variable by walking the parent chain. + * @param checkIfIsImport MarkBind patch extension — returns undefined for imports + */ + lookup(name: string, checkIfIsImport?: boolean): any; + + /** Resolve which frame owns a variable. */ + resolve(name: string, forWrite?: boolean): Frame | undefined; + + /** Create a child frame. */ + push(isolateWrites?: boolean): Frame; + + /** Return to the parent frame. */ + pop(): Frame | null | undefined; + } + + /** Runtime variable resolution: checks frame chain, then context. */ + export function contextOrFrameLookup(context: any, frame: Frame, name: string): any; + + export function makeMacro( + argNames: string[], + kwargNames: string[], + func: (...args: any[]) => any, + ): (...args: any[]) => any; + + export function makeKeywordArgs(obj: Record): Record; + export function numArgs(args: any[]): number; + export function suppressValue(val: any, autoescape: boolean): string; + export function ensureDefined(val: any, lineno: number, colno: number): any; + export function memberLookup(obj: any, val: any): any; + export function callWrap(obj: any, name: string, context: any, args: any[]): any; + export function handleError(error: any, lineno: number | null, colno: number | null): Error; + export function copySafeness(dest: any, target: any): any; + export function markSafe(val: any): SafeString; + export function asyncEach(arr: any[], dimen: number, iter: Function, cb: Function): void; + export function asyncAll(arr: any[], dimen: number, func: Function, cb: Function): void; + export function fromIterator(arr: any): any[]; + + export const isArray: (obj: any) => obj is any[]; + export const keys: (obj: any) => string[]; + export const inOperator: (key: any, val: any) => boolean; + + export class SafeString extends String { + constructor(val: string); + val: string; + length: number; + valueOf(): string; + toString(): string; + } +} + +// --------------------------------------------------------------------------- +// Sub-module: nunjucks/src/object +// --------------------------------------------------------------------------- +declare module 'nunjucks/src/object' { + export class Obj { + constructor(...args: any[]); + + /** Called by the constructor with all constructor arguments. Override in subclasses. */ + init(...args: any[]): void; + + /** Returns this.constructor.name */ + readonly typename: string; + + /** Create a subclass using nunjucks' custom OOP system. */ + static extend( + this: T, + name: string, + props?: Record, + ): T; + static extend( + this: T, + props: Record, + ): T; + } + + export class EmitterObj extends Obj { + on(name: string, func: (...args: any[]) => void): void; + emit(name: string, ...args: any[]): void; + } +} + +// --------------------------------------------------------------------------- +// Augment the main 'nunjucks' module with internal properties & sub-modules +// --------------------------------------------------------------------------- +declare module 'nunjucks' { + import { Frame } from 'nunjucks/src/runtime'; + import { Obj } from 'nunjucks/src/object'; + + // ---- lib namespace additions ---- + namespace lib { + function isFunction(obj: any): obj is Function; + function extend(obj1: any, ...objs: any[]): any; + function keys(obj: any): string[]; + function indexOf(arr: T[], item: T): number; + function asyncIter( + arr: any[], + iter: (item: any, index: number, next: () => void, done: (err?: any, result?: any) => void) => void, + cb: (err?: any, result?: any) => void, + ): void; + function _prettifyError(path: string | null, withInternals: boolean, err: Error): Error; + function inOperator(key: any, val: any): boolean; + function isArray(obj: any): obj is any[]; + } + + // ---- runtime namespace additions ---- + namespace runtime { + export { Frame }; + + function contextOrFrameLookup(context: any, frame: Frame, name: string): any; + function makeMacro( + argNames: string[], + kwargNames: string[], + func: (...args: any[]) => any, + ): (...args: any[]) => any; + function handleError(error: any, lineno: number | null, colno: number | null): Error; + } + + // ---- nodes namespace (AST node types used by the patches) ---- + namespace nodes { + class Node { + lineno: number; + colno: number; + fields: string[]; + findAll(type: new (...args: any[]) => T, results?: T[]): T[]; + iterFields(func: (node: any, fieldName: string) => void): void; + } + + class Value extends Node { + value: any; + } + + class Symbol extends Value { + value: string; + } + + class NodeList extends Node { + children: Node[]; + addChild(node: Node): void; + } + + class Pair extends Node { + key: Value; + value: Value; + } + + class Dict extends NodeList { + children: Pair[]; + } + + class Block extends Node { + name: Value; + body: NodeList; + } + + class Import extends Node { + template: Node; + target: Value; + withContext: boolean; + } + + class FromImport extends Node { + template: Node; + names: NodeList; + withContext: boolean; + } + + class Macro extends Node { + name: Value; + args: NodeList; + body: NodeList; + } + } + + // ---- compiler namespace ---- + namespace compiler { + function compile( + src: string, + asyncFilters: string[], + extensions: any[], + name: string, + opts?: { throwOnUndefined?: boolean }, + ): string; + + class Compiler { + templateName: string; + codebuf: string[]; + lastId: number; + buffer: string | null; + bufferStack: string[]; + inBlock: boolean; + throwOnUndefined: boolean; + + init(templateName: string, throwOnUndefined?: boolean): void; + compile(node: nodes.Node, frame?: Frame): void; + getCode(): string; + fail(msg: string, lineno?: number, colno?: number): never; + assertType(node: nodes.Node, type: Function): void; + + // Code emission + _emit(code: string): void; + _emitLine(code: string): void; + _emitLines(...lines: string[]): void; + _emitFuncBegin(node: nodes.Node, name: string): void; + _emitFuncEnd(noReturn?: boolean): void; + + // Scope & buffer management + _addScopeLevel(): void; + _tmpid(): string; + _makeCallback(id: string): string; + _pushBuffer(): string; + _popBuffer(): void; + _withScopedSyntax(func: () => void): void; + + // Compilation helpers + _compileExpression(node: nodes.Node, frame: Frame): void; + _compileChildren(node: nodes.Node, frame: Frame): void; + _compileGetTemplate( + node: nodes.Node, + frame: Frame, + eagerCompile: boolean, + ignoreMissing: boolean, + ): string; + + // Methods patched by MarkBind + compileSymbol(node: nodes.Symbol, frame: Frame): void; + compileImport(node: nodes.Import, frame: Frame): void; + compileFromImport(node: nodes.FromImport, frame: Frame): void; + compileRoot(node: nodes.Node, frame: Frame | undefined): void; + _compileMacro(node: nodes.Macro, frame: Frame | undefined): string; + } + } + + // ---- Environment additions (internal properties) ---- + interface Environment { + loaders: Array<{ + cache: Record; + pathsToNames: Record; + noCache: boolean; + async?: boolean; + getSource(name: string, cb?: Function): any; + resolve?(from: string, to: string): string; + }>; + globals: Record; + opts: ConfigureOptions & { dev?: boolean }; + + resolveTemplate( + loader: any, + parentName: string | null, + name: string, + ): string; + + getTemplate( + name: string | Template, + eagerCompile?: boolean | Function, + parentName?: string | null | Function, + ignoreMissing?: boolean | Function, + cb?: (err: Error | null, tmpl?: Template) => void, + ): Template | undefined; + } + + // ---- Template additions (internal properties) ---- + interface Template { + env: Environment; + path: string; + blocks: Record; + rootRenderFunc: ( + env: Environment, + context: any, + frame: Frame, + runtime: typeof import('nunjucks/src/runtime'), + cb: (err: Error | null, res?: string) => void, + ) => void; + + compile(): void; + } +} diff --git a/packages/core/src/patches/nunjucks/nunjucks-submodules.d.ts b/packages/core/src/patches/nunjucks/nunjucks-submodules.d.ts new file mode 100644 index 0000000000..a14967a80c --- /dev/null +++ b/packages/core/src/patches/nunjucks/nunjucks-submodules.d.ts @@ -0,0 +1,123 @@ +/** + * Ambient module declarations for nunjucks internal sub-modules. + * + * These sub-modules (nunjucks/src/runtime, nunjucks/src/object) are not typed + * by @types/nunjucks. This file declares them as ambient external modules + * so they can be imported with type safety. + * + * IMPORTANT: This file must NOT have any top-level import/export statements, + * otherwise the 'declare module' blocks become augmentations instead of + * ambient declarations, and TypeScript will not recognize the sub-modules. + * + * Typed against nunjucks v3.2.4 (only the internals used by the patches). + */ + +// --------------------------------------------------------------------------- +// Sub-module: nunjucks/src/runtime +// --------------------------------------------------------------------------- +declare module 'nunjucks/src/runtime' { + + export class Frame { + variables: Record; + parent: Frame | null | undefined; + topLevel: boolean; + isolateWrites: boolean | undefined; + + /** Set of imported names — added by the MarkBind patch */ + imports?: Set; + + constructor(parent?: Frame, isolateWrites?: boolean); + + /** + * Set a variable in this frame. + * @param name Dot-separated variable name (e.g. "a.b.c") + * @param val Value to set + * @param resolveUp If true, walk up the frame chain and set on the first frame that owns the name + * @param isImport MarkBind patch extension — flags the variable as an import + */ + set(name: string, val: any, resolveUp?: boolean, isImport?: boolean): void; + + /** Get a variable from this frame only (no parent walk). */ + get(name: string): any; + + /** + * Look up a variable by walking the parent chain. + * @param checkIfIsImport MarkBind patch extension — returns undefined for imports + */ + lookup(name: string, checkIfIsImport?: boolean): any; + + /** Resolve which frame owns a variable. */ + resolve(name: string, forWrite?: boolean): Frame | undefined; + + /** Create a child frame. */ + push(isolateWrites?: boolean): Frame; + + /** Return to the parent frame. */ + pop(): Frame | null | undefined; + } + + /** Runtime variable resolution: checks frame chain, then context. */ + export function contextOrFrameLookup(context: any, frame: Frame, name: string): any; + + export function makeMacro( + argNames: string[], + kwargNames: string[], + func: (...args: any[]) => any, + ): (...args: any[]) => any; + + export function makeKeywordArgs(obj: Record): Record; + export function numArgs(args: any[]): number; + export function suppressValue(val: any, autoescape: boolean): string; + export function ensureDefined(val: any, lineno: number, colno: number): any; + export function memberLookup(obj: any, val: any): any; + export function callWrap(obj: any, name: string, context: any, args: any[]): any; + export function handleError(error: any, lineno: number | null, colno: number | null): Error; + export function copySafeness(dest: any, target: any): any; + export function markSafe(val: any): SafeString; + export function asyncEach(arr: any[], dimen: number, iter: Function, cb: Function): void; + export function asyncAll(arr: any[], dimen: number, func: Function, cb: Function): void; + export function fromIterator(arr: any): any[]; + + export const isArray: (obj: any) => obj is any[]; + export const keys: (obj: any) => string[]; + export const inOperator: (key: any, val: any) => boolean; + + export class SafeString extends String { + constructor(val: string); + val: string; + length: number; + valueOf(): string; + toString(): string; + } +} + +// --------------------------------------------------------------------------- +// Sub-module: nunjucks/src/object +// --------------------------------------------------------------------------- +declare module 'nunjucks/src/object' { + export class Obj { + constructor(...args: any[]); + + /** Called by the constructor with all constructor arguments. Override in subclasses. */ + init(...args: any[]): void; + + /** Returns this.constructor.name */ + readonly typename: string; + + /** Create a subclass using nunjucks' custom OOP system. */ + static extend( + this: T, + name: string, + props?: Record, + ): T; + static extend( + this: T, + props: Record, + ): T; + } + + export class EmitterObj extends Obj { + on(name: string, func: (...args: any[]) => void): void; + emit(name: string, ...args: any[]): void; + } +} From 1214b2861131e9682d7a370cfd5ce14f1f0ac514 Mon Sep 17 00:00:00 2001 From: yihao Date: Wed, 4 Mar 2026 17:58:34 +0800 Subject: [PATCH 3/6] Rename core/src/patches to ts --- packages/core/src/patches/{htmlparser2.js => htmlparser2.ts} | 0 packages/core/src/patches/{index.js => index.ts} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/core/src/patches/{htmlparser2.js => htmlparser2.ts} (100%) rename packages/core/src/patches/{index.js => index.ts} (100%) diff --git a/packages/core/src/patches/htmlparser2.js b/packages/core/src/patches/htmlparser2.ts similarity index 100% rename from packages/core/src/patches/htmlparser2.js rename to packages/core/src/patches/htmlparser2.ts diff --git a/packages/core/src/patches/index.js b/packages/core/src/patches/index.ts similarity index 100% rename from packages/core/src/patches/index.js rename to packages/core/src/patches/index.ts From c2d44d69f871644a3bb4972079dd30457a3ced11 Mon Sep 17 00:00:00 2001 From: yihao Date: Wed, 4 Mar 2026 18:01:59 +0800 Subject: [PATCH 4/6] Migrate core/src/patches to ts --- .eslintignore | 2 +- .gitignore | 3 +- .../src/patches/htmlparser2-internal.d.ts | 95 +++++++++++++++++++ packages/core/src/patches/htmlparser2.ts | 52 ++++------ packages/core/src/patches/index.ts | 13 ++- 5 files changed, 119 insertions(+), 46 deletions(-) create mode 100644 packages/core/src/patches/htmlparser2-internal.d.ts diff --git a/.eslintignore b/.eslintignore index 4ecf195e5b..54d3063e00 100644 --- a/.eslintignore +++ b/.eslintignore @@ -20,7 +20,7 @@ packages/core/src/lib/markdown-it/highlight/*.js packages/core/src/lib/markdown-it/plugins/**/*.js packages/core/src/lib/markdown-it/utils/*.js packages/core/src/Page/*.js -packages/core/src/patches/nunjucks/*.js +packages/core/src/patches/**/*.js packages/core/src/plugins/**/*.js packages/core/src/Site/*.js packages/core/src/utils/*.js diff --git a/.gitignore b/.gitignore index 0b7a0fa93a..728c9ebc57 100644 --- a/.gitignore +++ b/.gitignore @@ -109,8 +109,7 @@ packages/core/src/patches/nunjucks/*.js # Manual type definitions need to be included !packages/cli/src/lib/live-server/index.d.ts -!packages/core/src/patches/nunjucks/nunjucks-internals.d.ts -!packages/core/src/patches/nunjucks/nunjucks-submodules.d.ts +!packages/core/src/patches/*.d.ts # Nx for Lerna .nx/cache diff --git a/packages/core/src/patches/htmlparser2-internal.d.ts b/packages/core/src/patches/htmlparser2-internal.d.ts new file mode 100644 index 0000000000..3cfba89f75 --- /dev/null +++ b/packages/core/src/patches/htmlparser2-internal.d.ts @@ -0,0 +1,95 @@ +export { } + +declare module 'htmlparser2' { + interface TokenizerCallbacks { + onattribdata(value: string): void; + onattribend(): void; + onattribname(name: string): void; + oncdata(data: string): void; + oncomment(data: string): void; + ondeclaration(data: string): void; + onend(): void; + onerror(error: Error, state?: number): void; + onopentagend(): void; + onprocessinginstruction(name: string, value: string): void; + onselfclosingtag(): void; + ontext(data: string): void; + } + + export class Tokenizer { + constructor(options: any, cbs: TokenizerCallbacks); + // Internal state + _state: number; + _buffer: string; + _sectionStart: number; + _index: number; + _bufferOffset: number; + _baseState: number; + _special: number; + _cbs: TokenizerCallbacks; + _running: boolean; + _ended: boolean; + _xmlMode: boolean; + _decodeEntities: boolean; + + // MarkBind-added properties (set by patch) + specialTagNames: string[]; + _matchingSpecialTagIndexes: number[]; + _nextSpecialTagMatchIndex: number; + + // Internal helpers + _getSection(): string; + _emitToken(name: string): void; + _cleanup(): void; + + // State handler methods (original htmlparser2 internals) + _stateText(c: string): void; + _stateBeforeTagName(c: string): void; + _stateInTagName(c: string): void; + _stateBeforeCloseingTagName(c: string): void; + _stateInCloseingTagName(c: string): void; + _stateAfterCloseingTagName(c: string): void; + _stateBeforeAttributeName(c: string): void; + _stateInSelfClosingTag(c: string): void; + _stateInAttributeName(c: string): void; + _stateAfterAttributeName(c: string): void; + _stateBeforeAttributeValue(c: string): void; + _stateInAttributeValueDoubleQuotes(c: string): void; + _stateInAttributeValueSingleQuotes(c: string): void; + _stateInAttributeValueNoQuotes(c: string): void; + _stateBeforeDeclaration(c: string): void; + _stateInDeclaration(c: string): void; + _stateInProcessingInstruction(c: string): void; + _stateBeforeComment(c: string): void; + _stateInComment(c: string): void; + _stateAfterComment1(c: string): void; + _stateAfterComment2(c: string): void; + _stateBeforeCdata1(c: string): void; + _stateBeforeCdata2(c: string): void; + _stateBeforeCdata3(c: string): void; + _stateBeforeCdata4(c: string): void; + _stateBeforeCdata5(c: string): void; + _stateBeforeCdata6(c: string): void; + _stateInCdata(c: string): void; + _stateAfterCdata1(c: string): void; + _stateAfterCdata2(c: string): void; + _stateBeforeSpecial(c: string): void; + _stateBeforeSpecialEnd(c: string): void; + _stateBeforeEntity(c: string): void; + _stateBeforeNumericEntity(c: string): void; + _stateInNamedEntity(c: string): void; + _stateInNumericEntity(c: string): void; + _stateInHexEntity(c: string): void; + + // MarkBind-added state handlers (set by patch) + _matchSpecialTagsFirstCharacters(c: string): boolean; + _matchSpecialTagsNextCharacters(c: string): number; + _matchNextSpecialTagClosingCharacter(c: string): number; + _parse(): void; + } + + export interface Parser { + _attribname: string; + _closeCurrentTag(): void; + } +} diff --git a/packages/core/src/patches/htmlparser2.ts b/packages/core/src/patches/htmlparser2.ts index 4e57c316be..803b1dbe9e 100644 --- a/packages/core/src/patches/htmlparser2.ts +++ b/packages/core/src/patches/htmlparser2.ts @@ -6,7 +6,7 @@ * 3. Ability to inject/whitelist certain tags to be parsed like script/style tags do. ('special' tags) */ -const { Tokenizer, Parser } = require('htmlparser2'); +import { Tokenizer, Parser } from 'htmlparser2'; /* Enable any self closing tags '' to be parsed. @@ -23,29 +23,11 @@ Parser.prototype.onselfclosingtag = function () { This is equivalent to the { lowerCaseAttributeNames: false } option of htmlparser2; We modify the relevant code to avoid passing it in repeatedly as well. */ -Parser.prototype.onattribname = function (name) { +Parser.prototype.onattribname = function (name: string) { this._attribname = name; }; -/* eslint-disable - brace-style, - indent, - keyword-spacing, - max-len, - no-mixed-spaces-and-tabs, - no-multi-spaces, - no-plusplus, - no-tabs, - no-unused-vars, - no-var, - one-var, - quotes, - semi, - space-before-blocks, - space-before-function-paren, - spaced-comment, - vars-on-top, -*/ +/* eslint-disable */ var i = 0, @@ -144,7 +126,7 @@ const DEFAULT_SPECIAL_TAGS = [ 'md', ]; -function whitespace(c) { +function whitespace(c: string) { return c === " " || c === "\n" || c === "\t" || c === "\f" || c === "\r"; } @@ -154,7 +136,7 @@ Tokenizer.prototype.specialTagNames = [...DEFAULT_SPECIAL_TAGS]; * Checks whether the token matches one of the first characters of the special tags, * and initialises the _matchingSpecialTagIndexes array with the matches' indexes if so. */ -Tokenizer.prototype._matchSpecialTagsFirstCharacters = function(c) { +Tokenizer.prototype._matchSpecialTagsFirstCharacters = function(c: string) { this._matchingSpecialTagIndexes = []; const numSpecialTags = this.specialTagNames.length; const lowerCaseChar = c.toLowerCase(); @@ -176,7 +158,7 @@ Tokenizer.prototype._matchSpecialTagsFirstCharacters = function(c) { * that do not match the current token. * If one of the previous matches successfully matched, the match index is returned. */ -Tokenizer.prototype._matchSpecialTagsNextCharacters = function(c) { +Tokenizer.prototype._matchSpecialTagsNextCharacters = function(c: string) { const matchingSpecialTags = []; const numMatchingTags = this._matchingSpecialTagIndexes.length; const lowerCaseChar = c.toLowerCase(); @@ -205,7 +187,7 @@ Tokenizer.prototype._matchSpecialTagsNextCharacters = function(c) { * Changes the Tokenizer state to BEFORE_SPECIAL if the token matches one of * the first characters of _specialTagNames. */ -Tokenizer.prototype._stateBeforeTagName = function(c) { +Tokenizer.prototype._stateBeforeTagName = function(c: string) { if (c === "/") { this._state = BEFORE_CLOSING_TAG_NAME; } else if (c === "<") { @@ -232,7 +214,7 @@ Tokenizer.prototype._stateBeforeTagName = function(c) { * Changes the Tokenizer state to IN_TAG_NAME or BEFORE_SPECIAL state again depending * on whether there are still matches in _matchingSpecialTagIndexes. */ -Tokenizer.prototype._stateBeforeSpecial = function(c) { +Tokenizer.prototype._stateBeforeSpecial = function(c: string) { const result = this._matchSpecialTagsNextCharacters(c); if (result === HAS_MATCHING) { this._nextSpecialTagMatchIndex += 1; @@ -261,7 +243,7 @@ Tokenizer.prototype._stateBeforeSpecial = function(c) { * Patched self closing tag state handler that removes the special state * if the special tag was self-closed. */ -Tokenizer.prototype._stateInSelfClosingTag = function(c) { +Tokenizer.prototype._stateInSelfClosingTag = function(c: string) { if (c === ">") { this._cbs.onselfclosingtag(); this._state = TEXT; @@ -284,7 +266,7 @@ Tokenizer.prototype._stateInSelfClosingTag = function(c) { * Processes the _special flag and _nextSpecialTagMatchIndex state variable, * returning a flag indicating whether the current special tag has finished matching or not. */ -Tokenizer.prototype._matchNextSpecialTagClosingCharacter = function(c) { +Tokenizer.prototype._matchNextSpecialTagClosingCharacter = function(c: string) { const nextTestChar = this.specialTagNames[this._special - 1][this._nextSpecialTagMatchIndex]; if (nextTestChar === undefined) { @@ -305,9 +287,10 @@ Tokenizer.prototype._matchNextSpecialTagClosingCharacter = function(c) { * Changes the Tokenizer state to BEFORE_SPECIAL_END if the token matches one of * the first character of the currently matched special tag. */ -Tokenizer.prototype._stateBeforeCloseingTagName = function(c) { - if (whitespace(c)); - else if (c === ">") { +Tokenizer.prototype._stateBeforeCloseingTagName = function(c: string) { + if (whitespace(c)) { + // do nothing, consume whitespace + } else if (c === ">") { this._state = TEXT; } else if (this._special !== SPECIAL_NONE) { if (this._matchNextSpecialTagClosingCharacter(c) !== NO_MATCH) { @@ -327,7 +310,7 @@ Tokenizer.prototype._stateBeforeCloseingTagName = function(c) { * on whether the token has finished or is still matching * the currently matched special tag. */ -Tokenizer.prototype._stateBeforeSpecialEnd = function(c) { +Tokenizer.prototype._stateBeforeSpecialEnd = function(c: string) { const result = this._matchNextSpecialTagClosingCharacter(c); if (result === HAS_MATCHING) { return; @@ -478,10 +461,7 @@ Tokenizer.prototype._parse = function(){ /** * Injects the tagsToIgnore into the Tokenizer's specialTagNames. */ -function injectIgnoreTags(tagsToIgnore) { +export function injectIgnoreTags(tagsToIgnore: string[]) { Tokenizer.prototype.specialTagNames = [...DEFAULT_SPECIAL_TAGS, ...tagsToIgnore]; } -module.exports = { - injectIgnoreTags, -}; diff --git a/packages/core/src/patches/index.ts b/packages/core/src/patches/index.ts index 7f631ad05c..4b1354b29a 100644 --- a/packages/core/src/patches/index.ts +++ b/packages/core/src/patches/index.ts @@ -1,12 +1,11 @@ -const htmlparser2patch = require('./htmlparser2'); -const markdownItCustomComponent - = require('../lib/markdown-it/patches/custom-component/customComponentPlugin'); +import { injectTags } from '../lib/markdown-it/patches/custom-component/customComponentPlugin'; +import { injectIgnoreTags } from './htmlparser2'; -function ignoreTags(tagsToIgnore) { - htmlparser2patch.injectIgnoreTags(tagsToIgnore); - markdownItCustomComponent.injectTags(tagsToIgnore); +function ignoreTags(tagsToIgnore: string[]) { + injectIgnoreTags(tagsToIgnore); + injectTags(tagsToIgnore); } -module.exports = { +export = { ignoreTags, }; From ce9f98071cdf3837a9bca731ee49fc7712e8f3f5 Mon Sep 17 00:00:00 2001 From: yihao Date: Wed, 4 Mar 2026 18:08:21 +0800 Subject: [PATCH 5/6] Rename core/src/lib/markdown-it/patches to TypeScript --- .gitignore | 1 + .../{customComponentPlugin.js => customComponentPlugin.ts} | 0 .../custom-component/{htmlBlockRule.js => htmlBlockRule.ts} | 0 .../custom-component/{htmlInlineRule.js => htmlInlineRule.ts} | 0 .../patches/custom-component/{htmlRe.js => htmlRe.ts} | 0 .../patches/custom-component/{inlineTags.js => inlineTags.ts} | 0 .../{markdown-it-emoji-fixed.js => markdown-it-emoji-fixed.ts} | 0 7 files changed, 1 insertion(+) rename packages/core/src/lib/markdown-it/patches/custom-component/{customComponentPlugin.js => customComponentPlugin.ts} (100%) rename packages/core/src/lib/markdown-it/patches/custom-component/{htmlBlockRule.js => htmlBlockRule.ts} (100%) rename packages/core/src/lib/markdown-it/patches/custom-component/{htmlInlineRule.js => htmlInlineRule.ts} (100%) rename packages/core/src/lib/markdown-it/patches/custom-component/{htmlRe.js => htmlRe.ts} (100%) rename packages/core/src/lib/markdown-it/patches/custom-component/{inlineTags.js => inlineTags.ts} (100%) rename packages/core/src/lib/markdown-it/patches/{markdown-it-emoji-fixed.js => markdown-it-emoji-fixed.ts} (100%) diff --git a/.gitignore b/.gitignore index 728c9ebc57..0d96646131 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,7 @@ packages/core/index.js packages/core/src/lib/progress/*.js packages/core/src/patches/nunjucks/*.js +packages/core/src/lib/markdown-it/patches/custom-component/*.js # --- packages/core end --- # Manual type definitions need to be included diff --git a/packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.js b/packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.ts similarity index 100% rename from packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.js rename to packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.ts diff --git a/packages/core/src/lib/markdown-it/patches/custom-component/htmlBlockRule.js b/packages/core/src/lib/markdown-it/patches/custom-component/htmlBlockRule.ts similarity index 100% rename from packages/core/src/lib/markdown-it/patches/custom-component/htmlBlockRule.js rename to packages/core/src/lib/markdown-it/patches/custom-component/htmlBlockRule.ts diff --git a/packages/core/src/lib/markdown-it/patches/custom-component/htmlInlineRule.js b/packages/core/src/lib/markdown-it/patches/custom-component/htmlInlineRule.ts similarity index 100% rename from packages/core/src/lib/markdown-it/patches/custom-component/htmlInlineRule.js rename to packages/core/src/lib/markdown-it/patches/custom-component/htmlInlineRule.ts diff --git a/packages/core/src/lib/markdown-it/patches/custom-component/htmlRe.js b/packages/core/src/lib/markdown-it/patches/custom-component/htmlRe.ts similarity index 100% rename from packages/core/src/lib/markdown-it/patches/custom-component/htmlRe.js rename to packages/core/src/lib/markdown-it/patches/custom-component/htmlRe.ts diff --git a/packages/core/src/lib/markdown-it/patches/custom-component/inlineTags.js b/packages/core/src/lib/markdown-it/patches/custom-component/inlineTags.ts similarity index 100% rename from packages/core/src/lib/markdown-it/patches/custom-component/inlineTags.js rename to packages/core/src/lib/markdown-it/patches/custom-component/inlineTags.ts diff --git a/packages/core/src/lib/markdown-it/patches/markdown-it-emoji-fixed.js b/packages/core/src/lib/markdown-it/patches/markdown-it-emoji-fixed.ts similarity index 100% rename from packages/core/src/lib/markdown-it/patches/markdown-it-emoji-fixed.js rename to packages/core/src/lib/markdown-it/patches/markdown-it-emoji-fixed.ts From ea62ea3d3f8c1fa6ce11b2ea45453373e063b2bc Mon Sep 17 00:00:00 2001 From: yihao Date: Wed, 4 Mar 2026 18:10:47 +0800 Subject: [PATCH 6/6] Adapt core/src/lib/markdown-it/patches to TypeScript --- .gitignore | 7 ++++--- .../custom-component/customComponentPlugin.ts | 18 +++++++----------- .../patches/custom-component/htmlBlockRule.ts | 15 ++++++++------- .../patches/custom-component/htmlInlineRule.ts | 9 +++++---- .../patches/custom-component/htmlRe.ts | 2 +- .../patches/custom-component/inlineTags.ts | 2 +- .../patches/markdown-it-emoji-fixed.ts | 4 ++-- 7 files changed, 28 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 0d96646131..43545b65e1 100644 --- a/.gitignore +++ b/.gitignore @@ -104,13 +104,14 @@ packages/core/test/unit/**/*.js packages/core/index.js packages/core/src/lib/progress/*.js -packages/core/src/patches/nunjucks/*.js -packages/core/src/lib/markdown-it/patches/custom-component/*.js +packages/core/src/patches/**/*.js +packages/core/src/lib/markdown-it/patches/**/*.js # --- packages/core end --- # Manual type definitions need to be included !packages/cli/src/lib/live-server/index.d.ts -!packages/core/src/patches/*.d.ts +!packages/core/src/patches/*-internal.d.ts +!packages/core/src/patches/*-submodules.d.ts # Nx for Lerna .nx/cache diff --git a/packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.ts b/packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.ts index 5aceabeb35..61e65d0120 100644 --- a/packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.ts +++ b/packages/core/src/lib/markdown-it/patches/custom-component/customComponentPlugin.ts @@ -8,10 +8,10 @@ * ,