From 6df4b0e813b98598d218172d58c3b1f66c10c896 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Tue, 14 May 2024 21:45:22 -0600
Subject: [PATCH 01/14] fix types
---
src/Instance.ts | 4 ++--
src/MarkedOptions.ts | 2 +-
src/Parser.ts | 8 +++-----
src/Renderer.ts | 18 +++++++++++-------
4 files changed, 17 insertions(+), 15 deletions(-)
diff --git a/src/Instance.ts b/src/Instance.ts
index eb460e0642..5fcd9bd61f 100644
--- a/src/Instance.ts
+++ b/src/Instance.ts
@@ -146,11 +146,11 @@ export class Marked {
if (!(prop in renderer)) {
throw new Error(`renderer '${prop}' does not exist`);
}
- if (prop === 'options') {
+ if (['options', 'parser'].includes(prop)) {
// ignore options property
continue;
}
- const rendererProp = prop as Exclude;
+ const rendererProp = prop as Exclude;
const rendererFunc = pack.renderer[rendererProp] as GenericRendererFunction;
const prevRenderer = renderer[rendererProp] as GenericRendererFunction;
// Replace renderer with func to run extension, but fall back if false
diff --git a/src/MarkedOptions.ts b/src/MarkedOptions.ts
index 78754f23fe..6be9d2f5fc 100644
--- a/src/MarkedOptions.ts
+++ b/src/MarkedOptions.ts
@@ -39,7 +39,7 @@ type HooksObject = {
[K in keyof HooksApi]?: (...args: Parameters) => ReturnType | Promise>
};
-type RendererApi = Omit<_Renderer, 'constructor' | 'options'>;
+type RendererApi = Omit<_Renderer, 'constructor' | 'options' | 'parser'>;
type RendererObject = {
[K in keyof RendererApi]?: (...args: Parameters) => ReturnType | false
};
diff --git a/src/Parser.ts b/src/Parser.ts
index d1be35f80f..0a53c08b6a 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -19,6 +19,7 @@ export class _Parser {
this.options.renderer = this.options.renderer || new _Renderer();
this.renderer = this.options.renderer;
this.renderer.options = this.options;
+ this.renderer.parser = this;
this.textRenderer = new _TextRenderer();
}
@@ -75,9 +76,7 @@ export class _Parser {
}
case 'code': {
const codeToken = token as Tokens.Code;
- out += this.renderer.code(codeToken.text,
- codeToken.lang,
- !!codeToken.escaped);
+ out += this.renderer.code(codeToken);
continue;
}
case 'table': {
@@ -113,8 +112,7 @@ export class _Parser {
}
case 'blockquote': {
const blockquoteToken = token as Tokens.Blockquote;
- const body = this.parse(blockquoteToken.tokens);
- out += this.renderer.blockquote(body);
+ out += this.renderer.blockquote(blockquoteToken);
continue;
}
case 'list': {
diff --git a/src/Renderer.ts b/src/Renderer.ts
index e00868c977..59c5a8dd4e 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -4,36 +4,40 @@ import {
escape
} from './helpers.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
+import type { Tokens } from './Tokens.ts';
+import type { _Parser } from './Parser.ts';
/**
* Renderer
*/
export class _Renderer {
options: MarkedOptions;
+ parser!: _Parser; // set by the parser
constructor(options?: MarkedOptions) {
this.options = options || _defaults;
}
- code(code: string, infostring: string | undefined, escaped: boolean): string {
- const lang = (infostring || '').match(/^\S*/)?.[0];
+ code({ text, lang, escaped }: Tokens.Code): string {
+ const langString = (lang || '').match(/^\S*/)?.[0];
- code = code.replace(/\n$/, '') + '\n';
+ const code = text.replace(/\n$/, '') + '\n';
- if (!lang) {
+ if (!langString) {
return ''
+ (escaped ? code : escape(code, true))
+ '
\n';
}
return ''
+ (escaped ? code : escape(code, true))
+ '
\n';
}
- blockquote(quote: string): string {
- return `\n${quote}
\n`;
+ blockquote({ tokens }: Tokens.Blockquote): string {
+ const body = this.parser.parse(tokens);
+ return `\n${body}
\n`;
}
html(html: string, block?: boolean) : string {
From 16798bc8aa6f94dcdb9cb17ba34a0d9e83c89dd1 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Wed, 15 May 2024 00:39:54 -0600
Subject: [PATCH 02/14] test
---
package-lock.json | 459 ++++++++++++++++++---------------------
src/Parser.ts | 87 ++++----
src/Renderer.ts | 38 ++--
src/TextRenderer.ts | 18 +-
src/Tokens.ts | 8 +-
test/unit/marked.test.js | 18 +-
6 files changed, 298 insertions(+), 330 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 5dc85a9040..de6abcf38b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5531,9 +5531,9 @@
}
},
"node_modules/npm": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/npm/-/npm-10.5.0.tgz",
- "integrity": "sha512-Ejxwvfh9YnWVU2yA5FzoYLTW52vxHCz+MHrOFg9Cc8IFgF/6f5AGPAvb5WTay5DIUP1NIfN3VBZ0cLlGO0Ys+A==",
+ "version": "10.7.0",
+ "resolved": "https://registry.npmjs.org/npm/-/npm-10.7.0.tgz",
+ "integrity": "sha512-FXylyYSXNjgXx3l82BT8RSQvCoGIQ3h8YdRFGKNvo3Pv/bKscK4pdWkx/onwTpHDqGw+oeLf4Rxln9WVyxAxlQ==",
"bundleDependencies": [
"@isaacs/string-locale-compare",
"@npmcli/arborist",
@@ -5542,6 +5542,7 @@
"@npmcli/map-workspaces",
"@npmcli/package-json",
"@npmcli/promise-spawn",
+ "@npmcli/redact",
"@npmcli/run-script",
"@sigstore/tuf",
"abbrev",
@@ -5550,8 +5551,6 @@
"chalk",
"ci-info",
"cli-columns",
- "cli-table3",
- "columnify",
"fastest-levenshtein",
"fs-minipass",
"glob",
@@ -5587,7 +5586,6 @@
"npm-profile",
"npm-registry-fetch",
"npm-user-validate",
- "npmlog",
"p-map",
"pacote",
"parse-conflict-json",
@@ -5612,66 +5610,64 @@
"@npmcli/arborist": "^7.2.1",
"@npmcli/config": "^8.0.2",
"@npmcli/fs": "^3.1.0",
- "@npmcli/map-workspaces": "^3.0.4",
- "@npmcli/package-json": "^5.0.0",
+ "@npmcli/map-workspaces": "^3.0.6",
+ "@npmcli/package-json": "^5.1.0",
"@npmcli/promise-spawn": "^7.0.1",
- "@npmcli/run-script": "^7.0.4",
- "@sigstore/tuf": "^2.3.1",
+ "@npmcli/redact": "^2.0.0",
+ "@npmcli/run-script": "^8.1.0",
+ "@sigstore/tuf": "^2.3.2",
"abbrev": "^2.0.0",
"archy": "~1.0.0",
"cacache": "^18.0.2",
"chalk": "^5.3.0",
"ci-info": "^4.0.0",
"cli-columns": "^4.0.0",
- "cli-table3": "^0.6.3",
- "columnify": "^1.6.0",
"fastest-levenshtein": "^1.0.16",
"fs-minipass": "^3.0.3",
- "glob": "^10.3.10",
+ "glob": "^10.3.12",
"graceful-fs": "^4.2.11",
"hosted-git-info": "^7.0.1",
- "ini": "^4.1.1",
- "init-package-json": "^6.0.0",
- "is-cidr": "^5.0.3",
+ "ini": "^4.1.2",
+ "init-package-json": "^6.0.2",
+ "is-cidr": "^5.0.5",
"json-parse-even-better-errors": "^3.0.1",
"libnpmaccess": "^8.0.1",
"libnpmdiff": "^6.0.3",
- "libnpmexec": "^7.0.4",
+ "libnpmexec": "^8.0.0",
"libnpmfund": "^5.0.1",
"libnpmhook": "^10.0.0",
"libnpmorg": "^6.0.1",
- "libnpmpack": "^6.0.3",
+ "libnpmpack": "^7.0.0",
"libnpmpublish": "^9.0.2",
"libnpmsearch": "^7.0.0",
"libnpmteam": "^6.0.0",
- "libnpmversion": "^5.0.1",
- "make-fetch-happen": "^13.0.0",
- "minimatch": "^9.0.3",
+ "libnpmversion": "^6.0.0",
+ "make-fetch-happen": "^13.0.1",
+ "minimatch": "^9.0.4",
"minipass": "^7.0.4",
"minipass-pipeline": "^1.2.4",
"ms": "^2.1.2",
- "node-gyp": "^10.0.1",
+ "node-gyp": "^10.1.0",
"nopt": "^7.2.0",
"normalize-package-data": "^6.0.0",
"npm-audit-report": "^5.0.0",
"npm-install-checks": "^6.3.0",
- "npm-package-arg": "^11.0.1",
+ "npm-package-arg": "^11.0.2",
"npm-pick-manifest": "^9.0.0",
- "npm-profile": "^9.0.0",
- "npm-registry-fetch": "^16.1.0",
+ "npm-profile": "^9.0.2",
+ "npm-registry-fetch": "^17.0.0",
"npm-user-validate": "^2.0.0",
- "npmlog": "^7.0.1",
"p-map": "^4.0.0",
- "pacote": "^17.0.6",
+ "pacote": "^18.0.3",
"parse-conflict-json": "^3.0.1",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.2.0",
"qrcode-terminal": "^0.12.0",
- "read": "^2.1.0",
+ "read": "^3.0.1",
"semver": "^7.6.0",
- "spdx-expression-parse": "^3.0.1",
+ "spdx-expression-parse": "^4.0.0",
"ssri": "^10.0.5",
"supports-color": "^9.4.0",
- "tar": "^6.2.0",
+ "tar": "^6.2.1",
"text-table": "~0.2.0",
"tiny-relative-date": "^1.3.0",
"treeverse": "^3.0.0",
@@ -5699,16 +5695,6 @@
"node": ">=8"
}
},
- "node_modules/npm/node_modules/@colors/colors": {
- "version": "1.5.0",
- "dev": true,
- "inBundle": true,
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.1.90"
- }
- },
"node_modules/npm/node_modules/@isaacs/cliui": {
"version": "8.0.2",
"dev": true,
@@ -5783,7 +5769,7 @@
"license": "ISC"
},
"node_modules/npm/node_modules/@npmcli/agent": {
- "version": "2.2.1",
+ "version": "2.2.2",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -5792,44 +5778,45 @@
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.1",
"lru-cache": "^10.0.1",
- "socks-proxy-agent": "^8.0.1"
+ "socks-proxy-agent": "^8.0.3"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/@npmcli/arborist": {
- "version": "7.4.0",
+ "version": "7.5.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"@isaacs/string-locale-compare": "^1.1.0",
"@npmcli/fs": "^3.1.0",
- "@npmcli/installed-package-contents": "^2.0.2",
+ "@npmcli/installed-package-contents": "^2.1.0",
"@npmcli/map-workspaces": "^3.0.2",
- "@npmcli/metavuln-calculator": "^7.0.0",
+ "@npmcli/metavuln-calculator": "^7.1.0",
"@npmcli/name-from-folder": "^2.0.0",
"@npmcli/node-gyp": "^3.0.0",
- "@npmcli/package-json": "^5.0.0",
+ "@npmcli/package-json": "^5.1.0",
"@npmcli/query": "^3.1.0",
- "@npmcli/run-script": "^7.0.2",
+ "@npmcli/redact": "^2.0.0",
+ "@npmcli/run-script": "^8.1.0",
"bin-links": "^4.0.1",
"cacache": "^18.0.0",
"common-ancestor-path": "^1.0.1",
"hosted-git-info": "^7.0.1",
"json-parse-even-better-errors": "^3.0.0",
"json-stringify-nice": "^1.1.4",
- "minimatch": "^9.0.0",
+ "minimatch": "^9.0.4",
"nopt": "^7.0.0",
"npm-install-checks": "^6.2.0",
- "npm-package-arg": "^11.0.1",
+ "npm-package-arg": "^11.0.2",
"npm-pick-manifest": "^9.0.0",
- "npm-registry-fetch": "^16.0.0",
- "npmlog": "^7.0.1",
- "pacote": "^17.0.4",
+ "npm-registry-fetch": "^17.0.0",
+ "pacote": "^18.0.1",
"parse-conflict-json": "^3.0.0",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.2.0",
+ "proggy": "^2.0.0",
"promise-all-reject-late": "^1.0.0",
"promise-call-limit": "^3.0.1",
"read-package-json-fast": "^3.0.2",
@@ -5846,16 +5833,16 @@
}
},
"node_modules/npm/node_modules/@npmcli/config": {
- "version": "8.2.0",
+ "version": "8.3.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/map-workspaces": "^3.0.2",
"ci-info": "^4.0.0",
- "ini": "^4.1.0",
+ "ini": "^4.1.2",
"nopt": "^7.0.0",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.2.0",
"read-package-json-fast": "^3.0.2",
"semver": "^7.3.5",
"walk-up-path": "^3.0.1"
@@ -5867,7 +5854,6 @@
"node_modules/npm/node_modules/@npmcli/disparity-colors": {
"version": "3.0.0",
"dev": true,
- "inBundle": true,
"license": "ISC",
"dependencies": {
"ansi-styles": "^4.3.0"
@@ -5879,7 +5865,6 @@
"node_modules/npm/node_modules/@npmcli/disparity-colors/node_modules/ansi-styles": {
"version": "4.3.0",
"dev": true,
- "inBundle": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
@@ -5904,7 +5889,7 @@
}
},
"node_modules/npm/node_modules/@npmcli/git": {
- "version": "5.0.4",
+ "version": "5.0.6",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -5912,7 +5897,7 @@
"@npmcli/promise-spawn": "^7.0.0",
"lru-cache": "^10.0.1",
"npm-pick-manifest": "^9.0.0",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.0.0",
"promise-inflight": "^1.0.1",
"promise-retry": "^2.0.1",
"semver": "^7.3.5",
@@ -5923,7 +5908,7 @@
}
},
"node_modules/npm/node_modules/@npmcli/installed-package-contents": {
- "version": "2.0.2",
+ "version": "2.1.0",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -5932,14 +5917,14 @@
"npm-normalize-package-bin": "^3.0.0"
},
"bin": {
- "installed-package-contents": "lib/index.js"
+ "installed-package-contents": "bin/index.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/@npmcli/map-workspaces": {
- "version": "3.0.4",
+ "version": "3.0.6",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -5954,14 +5939,15 @@
}
},
"node_modules/npm/node_modules/@npmcli/metavuln-calculator": {
- "version": "7.0.0",
+ "version": "7.1.0",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"cacache": "^18.0.0",
"json-parse-even-better-errors": "^3.0.0",
- "pacote": "^17.0.0",
+ "pacote": "^18.0.0",
+ "proc-log": "^4.1.0",
"semver": "^7.3.5"
},
"engines": {
@@ -5987,7 +5973,7 @@
}
},
"node_modules/npm/node_modules/@npmcli/package-json": {
- "version": "5.0.0",
+ "version": "5.1.0",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -5997,7 +5983,7 @@
"hosted-git-info": "^7.0.0",
"json-parse-even-better-errors": "^3.0.0",
"normalize-package-data": "^6.0.0",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.0.0",
"semver": "^7.5.3"
},
"engines": {
@@ -6028,8 +6014,17 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/npm/node_modules/@npmcli/redact": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
"node_modules/npm/node_modules/@npmcli/run-script": {
- "version": "7.0.4",
+ "version": "8.1.0",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -6038,6 +6033,7 @@
"@npmcli/package-json": "^5.0.0",
"@npmcli/promise-spawn": "^7.0.0",
"node-gyp": "^10.0.0",
+ "proc-log": "^4.0.0",
"which": "^4.0.0"
},
"engines": {
@@ -6055,19 +6051,19 @@
}
},
"node_modules/npm/node_modules/@sigstore/bundle": {
- "version": "2.2.0",
+ "version": "2.3.1",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
- "@sigstore/protobuf-specs": "^0.3.0"
+ "@sigstore/protobuf-specs": "^0.3.1"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/@sigstore/core": {
- "version": "1.0.0",
+ "version": "1.1.0",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
@@ -6076,23 +6072,23 @@
}
},
"node_modules/npm/node_modules/@sigstore/protobuf-specs": {
- "version": "0.3.0",
+ "version": "0.3.1",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
"engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ "node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/@sigstore/sign": {
- "version": "2.2.3",
+ "version": "2.3.0",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
- "@sigstore/bundle": "^2.2.0",
+ "@sigstore/bundle": "^2.3.0",
"@sigstore/core": "^1.0.0",
- "@sigstore/protobuf-specs": "^0.3.0",
+ "@sigstore/protobuf-specs": "^0.3.1",
"make-fetch-happen": "^13.0.0"
},
"engines": {
@@ -6100,7 +6096,7 @@
}
},
"node_modules/npm/node_modules/@sigstore/tuf": {
- "version": "2.3.1",
+ "version": "2.3.2",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
@@ -6113,14 +6109,14 @@
}
},
"node_modules/npm/node_modules/@sigstore/verify": {
- "version": "1.1.0",
+ "version": "1.2.0",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
- "@sigstore/bundle": "^2.2.0",
- "@sigstore/core": "^1.0.0",
- "@sigstore/protobuf-specs": "^0.3.0"
+ "@sigstore/bundle": "^2.3.1",
+ "@sigstore/core": "^1.1.0",
+ "@sigstore/protobuf-specs": "^0.3.1"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
@@ -6158,7 +6154,7 @@
}
},
"node_modules/npm/node_modules/agent-base": {
- "version": "7.1.0",
+ "version": "7.1.1",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -6218,7 +6214,6 @@
"node_modules/npm/node_modules/are-we-there-yet": {
"version": "4.0.2",
"dev": true,
- "inBundle": true,
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
@@ -6246,12 +6241,15 @@
}
},
"node_modules/npm/node_modules/binary-extensions": {
- "version": "2.2.0",
+ "version": "2.3.0",
"dev": true,
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/npm/node_modules/brace-expansion": {
@@ -6264,7 +6262,7 @@
}
},
"node_modules/npm/node_modules/builtins": {
- "version": "5.0.1",
+ "version": "5.1.0",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -6332,7 +6330,7 @@
}
},
"node_modules/npm/node_modules/cidr-regex": {
- "version": "4.0.3",
+ "version": "4.0.5",
"dev": true,
"inBundle": true,
"license": "BSD-2-Clause",
@@ -6365,30 +6363,6 @@
"node": ">= 10"
}
},
- "node_modules/npm/node_modules/cli-table3": {
- "version": "0.6.3",
- "dev": true,
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": "10.* || >= 12.*"
- },
- "optionalDependencies": {
- "@colors/colors": "1.5.0"
- }
- },
- "node_modules/npm/node_modules/clone": {
- "version": "1.0.4",
- "dev": true,
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8"
- }
- },
"node_modules/npm/node_modules/cmd-shim": {
"version": "6.0.2",
"dev": true,
@@ -6419,25 +6393,11 @@
"node_modules/npm/node_modules/color-support": {
"version": "1.1.3",
"dev": true,
- "inBundle": true,
"license": "ISC",
"bin": {
"color-support": "bin.js"
}
},
- "node_modules/npm/node_modules/columnify": {
- "version": "1.6.0",
- "dev": true,
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "strip-ansi": "^6.0.1",
- "wcwidth": "^1.0.0"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
"node_modules/npm/node_modules/common-ancestor-path": {
"version": "1.0.1",
"dev": true,
@@ -6447,7 +6407,6 @@
"node_modules/npm/node_modules/console-control-strings": {
"version": "1.1.0",
"dev": true,
- "inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/cross-spawn": {
@@ -6514,18 +6473,6 @@
"inBundle": true,
"license": "MIT"
},
- "node_modules/npm/node_modules/defaults": {
- "version": "1.0.4",
- "dev": true,
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "clone": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/npm/node_modules/diff": {
"version": "5.2.0",
"dev": true,
@@ -6627,7 +6574,6 @@
"node_modules/npm/node_modules/gauge": {
"version": "5.0.1",
"dev": true,
- "inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^1.0.3 || ^2.0.0",
@@ -6644,16 +6590,16 @@
}
},
"node_modules/npm/node_modules/glob": {
- "version": "10.3.10",
+ "version": "10.3.12",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
- "jackspeak": "^2.3.5",
+ "jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
- "path-scurry": "^1.10.1"
+ "minipass": "^7.0.4",
+ "path-scurry": "^1.10.2"
},
"bin": {
"glob": "dist/esm/bin.mjs"
@@ -6674,11 +6620,10 @@
"node_modules/npm/node_modules/has-unicode": {
"version": "2.0.1",
"dev": true,
- "inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/hasown": {
- "version": "2.0.1",
+ "version": "2.0.2",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -6777,7 +6722,7 @@
}
},
"node_modules/npm/node_modules/ini": {
- "version": "4.1.1",
+ "version": "4.1.2",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -6786,15 +6731,15 @@
}
},
"node_modules/npm/node_modules/init-package-json": {
- "version": "6.0.0",
+ "version": "6.0.2",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
+ "@npmcli/package-json": "^5.0.0",
"npm-package-arg": "^11.0.0",
"promzard": "^1.0.0",
- "read": "^2.0.0",
- "read-package-json": "^7.0.0",
+ "read": "^3.0.1",
"semver": "^7.3.5",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "^5.0.0"
@@ -6816,12 +6761,6 @@
"node": ">= 12"
}
},
- "node_modules/npm/node_modules/ip-address/node_modules/sprintf-js": {
- "version": "1.1.3",
- "dev": true,
- "inBundle": true,
- "license": "BSD-3-Clause"
- },
"node_modules/npm/node_modules/ip-regex": {
"version": "5.0.0",
"dev": true,
@@ -6835,12 +6774,12 @@
}
},
"node_modules/npm/node_modules/is-cidr": {
- "version": "5.0.3",
+ "version": "5.0.5",
"dev": true,
"inBundle": true,
"license": "BSD-2-Clause",
"dependencies": {
- "cidr-regex": "4.0.3"
+ "cidr-regex": "^4.0.4"
},
"engines": {
"node": ">=14"
@@ -6943,52 +6882,50 @@
"license": "MIT"
},
"node_modules/npm/node_modules/libnpmaccess": {
- "version": "8.0.2",
+ "version": "8.0.5",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
- "npm-package-arg": "^11.0.1",
- "npm-registry-fetch": "^16.0.0"
+ "npm-package-arg": "^11.0.2",
+ "npm-registry-fetch": "^17.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmdiff": {
- "version": "6.0.7",
+ "version": "6.1.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^7.2.1",
- "@npmcli/disparity-colors": "^3.0.0",
- "@npmcli/installed-package-contents": "^2.0.2",
- "binary-extensions": "^2.2.0",
+ "@npmcli/installed-package-contents": "^2.1.0",
+ "binary-extensions": "^2.3.0",
"diff": "^5.1.0",
- "minimatch": "^9.0.0",
- "npm-package-arg": "^11.0.1",
- "pacote": "^17.0.4",
- "tar": "^6.2.0"
+ "minimatch": "^9.0.4",
+ "npm-package-arg": "^11.0.2",
+ "pacote": "^18.0.1",
+ "tar": "^6.2.1"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmexec": {
- "version": "7.0.8",
+ "version": "8.1.0",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^7.2.1",
- "@npmcli/run-script": "^7.0.2",
+ "@npmcli/run-script": "^8.1.0",
"ci-info": "^4.0.0",
- "npm-package-arg": "^11.0.1",
- "npmlog": "^7.0.1",
- "pacote": "^17.0.4",
- "proc-log": "^3.0.0",
- "read": "^2.0.0",
+ "npm-package-arg": "^11.0.2",
+ "pacote": "^18.0.1",
+ "proc-log": "^4.2.0",
+ "read": "^3.0.1",
"read-package-json-fast": "^3.0.2",
"semver": "^7.3.7",
"walk-up-path": "^3.0.1"
@@ -6998,7 +6935,7 @@
}
},
"node_modules/npm/node_modules/libnpmfund": {
- "version": "5.0.5",
+ "version": "5.0.9",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -7010,57 +6947,57 @@
}
},
"node_modules/npm/node_modules/libnpmhook": {
- "version": "10.0.1",
+ "version": "10.0.4",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
- "npm-registry-fetch": "^16.0.0"
+ "npm-registry-fetch": "^17.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmorg": {
- "version": "6.0.2",
+ "version": "6.0.5",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
- "npm-registry-fetch": "^16.0.0"
+ "npm-registry-fetch": "^17.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmpack": {
- "version": "6.0.7",
+ "version": "7.0.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/arborist": "^7.2.1",
- "@npmcli/run-script": "^7.0.2",
- "npm-package-arg": "^11.0.1",
- "pacote": "^17.0.4"
+ "@npmcli/run-script": "^8.1.0",
+ "npm-package-arg": "^11.0.2",
+ "pacote": "^18.0.1"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmpublish": {
- "version": "9.0.4",
+ "version": "9.0.7",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"ci-info": "^4.0.0",
"normalize-package-data": "^6.0.0",
- "npm-package-arg": "^11.0.1",
- "npm-registry-fetch": "^16.0.0",
- "proc-log": "^3.0.0",
+ "npm-package-arg": "^11.0.2",
+ "npm-registry-fetch": "^17.0.0",
+ "proc-log": "^4.2.0",
"semver": "^7.3.7",
"sigstore": "^2.2.0",
"ssri": "^10.0.5"
@@ -7070,40 +7007,40 @@
}
},
"node_modules/npm/node_modules/libnpmsearch": {
- "version": "7.0.1",
+ "version": "7.0.4",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
- "npm-registry-fetch": "^16.0.0"
+ "npm-registry-fetch": "^17.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmteam": {
- "version": "6.0.1",
+ "version": "6.0.4",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"aproba": "^2.0.0",
- "npm-registry-fetch": "^16.0.0"
+ "npm-registry-fetch": "^17.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/libnpmversion": {
- "version": "5.0.2",
+ "version": "6.0.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
- "@npmcli/git": "^5.0.3",
- "@npmcli/run-script": "^7.0.2",
+ "@npmcli/git": "^5.0.6",
+ "@npmcli/run-script": "^8.1.0",
"json-parse-even-better-errors": "^3.0.0",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.2.0",
"semver": "^7.3.7"
},
"engines": {
@@ -7111,7 +7048,7 @@
}
},
"node_modules/npm/node_modules/lru-cache": {
- "version": "10.2.0",
+ "version": "10.2.2",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -7120,7 +7057,7 @@
}
},
"node_modules/npm/node_modules/make-fetch-happen": {
- "version": "13.0.0",
+ "version": "13.0.1",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -7134,6 +7071,7 @@
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"negotiator": "^0.6.3",
+ "proc-log": "^4.2.0",
"promise-retry": "^2.0.1",
"ssri": "^10.0.0"
},
@@ -7142,7 +7080,7 @@
}
},
"node_modules/npm/node_modules/minimatch": {
- "version": "9.0.3",
+ "version": "9.0.4",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -7350,7 +7288,7 @@
}
},
"node_modules/npm/node_modules/node-gyp": {
- "version": "10.0.1",
+ "version": "10.1.0",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -7373,6 +7311,15 @@
"node": "^16.14.0 || >=18.0.0"
}
},
+ "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/npm/node_modules/nopt": {
"version": "7.2.0",
"dev": true,
@@ -7446,13 +7393,13 @@
}
},
"node_modules/npm/node_modules/npm-package-arg": {
- "version": "11.0.1",
+ "version": "11.0.2",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"hosted-git-info": "^7.0.0",
- "proc-log": "^3.0.0",
+ "proc-log": "^4.0.0",
"semver": "^7.3.5",
"validate-npm-package-name": "^5.0.0"
},
@@ -7488,31 +7435,32 @@
}
},
"node_modules/npm/node_modules/npm-profile": {
- "version": "9.0.0",
+ "version": "9.0.2",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
- "npm-registry-fetch": "^16.0.0",
- "proc-log": "^3.0.0"
+ "npm-registry-fetch": "^17.0.0",
+ "proc-log": "^4.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/npm/node_modules/npm-registry-fetch": {
- "version": "16.1.0",
+ "version": "17.0.0",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
+ "@npmcli/redact": "^2.0.0",
"make-fetch-happen": "^13.0.0",
"minipass": "^7.0.2",
"minipass-fetch": "^3.0.0",
"minipass-json-stream": "^1.0.1",
"minizlib": "^2.1.2",
"npm-package-arg": "^11.0.0",
- "proc-log": "^3.0.0"
+ "proc-log": "^4.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
@@ -7530,7 +7478,6 @@
"node_modules/npm/node_modules/npmlog": {
"version": "7.0.1",
"dev": true,
- "inBundle": true,
"license": "ISC",
"dependencies": {
"are-we-there-yet": "^4.0.0",
@@ -7558,26 +7505,25 @@
}
},
"node_modules/npm/node_modules/pacote": {
- "version": "17.0.6",
+ "version": "18.0.3",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
"@npmcli/git": "^5.0.0",
"@npmcli/installed-package-contents": "^2.0.1",
+ "@npmcli/package-json": "^5.1.0",
"@npmcli/promise-spawn": "^7.0.0",
- "@npmcli/run-script": "^7.0.0",
+ "@npmcli/run-script": "^8.0.0",
"cacache": "^18.0.0",
"fs-minipass": "^3.0.0",
"minipass": "^7.0.2",
"npm-package-arg": "^11.0.0",
"npm-packlist": "^8.0.0",
"npm-pick-manifest": "^9.0.0",
- "npm-registry-fetch": "^16.0.0",
- "proc-log": "^3.0.0",
+ "npm-registry-fetch": "^17.0.0",
+ "proc-log": "^4.0.0",
"promise-retry": "^2.0.1",
- "read-package-json": "^7.0.0",
- "read-package-json-fast": "^3.0.0",
"sigstore": "^2.2.0",
"ssri": "^10.0.0",
"tar": "^6.1.11"
@@ -7613,12 +7559,12 @@
}
},
"node_modules/npm/node_modules/path-scurry": {
- "version": "1.10.1",
+ "version": "1.10.2",
"dev": true,
"inBundle": true,
"license": "BlueOak-1.0.0",
"dependencies": {
- "lru-cache": "^9.1.1 || ^10.0.0",
+ "lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
@@ -7629,7 +7575,7 @@
}
},
"node_modules/npm/node_modules/postcss-selector-parser": {
- "version": "6.0.15",
+ "version": "6.0.16",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -7642,7 +7588,16 @@
}
},
"node_modules/npm/node_modules/proc-log": {
- "version": "3.0.0",
+ "version": "4.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm/node_modules/proggy": {
+ "version": "2.0.0",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -7688,12 +7643,12 @@
}
},
"node_modules/npm/node_modules/promzard": {
- "version": "1.0.0",
+ "version": "1.0.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
- "read": "^2.0.0"
+ "read": "^3.0.1"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
@@ -7708,12 +7663,12 @@
}
},
"node_modules/npm/node_modules/read": {
- "version": "2.1.0",
+ "version": "3.0.1",
"dev": true,
"inBundle": true,
"license": "ISC",
"dependencies": {
- "mute-stream": "~1.0.0"
+ "mute-stream": "^1.0.0"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
@@ -7731,7 +7686,6 @@
"node_modules/npm/node_modules/read-package-json": {
"version": "7.0.0",
"dev": true,
- "inBundle": true,
"license": "ISC",
"dependencies": {
"glob": "^10.2.2",
@@ -7802,7 +7756,6 @@
"node_modules/npm/node_modules/set-blocking": {
"version": "2.0.0",
"dev": true,
- "inBundle": true,
"license": "ISC"
},
"node_modules/npm/node_modules/shebang-command": {
@@ -7839,17 +7792,17 @@
}
},
"node_modules/npm/node_modules/sigstore": {
- "version": "2.2.2",
+ "version": "2.3.0",
"dev": true,
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
- "@sigstore/bundle": "^2.2.0",
+ "@sigstore/bundle": "^2.3.1",
"@sigstore/core": "^1.0.0",
- "@sigstore/protobuf-specs": "^0.3.0",
- "@sigstore/sign": "^2.2.3",
+ "@sigstore/protobuf-specs": "^0.3.1",
+ "@sigstore/sign": "^2.3.0",
"@sigstore/tuf": "^2.3.1",
- "@sigstore/verify": "^1.1.0"
+ "@sigstore/verify": "^1.2.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
@@ -7866,7 +7819,7 @@
}
},
"node_modules/npm/node_modules/socks": {
- "version": "2.8.0",
+ "version": "2.8.3",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -7875,17 +7828,17 @@
"smart-buffer": "^4.2.0"
},
"engines": {
- "node": ">= 16.0.0",
+ "node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/npm/node_modules/socks-proxy-agent": {
- "version": "8.0.2",
+ "version": "8.0.3",
"dev": true,
"inBundle": true,
"license": "MIT",
"dependencies": {
- "agent-base": "^7.0.2",
+ "agent-base": "^7.1.1",
"debug": "^4.3.4",
"socks": "^2.7.1"
},
@@ -7903,6 +7856,16 @@
"spdx-license-ids": "^3.0.0"
}
},
+ "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
"node_modules/npm/node_modules/spdx-exceptions": {
"version": "2.5.0",
"dev": true,
@@ -7910,7 +7873,7 @@
"license": "CC-BY-3.0"
},
"node_modules/npm/node_modules/spdx-expression-parse": {
- "version": "3.0.1",
+ "version": "4.0.0",
"dev": true,
"inBundle": true,
"license": "MIT",
@@ -7925,6 +7888,12 @@
"inBundle": true,
"license": "CC0-1.0"
},
+ "node_modules/npm/node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/npm/node_modules/ssri": {
"version": "10.0.5",
"dev": true,
@@ -8004,7 +7973,7 @@
}
},
"node_modules/npm/node_modules/tar": {
- "version": "6.2.0",
+ "version": "6.2.1",
"dev": true,
"inBundle": true,
"license": "ISC",
@@ -8128,6 +8097,16 @@
"spdx-expression-parse": "^3.0.0"
}
},
+ "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
"node_modules/npm/node_modules/validate-npm-package-name": {
"version": "5.0.0",
"dev": true,
@@ -8146,15 +8125,6 @@
"inBundle": true,
"license": "ISC"
},
- "node_modules/npm/node_modules/wcwidth": {
- "version": "1.0.1",
- "dev": true,
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "defaults": "^1.0.3"
- }
- },
"node_modules/npm/node_modules/which": {
"version": "4.0.0",
"dev": true,
@@ -8182,7 +8152,6 @@
"node_modules/npm/node_modules/wide-align": {
"version": "1.1.5",
"dev": true,
- "inBundle": true,
"license": "ISC",
"dependencies": {
"string-width": "^1.0.2 || 2 || 3 || 4"
diff --git a/src/Parser.ts b/src/Parser.ts
index 0a53c08b6a..e7d524ce03 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -1,10 +1,7 @@
import { _Renderer } from './Renderer.ts';
import { _TextRenderer } from './TextRenderer.ts';
import { _defaults } from './defaults.ts';
-import {
- unescape
-} from './helpers.ts';
-import type { Token, Tokens } from './Tokens.ts';
+import type { TokenWithoutGeneric, Token, Tokens } from './Tokens.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
/**
@@ -46,11 +43,11 @@ export class _Parser {
let out = '';
for (let i = 0; i < tokens.length; i++) {
- const token = tokens[i];
+ const anyToken = tokens[i];
// Run any renderer extensions
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
- const genericToken = token as Tokens.Generic;
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
+ const genericToken = anyToken as Tokens.Generic;
const ret = this.options.extensions.renderers[genericToken.type].call({ parser: this }, genericToken);
if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
out += ret || '';
@@ -58,25 +55,22 @@ export class _Parser {
}
}
+ const token = anyToken as TokenWithoutGeneric;
+
switch (token.type) {
case 'space': {
continue;
}
case 'hr': {
- out += this.renderer.hr();
+ out += this.renderer.hr(token);
continue;
}
case 'heading': {
- const headingToken = token as Tokens.Heading;
- out += this.renderer.heading(
- this.parseInline(headingToken.tokens),
- headingToken.depth,
- unescape(this.parseInline(headingToken.tokens, this.textRenderer)));
+ out += this.renderer.heading(token);
continue;
}
case 'code': {
- const codeToken = token as Tokens.Code;
- out += this.renderer.code(codeToken);
+ out += this.renderer.code(token);
continue;
}
case 'table': {
@@ -111,8 +105,7 @@ export class _Parser {
continue;
}
case 'blockquote': {
- const blockquoteToken = token as Tokens.Blockquote;
- out += this.renderer.blockquote(blockquoteToken);
+ out += this.renderer.blockquote(token);
continue;
}
case 'list': {
@@ -155,23 +148,30 @@ export class _Parser {
continue;
}
case 'html': {
- const htmlToken = token as Tokens.HTML;
- out += this.renderer.html(htmlToken.text, htmlToken.block);
+ out += this.renderer.html(token);
continue;
}
case 'paragraph': {
- const paragraphToken = token as Tokens.Paragraph;
- out += this.renderer.paragraph(this.parseInline(paragraphToken.tokens));
+ out += this.renderer.paragraph(token);
continue;
}
case 'text': {
- let textToken = token as Tokens.Text;
- let body = textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
+ let textToken = token;
+ let body = 'tokens' in textToken && textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
textToken = tokens[++i] as Tokens.Text;
body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);
}
- out += top ? this.renderer.paragraph(body) : body;
+ if (top) {
+ out += this.renderer.paragraph({
+ type: 'paragraph',
+ raw: body,
+ text: body,
+ tokens: [{ type: 'text', raw: body, text: body }]
+ });
+ } else {
+ out += body;
+ }
continue;
}
@@ -198,65 +198,58 @@ export class _Parser {
let out = '';
for (let i = 0; i < tokens.length; i++) {
- const token = tokens[i];
+ const anyToken = tokens[i];
// Run any renderer extensions
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[token.type]) {
- const ret = this.options.extensions.renderers[token.type].call({ parser: this }, token);
- if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(token.type)) {
+ if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
+ const ret = this.options.extensions.renderers[anyToken.type].call({ parser: this }, anyToken);
+ if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(anyToken.type)) {
out += ret || '';
continue;
}
}
+ const token = anyToken as TokenWithoutGeneric;
+
switch (token.type) {
case 'escape': {
- const escapeToken = token as Tokens.Escape;
- out += renderer.text(escapeToken.text);
+ out += renderer.text(token);
break;
}
case 'html': {
- const tagToken = token as Tokens.Tag;
- out += renderer.html(tagToken.text);
+ out += renderer.html(token);
break;
}
case 'link': {
- const linkToken = token as Tokens.Link;
- out += renderer.link(linkToken.href, linkToken.title, this.parseInline(linkToken.tokens, renderer));
+ out += renderer.link(token);
break;
}
case 'image': {
- const imageToken = token as Tokens.Image;
- out += renderer.image(imageToken.href, imageToken.title, imageToken.text);
+ out += renderer.image(token);
break;
}
case 'strong': {
- const strongToken = token as Tokens.Strong;
- out += renderer.strong(this.parseInline(strongToken.tokens, renderer));
+ out += renderer.strong(token);
break;
}
case 'em': {
- const emToken = token as Tokens.Em;
- out += renderer.em(this.parseInline(emToken.tokens, renderer));
+ out += renderer.em(token);
break;
}
case 'codespan': {
- const codespanToken = token as Tokens.Codespan;
- out += renderer.codespan(codespanToken.text);
+ out += renderer.codespan(token);
break;
}
case 'br': {
- out += renderer.br();
+ out += renderer.br(token);
break;
}
case 'del': {
- const delToken = token as Tokens.Del;
- out += renderer.del(this.parseInline(delToken.tokens, renderer));
+ out += renderer.del(token);
break;
}
case 'text': {
- const textToken = token as Tokens.Text;
- out += renderer.text(textToken.text);
+ out += renderer.text(token);
break;
}
default: {
diff --git a/src/Renderer.ts b/src/Renderer.ts
index 59c5a8dd4e..17e49c4d0c 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -40,16 +40,15 @@ export class _Renderer {
return `\n${body}
\n`;
}
- html(html: string, block?: boolean) : string {
- return html;
+ html({ text }: Tokens.HTML | Tokens.Tag) : string {
+ return text;
}
- heading(text: string, level: number, raw: string): string {
- // ignore IDs
- return `${text}\n`;
+ heading({ tokens, depth }: Tokens.Heading): string {
+ return `${this.parser.parseInline(tokens)}\n`;
}
- hr(): string {
+ hr(token: Tokens.Hr): string {
return '
\n';
}
@@ -69,8 +68,8 @@ export class _Renderer {
+ 'disabled="" type="checkbox">';
}
- paragraph(text: string): string {
- return `${text}
\n`;
+ paragraph({ tokens }: Tokens.Paragraph): string {
+ return `${this.parser.parseInline(tokens)}
\n`;
}
table(header: string, body: string): string {
@@ -102,27 +101,28 @@ export class _Renderer {
/**
* span level renderer
*/
- strong(text: string): string {
- return `${text}`;
+ strong({ tokens }: Tokens.Strong): string {
+ return `${this.parser.parseInline(tokens)}`;
}
- em(text: string): string {
- return `${text}`;
+ em({ tokens }: Tokens.Em): string {
+ return `${this.parser.parseInline(tokens)}`;
}
- codespan(text: string): string {
+ codespan({ text }: Tokens.Codespan): string {
return `${text}
`;
}
- br(): string {
+ br(token: Tokens.Br): string {
return '
';
}
- del(text: string): string {
- return `${text}`;
+ del({ tokens }: Tokens.Del): string {
+ return `${this.parser.parseInline(tokens)}`;
}
- link(href: string, title: string | null | undefined, text: string): string {
+ link({ href, title, tokens }: Tokens.Link): string {
+ const text = this.parser.parseInline(tokens);
const cleanHref = cleanUrl(href);
if (cleanHref === null) {
return text;
@@ -136,7 +136,7 @@ export class _Renderer {
return out;
}
- image(href: string, title: string | null, text: string): string {
+ image({ href, title, text }: Tokens.Image): string {
const cleanHref = cleanUrl(href);
if (cleanHref === null) {
return text;
@@ -151,7 +151,7 @@ export class _Renderer {
return out;
}
- text(text: string) : string {
+ text({ text }: Tokens.Text | Tokens.Escape | Tokens.Tag) : string {
return text;
}
}
diff --git a/src/TextRenderer.ts b/src/TextRenderer.ts
index 038b6db031..a83b754811 100644
--- a/src/TextRenderer.ts
+++ b/src/TextRenderer.ts
@@ -1,38 +1,40 @@
+import type { Tokens } from './Tokens.ts';
+
/**
* TextRenderer
* returns only the textual part of the token
*/
export class _TextRenderer {
// no need for block level renderers
- strong(text: string) {
+ strong({ text }: Tokens.Strong) {
return text;
}
- em(text: string) {
+ em({ text }: Tokens.Em) {
return text;
}
- codespan(text: string) {
+ codespan({ text }: Tokens.Codespan) {
return text;
}
- del(text: string) {
+ del({ text }: Tokens.Del) {
return text;
}
- html(text: string) {
+ html({ text }: Tokens.HTML | Tokens.Tag) {
return text;
}
- text(text: string) {
+ text({ text }: Tokens.Text | Tokens.Escape | Tokens.Tag) {
return text;
}
- link(href: string, title: string | null | undefined, text: string) {
+ link({ text }: Tokens.Link) {
return '' + text;
}
- image(href: string, title: string | null, text: string) {
+ image({ text }: Tokens.Image) {
return '' + text;
}
diff --git a/src/Tokens.ts b/src/Tokens.ts
index c5c846a557..fecafc8a2a 100644
--- a/src/Tokens.ts
+++ b/src/Tokens.ts
@@ -1,5 +1,6 @@
/* eslint-disable no-use-before-define */
-export type Token = (
+
+export type TokenWithoutGeneric = (
Tokens.Space
| Tokens.Code
| Tokens.Heading
@@ -20,7 +21,10 @@ export type Token = (
| Tokens.Em
| Tokens.Codespan
| Tokens.Br
- | Tokens.Del
+ | Tokens.Del);
+
+export type Token = (
+ TokenWithoutGeneric
| Tokens.Generic);
export namespace Tokens {
diff --git a/test/unit/marked.test.js b/test/unit/marked.test.js
index c9c0925a12..7cfe2d6928 100644
--- a/test/unit/marked.test.js
+++ b/test/unit/marked.test.js
@@ -38,7 +38,7 @@ describe('marked unit', () => {
const md = 'HTML Image: ';
marked.parse(md, { renderer });
- assert.strictEqual(renderer.html.mock.calls[0].arguments[0], '');
+ assert.strictEqual(renderer.html.mock.calls[0].arguments[0].raw, '');
});
});
@@ -490,7 +490,7 @@ describe('marked unit', () => {
}
},
renderer: {
- heading(text, depth, raw) {
+ heading({ text, depth }) {
if (text === name) {
return `${text}\n`;
}
@@ -692,7 +692,7 @@ used extension2 walked
it('should use renderer', () => {
const extension = {
renderer: {
- paragraph(text) {
+ paragraph() {
return 'extension';
}
}
@@ -700,7 +700,7 @@ used extension2 walked
mock.method(extension.renderer, 'paragraph');
marked.use(extension);
const html = marked.parse('text');
- assert.strictEqual(extension.renderer.paragraph.mock.calls[0].arguments[0], 'text');
+ assert.strictEqual(extension.renderer.paragraph.mock.calls[0].arguments[0].raw, 'text');
assert.strictEqual(html, 'extension');
});
@@ -773,17 +773,17 @@ used extension2 walked
it('should use last extension function and not override others', () => {
const extension1 = {
renderer: {
- paragraph(text) {
+ paragraph() {
return 'extension1 paragraph\n';
},
- html(html) {
+ html() {
return 'extension1 html\n';
}
}
};
const extension2 = {
renderer: {
- paragraph(text) {
+ paragraph() {
return 'extension2 paragraph\n';
}
}
@@ -803,7 +803,7 @@ paragraph
it('should use previous extension when returning false', () => {
const extension1 = {
renderer: {
- paragraph(text) {
+ paragraph({ text }) {
if (text !== 'original') {
return 'extension1 paragraph\n';
}
@@ -813,7 +813,7 @@ paragraph
};
const extension2 = {
renderer: {
- paragraph(text) {
+ paragraph({ text }) {
if (text !== 'extension1' && text !== 'original') {
return 'extension2 paragraph\n';
}
From bad0d6be361f047ddb3372b10f8656db8d52ecc1 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Wed, 15 May 2024 01:10:51 -0600
Subject: [PATCH 03/14] add list
---
src/Parser.ts | 37 +-------------------------------
src/Renderer.ts | 46 ++++++++++++++++++++++++++++++++++------
src/Tokens.ts | 4 ++++
test/unit/Parser.test.js | 2 ++
4 files changed, 46 insertions(+), 43 deletions(-)
diff --git a/src/Parser.ts b/src/Parser.ts
index e7d524ce03..431f6ec15e 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -109,42 +109,7 @@ export class _Parser {
continue;
}
case 'list': {
- const listToken = token as Tokens.List;
- const ordered = listToken.ordered;
- const start = listToken.start;
- const loose = listToken.loose;
-
- let body = '';
- for (let j = 0; j < listToken.items.length; j++) {
- const item = listToken.items[j];
- const checked = item.checked;
- const task = item.task;
-
- let itemBody = '';
- if (item.task) {
- const checkbox = this.renderer.checkbox(!!checked);
- if (loose) {
- if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
- item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
- item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
- }
- } else {
- item.tokens.unshift({
- type: 'text',
- text: checkbox + ' '
- } as Tokens.Text);
- }
- } else {
- itemBody += checkbox + ' ';
- }
- }
-
- itemBody += this.parse(item.tokens, loose);
- body += this.renderer.listitem(itemBody, task, !!checked);
- }
-
- out += this.renderer.list(body, ordered, start);
+ out += this.renderer.list(token);
continue;
}
case 'html': {
diff --git a/src/Renderer.ts b/src/Renderer.ts
index 17e49c4d0c..b6f1900f21 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -52,17 +52,49 @@ export class _Renderer {
return '
\n';
}
- list(body: string, ordered: boolean, start: number | ''): string {
+ list(token: Tokens.List): string {
+ const ordered = token.ordered;
+ const start = token.start;
+
+ let body = '';
+ for (let j = 0; j < token.items.length; j++) {
+ const item = token.items[j];
+ body += this.listitem(item);
+ }
+
const type = ordered ? 'ol' : 'ul';
- const startatt = (ordered && start !== 1) ? (' start="' + start + '"') : '';
- return '<' + type + startatt + '>\n' + body + '' + type + '>\n';
- }
+ const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : '';
+ return '<' + type + startAttr + '>\n' + body + '' + type + '>\n';
+ }
+
+ listitem(item: Tokens.ListItem): string {
+ let itemBody = '';
+ if (item.task) {
+ const checkbox = this.checkbox({ checked: !!item.checked });
+ if (item.loose) {
+ if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
+ item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
+ item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
+ }
+ } else {
+ item.tokens.unshift({
+ type: 'text',
+ raw: checkbox + ' ',
+ text: checkbox + ' '
+ });
+ }
+ } else {
+ itemBody += checkbox + ' ';
+ }
+ }
+
+ itemBody += this.parser.parse(item.tokens, !!item.loose);
- listitem(text: string, task: boolean, checked: boolean): string {
- return `${text}\n`;
+ return `${itemBody}\n`;
}
- checkbox(checked: boolean): string {
+ checkbox({ checked }: Tokens.Checkbox): string {
return '';
diff --git a/src/Tokens.ts b/src/Tokens.ts
index fecafc8a2a..f8ca7a6bfa 100644
--- a/src/Tokens.ts
+++ b/src/Tokens.ts
@@ -94,6 +94,10 @@ export namespace Tokens {
tokens: Token[];
}
+ export interface Checkbox {
+ checked: boolean;
+ }
+
export interface Paragraph {
type: 'paragraph';
raw: string;
diff --git a/test/unit/Parser.test.js b/test/unit/Parser.test.js
index 5e2a6f3f53..38bf92fbdb 100644
--- a/test/unit/Parser.test.js
+++ b/test/unit/Parser.test.js
@@ -273,6 +273,7 @@ describe('Parser', () => {
{
task: false,
checked: undefined,
+ loose: true,
tokens: [
{
type: 'text',
@@ -284,6 +285,7 @@ describe('Parser', () => {
{
task: false,
checked: undefined,
+ loose: true,
tokens: [
{
type: 'text',
From ff0cc66d801962ca88143b45cd9f557f277d1b95 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Wed, 15 May 2024 01:20:10 -0600
Subject: [PATCH 04/14] add table
---
src/Parser.ts | 29 +----------------------------
src/Renderer.ts | 46 ++++++++++++++++++++++++++++++++++++++--------
2 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/src/Parser.ts b/src/Parser.ts
index 431f6ec15e..a6ddc37015 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -74,34 +74,7 @@ export class _Parser {
continue;
}
case 'table': {
- const tableToken = token as Tokens.Table;
- let header = '';
-
- // header
- let cell = '';
- for (let j = 0; j < tableToken.header.length; j++) {
- cell += this.renderer.tablecell(
- this.parseInline(tableToken.header[j].tokens),
- { header: true, align: tableToken.align[j] }
- );
- }
- header += this.renderer.tablerow(cell);
-
- let body = '';
- for (let j = 0; j < tableToken.rows.length; j++) {
- const row = tableToken.rows[j];
-
- cell = '';
- for (let k = 0; k < row.length; k++) {
- cell += this.renderer.tablecell(
- this.parseInline(row[k].tokens),
- { header: false, align: tableToken.align[k] }
- );
- }
-
- body += this.renderer.tablerow(cell);
- }
- out += this.renderer.table(header, body);
+ out += this.renderer.table(token);
continue;
}
case 'blockquote': {
diff --git a/src/Renderer.ts b/src/Renderer.ts
index b6f1900f21..274e0515af 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -4,7 +4,7 @@ import {
escape
} from './helpers.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
-import type { Tokens } from './Tokens.ts';
+import type { Tokens, Token } from './Tokens.ts';
import type { _Parser } from './Parser.ts';
/**
@@ -104,7 +104,35 @@ export class _Renderer {
return `${this.parser.parseInline(tokens)}
\n`;
}
- table(header: string, body: string): string {
+ table(token: Tokens.Table): string {
+ let header = '';
+
+ // header
+ let cell = '';
+ for (let j = 0; j < token.header.length; j++) {
+ cell += this.tablecell({
+ tokens: token.header[j].tokens,
+ header: true,
+ align: token.align[j]
+ });
+ }
+ header += this.tablerow({ text: cell });
+
+ let body = '';
+ for (let j = 0; j < token.rows.length; j++) {
+ const row = token.rows[j];
+
+ cell = '';
+ for (let k = 0; k < row.length; k++) {
+ cell += this.tablecell({
+ tokens: row[k].tokens,
+ header: false,
+ align: token.align[k]
+ });
+ }
+
+ body += this.tablerow({ text: cell });
+ }
if (body) body = `${body}`;
return '\n'
@@ -115,17 +143,19 @@ export class _Renderer {
+ '
\n';
}
- tablerow(content: string): string {
- return `\n${content}
\n`;
+ tablerow({ text }: { text: string }): string {
+ return `\n${text}
\n`;
}
- tablecell(content: string, flags: {
+ tablecell(token: {
+ tokens: Token[];
header: boolean;
align: 'center' | 'left' | 'right' | null;
}): string {
- const type = flags.header ? 'th' : 'td';
- const tag = flags.align
- ? `<${type} align="${flags.align}">`
+ const content = this.parser.parseInline(token.tokens);
+ const type = token.header ? 'th' : 'td';
+ const tag = token.align
+ ? `<${type} align="${token.align}">`
: `<${type}>`;
return tag + content + `${type}>\n`;
}
From 45dd2c305d70d23be284b95cc4b86c795a0045a9 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Wed, 15 May 2024 01:22:26 -0600
Subject: [PATCH 05/14] add space renderer
---
src/Parser.ts | 1 +
src/Renderer.ts | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/src/Parser.ts b/src/Parser.ts
index a6ddc37015..4ec937eee7 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -59,6 +59,7 @@ export class _Parser {
switch (token.type) {
case 'space': {
+ out += this.renderer.space(token);
continue;
}
case 'hr': {
diff --git a/src/Renderer.ts b/src/Renderer.ts
index 274e0515af..c02a5b70fd 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -17,6 +17,10 @@ export class _Renderer {
this.options = options || _defaults;
}
+ space(token: Tokens.Space): string {
+ return '';
+ }
+
code({ text, lang, escaped }: Tokens.Code): string {
const langString = (lang || '').match(/^\S*/)?.[0];
From 87ae47e938c647c1cf26c0d78ffd6ed6c8e889ee Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Wed, 15 May 2024 01:31:55 -0600
Subject: [PATCH 06/14] use text renderer
---
src/Parser.ts | 6 +++---
src/Renderer.ts | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Parser.ts b/src/Parser.ts
index 4ec937eee7..a93887c0c5 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -96,10 +96,10 @@ export class _Parser {
}
case 'text': {
let textToken = token;
- let body = 'tokens' in textToken && textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text;
+ let body = this.renderer.text(textToken);
while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
- textToken = tokens[++i] as Tokens.Text;
- body += '\n' + (textToken.tokens ? this.parseInline(textToken.tokens) : textToken.text);
+ textToken = tokens[++i] as Tokens.Text | Tokens.Tag;
+ body += '\n' + this.renderer.text(textToken);
}
if (top) {
out += this.renderer.paragraph({
diff --git a/src/Renderer.ts b/src/Renderer.ts
index c02a5b70fd..9dd3fe0d1e 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -217,7 +217,7 @@ export class _Renderer {
return out;
}
- text({ text }: Tokens.Text | Tokens.Escape | Tokens.Tag) : string {
- return text;
+ text(token: Tokens.Text | Tokens.Escape | Tokens.Tag) : string {
+ return 'tokens' in token && token.tokens ? this.parser.parseInline(token.tokens) : token.text;
}
}
From 40e0f61453648ee6e9afaf0317b2e82da2bd655f Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Wed, 15 May 2024 22:39:48 -0600
Subject: [PATCH 07/14] fix types
---
src/Renderer.ts | 22 +++---------
src/Tokenizer.ts | 14 +++++---
src/Tokens.ts | 6 ++++
test/types/marked.ts | 51 ++++++++++++++--------------
test/unit/Lexer.test.js | 72 ++++++++++++++++++++++++++++++----------
test/unit/Parser.test.js | 16 ++++++---
6 files changed, 112 insertions(+), 69 deletions(-)
diff --git a/src/Renderer.ts b/src/Renderer.ts
index 9dd3fe0d1e..b790803a90 100644
--- a/src/Renderer.ts
+++ b/src/Renderer.ts
@@ -4,7 +4,7 @@ import {
escape
} from './helpers.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
-import type { Tokens, Token } from './Tokens.ts';
+import type { Tokens } from './Tokens.ts';
import type { _Parser } from './Parser.ts';
/**
@@ -114,11 +114,7 @@ export class _Renderer {
// header
let cell = '';
for (let j = 0; j < token.header.length; j++) {
- cell += this.tablecell({
- tokens: token.header[j].tokens,
- header: true,
- align: token.align[j]
- });
+ cell += this.tablecell(token.header[j]);
}
header += this.tablerow({ text: cell });
@@ -128,11 +124,7 @@ export class _Renderer {
cell = '';
for (let k = 0; k < row.length; k++) {
- cell += this.tablecell({
- tokens: row[k].tokens,
- header: false,
- align: token.align[k]
- });
+ cell += this.tablecell(row[k]);
}
body += this.tablerow({ text: cell });
@@ -147,15 +139,11 @@ export class _Renderer {
+ '\n';
}
- tablerow({ text }: { text: string }): string {
+ tablerow({ text }: Tokens.TableRow): string {
return `\n${text}
\n`;
}
- tablecell(token: {
- tokens: Token[];
- header: boolean;
- align: 'center' | 'left' | 'right' | null;
- }): string {
+ tablecell(token: Tokens.TableCell): string {
const content = this.parser.parseInline(token.tokens);
const type = token.header ? 'th' : 'td';
const tag = token.align
diff --git a/src/Tokenizer.ts b/src/Tokenizer.ts
index 10b31454e2..f3ef1c5686 100644
--- a/src/Tokenizer.ts
+++ b/src/Tokenizer.ts
@@ -438,18 +438,22 @@ export class _Tokenizer {
}
}
- for (const header of headers) {
+ for (let i = 0; i < headers.length; i++) {
item.header.push({
- text: header,
- tokens: this.lexer.inline(header)
+ text: headers[i],
+ tokens: this.lexer.inline(headers[i]),
+ header: true,
+ align: item.align[i]
});
}
for (const row of rows) {
- item.rows.push(splitCells(row, item.header.length).map(cell => {
+ item.rows.push(splitCells(row, item.header.length).map((cell, i) => {
return {
text: cell,
- tokens: this.lexer.inline(cell)
+ tokens: this.lexer.inline(cell),
+ header: false,
+ align: item.align[i]
};
}));
}
diff --git a/src/Tokens.ts b/src/Tokens.ts
index f8ca7a6bfa..e2fb1618cf 100644
--- a/src/Tokens.ts
+++ b/src/Tokens.ts
@@ -58,9 +58,15 @@ export namespace Tokens {
rows: TableCell[][];
}
+ export interface TableRow {
+ text: string;
+ }
+
export interface TableCell {
text: string;
tokens: Token[];
+ header: boolean;
+ align: 'center' | 'left' | 'right' | null;
}
export interface Hr {
diff --git a/test/types/marked.ts b/test/types/marked.ts
index 8bf2997b2e..b8d373bbb3 100644
--- a/test/types/marked.ts
+++ b/test/types/marked.ts
@@ -64,6 +64,7 @@ console.log(marked.parseInline('9) I am using __markdown__.'));
console.log(marked.parseInline('10) I am using __markdown__.', options));
const text = 'Something';
+const raw = 'Raw';
const tokens: TokensList = marked.lexer(text, options);
console.log(marked.parser(tokens));
@@ -79,8 +80,8 @@ const re: Record>> = marked.Lexer.
const lexerOptions: MarkedOptions = lexer.options;
const renderer = new marked.Renderer();
-renderer.heading = (text, level, raw) => {
- return text + level.toString();
+renderer.heading = ({ text, depth }) => {
+ return text + depth.toString();
};
renderer.hr = () => {
return `
\n`;
@@ -90,31 +91,31 @@ renderer.checkbox = checked => {
};
class ExtendedRenderer extends marked.Renderer {
- code = (code: string, language: string | undefined, isEscaped: boolean): string => super.code(code, language, isEscaped);
- blockquote = (quote: string): string => super.blockquote(quote);
- html = (html: string): string => super.html(html);
- heading = (text: string, level: 1 | 2 | 3 | 4 | 5 | 6, raw: string): string => super.heading(text, level, raw);
- hr = (): string => super.hr();
- list = (body: string, ordered: boolean, start: number): string => super.list(body, ordered, start);
- listitem = (text: string, task: boolean, checked: boolean): string => super.listitem(text, task, checked);
- checkbox = (checked: boolean): string => super.checkbox(checked);
- paragraph = (text: string): string => super.paragraph(text);
- table = (header: string, body: string): string => super.table(header, body);
- tablerow = (content: string): string => super.tablerow(content);
- tablecell = (content: string, flags: { header: boolean; align: 'center' | 'left' | 'right' | null }): string => super.tablecell(content, flags);
- strong = (text: string): string => super.strong(text);
- em = (text: string): string => super.em(text);
- codespan = (code: string): string => super.codespan(code);
- br = (): string => super.br();
- del = (text: string): string => super.del(text);
- link = (href: string, title: string, text: string): string => super.link(href, title, text);
- image = (href: string, title: string, text: string): string => super.image(href, title, text);
+ code = ({ type, raw, text, codeBlockStyle, lang, escaped }: Tokens.Code): string => super.code({ type, raw, text, codeBlockStyle, lang, escaped });
+ blockquote = ({ type, raw, text, tokens }: Tokens.Blockquote): string => super.blockquote({ type, raw, text, tokens });
+ html = ({ type, raw, text, pre, block }: Tokens.HTML): string => super.html({ type, raw, text, pre, block });
+ heading = ({ type, raw, text, depth, tokens }: Tokens.Heading): string => super.heading({ type, raw, text, depth, tokens });
+ hr = ({ type, raw }: Tokens.Hr): string => super.hr({ type, raw });
+ list = ({ type, raw, ordered, start, loose, items }: Tokens.List): string => super.list({ type, raw, ordered, start, loose, items});
+ listitem = ({ type, raw, task, checked, loose, text, tokens }: Tokens.ListItem): string => super.listitem({ type, raw, task, checked, loose, text, tokens });
+ checkbox = ({ checked }: Tokens.Checkbox): string => super.checkbox({ checked });
+ paragraph = ({ type, raw, pre, text, tokens }: Tokens.Paragraph): string => super.paragraph({ type, raw, pre, text, tokens });
+ table = ({ type, raw, align, header, rows }: Tokens.Table): string => super.table({ type, raw, align, header, rows });
+ tablerow = ({ text }: Tokens.TableRow): string => super.tablerow({ text });
+ tablecell = ({ text, tokens, header, align }: Tokens.TableCell): string => super.tablecell({ text, tokens, header, align });
+ strong = ({ type, raw, text, tokens }: Tokens.Strong): string => super.strong({ type, raw, text, tokens });
+ em = ({ type, raw, text, tokens }: Tokens.Em): string => super.em({ type, raw, text, tokens });
+ codespan = ({ type, raw, text }: Tokens.Codespan): string => super.codespan({ type, raw, text });
+ br = ({ type, raw }: Tokens.Br): string => super.br({ type, raw });
+ del = ({ type, raw, text, tokens }: Tokens.Del): string => super.del({ type, raw, text, tokens });
+ link = ({ type, raw, href, title, text, tokens }: Tokens.Link): string => super.link({ type, raw, href, title, text, tokens });
+ image = ({ type, raw, href, title, text }: Tokens.Image): string => super.image({ type, raw, href, title, text });
}
const rendererOptions: MarkedOptions = renderer.options;
const textRenderer = new marked.TextRenderer();
-console.log(textRenderer.strong(text));
+console.log(textRenderer.strong({ type : 'strong', raw, text, tokens }));
const parseTestText = '- list1\n - list1.1\n\n listend';
const parseTestTokens: TokensList = marked.lexer(parseTestText, options);
@@ -135,14 +136,14 @@ marked.use({ renderer }, { tokenizer });
marked.use({
renderer: {
- heading(text, level) {
- if (level > 3) {
+ heading({ text, depth }) {
+ if (depth > 3) {
return `${text}
`;
}
return false;
},
- listitem(text, task, checked) {
+ listitem({ text, task, checked }) {
if (task) return `${text}\n`;
else return `${text}\n`;
}
diff --git a/test/unit/Lexer.test.js b/test/unit/Lexer.test.js
index 8a331fbbe7..fbf932090a 100644
--- a/test/unit/Lexer.test.js
+++ b/test/unit/Lexer.test.js
@@ -196,22 +196,30 @@ lheading 2
header: [
{
text: 'a',
- tokens: [{ type: 'text', raw: 'a', text: 'a' }]
+ tokens: [{ type: 'text', raw: 'a', text: 'a' }],
+ header: true,
+ align: null
},
{
text: 'b',
- tokens: [{ type: 'text', raw: 'b', text: 'b' }]
+ tokens: [{ type: 'text', raw: 'b', text: 'b' }],
+ header: true,
+ align: null
}
],
rows: [
[
{
text: '1',
- tokens: [{ type: 'text', raw: '1', text: '1' }]
+ tokens: [{ type: 'text', raw: '1', text: '1' }],
+ header: false,
+ align: null
},
{
text: '2',
- tokens: [{ type: 'text', raw: '2', text: '2' }]
+ tokens: [{ type: 'text', raw: '2', text: '2' }],
+ header: false,
+ align: null
}
]
]
@@ -243,22 +251,30 @@ paragraph 1
header: [
{
text: 'a',
- tokens: [{ type: 'text', raw: 'a', text: 'a' }]
+ tokens: [{ type: 'text', raw: 'a', text: 'a' }],
+ header: true,
+ align: null
},
{
text: 'b',
- tokens: [{ type: 'text', raw: 'b', text: 'b' }]
+ tokens: [{ type: 'text', raw: 'b', text: 'b' }],
+ header: true,
+ align: null
}
],
rows: [
[
{
text: '1',
- tokens: [{ type: 'text', raw: '1', text: '1' }]
+ tokens: [{ type: 'text', raw: '1', text: '1' }],
+ header: false,
+ align: null
},
{
text: '2',
- tokens: [{ type: 'text', raw: '2', text: '2' }]
+ tokens: [{ type: 'text', raw: '2', text: '2' }],
+ header: false,
+ align: null
}
]
]
@@ -284,30 +300,42 @@ paragraph 1
header: [
{
text: 'a',
- tokens: [{ type: 'text', raw: 'a', text: 'a' }]
+ tokens: [{ type: 'text', raw: 'a', text: 'a' }],
+ header: true,
+ align: 'left'
},
{
text: 'b',
- tokens: [{ type: 'text', raw: 'b', text: 'b' }]
+ tokens: [{ type: 'text', raw: 'b', text: 'b' }],
+ header: true,
+ align: 'center'
},
{
text: 'c',
- tokens: [{ type: 'text', raw: 'c', text: 'c' }]
+ tokens: [{ type: 'text', raw: 'c', text: 'c' }],
+ header: true,
+ align: 'right'
}
],
rows: [
[
{
text: '1',
- tokens: [{ type: 'text', raw: '1', text: '1' }]
+ tokens: [{ type: 'text', raw: '1', text: '1' }],
+ header: false,
+ align: 'left'
},
{
text: '2',
- tokens: [{ type: 'text', raw: '2', text: '2' }]
+ tokens: [{ type: 'text', raw: '2', text: '2' }],
+ header: false,
+ align: 'center'
},
{
text: '3',
- tokens: [{ type: 'text', raw: '3', text: '3' }]
+ tokens: [{ type: 'text', raw: '3', text: '3' }],
+ header: false,
+ align: 'right'
}
]
]
@@ -333,22 +361,30 @@ a | b
header: [
{
text: 'a',
- tokens: [{ type: 'text', raw: 'a', text: 'a' }]
+ tokens: [{ type: 'text', raw: 'a', text: 'a' }],
+ header: true,
+ align: null
},
{
text: 'b',
- tokens: [{ type: 'text', raw: 'b', text: 'b' }]
+ tokens: [{ type: 'text', raw: 'b', text: 'b' }],
+ header: true,
+ align: null
}
],
rows: [
[
{
text: '1',
- tokens: [{ type: 'text', raw: '1', text: '1' }]
+ tokens: [{ type: 'text', raw: '1', text: '1' }],
+ header: false,
+ align: null
},
{
text: '2',
- tokens: [{ type: 'text', raw: '2', text: '2' }]
+ tokens: [{ type: 'text', raw: '2', text: '2' }],
+ header: false,
+ align: null
}
]
]
diff --git a/test/unit/Parser.test.js b/test/unit/Parser.test.js
index 38bf92fbdb..c8b151c2ea 100644
--- a/test/unit/Parser.test.js
+++ b/test/unit/Parser.test.js
@@ -77,22 +77,30 @@ describe('Parser', () => {
header: [
{
text: 'a',
- tokens: [{ type: 'text', raw: 'a', text: 'a' }]
+ tokens: [{ type: 'text', raw: 'a', text: 'a' }],
+ header: true,
+ align: 'left'
},
{
text: 'b',
- tokens: [{ type: 'text', raw: 'b', text: 'b' }]
+ tokens: [{ type: 'text', raw: 'b', text: 'b' }],
+ header: true,
+ align: 'right'
}
],
rows: [
[
{
text: '1',
- tokens: [{ type: 'text', raw: '1', text: '1' }]
+ tokens: [{ type: 'text', raw: '1', text: '1' }],
+ header: false,
+ align: 'left'
},
{
text: '2',
- tokens: [{ type: 'text', raw: '2', text: '2' }]
+ tokens: [{ type: 'text', raw: '2', text: '2' }],
+ header: false,
+ align: 'right'
}
]
]
From 260d41e8ec921881ed423b91abf624c1da9bb549 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Thu, 16 May 2024 00:07:49 -0600
Subject: [PATCH 08/14] update docs
---
docs/USING_PRO.md | 109 ++++++++++++++++++++++------------------------
1 file changed, 53 insertions(+), 56 deletions(-)
diff --git a/docs/USING_PRO.md b/docs/USING_PRO.md
index c4e1ddd8d2..a147ad1cc4 100644
--- a/docs/USING_PRO.md
+++ b/docs/USING_PRO.md
@@ -68,16 +68,16 @@ import { marked } from 'marked';
// Override function
const renderer = {
- heading(text, level) {
+ heading({ text, depth }) {
const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
return `
-
+
${text}
- `;
+ `;
}
};
@@ -97,7 +97,7 @@ console.log(marked.parse('# heading+'));
heading+
```
-**Note:** Calling `marked.use()` in the following way will avoid overriding the `heading` token output but create a new renderer in the process.
+**Note:** Calling `marked.use()` in the following way will avoid overriding the `heading` token output but create a new `heading` renderer in the process.
```js
marked.use({
@@ -112,38 +112,32 @@ marked.use({
### Block-level renderer methods
-- **code**(*string* code, *string* infostring, *boolean* escaped)
-- **blockquote**(*string* quote)
-- **html**(*string* html, *boolean* block)
-- **heading**(*string* text, *number* level, *string* raw)
-- **hr**()
-- **list**(*string* body, *boolean* ordered, *number* start)
-- **listitem**(*string* text, *boolean* task, *boolean* checked)
-- **checkbox**(*boolean* checked)
-- **paragraph**(*string* text)
-- **table**(*string* header, *string* body)
-- **tablerow**(*string* content)
-- **tablecell**(*string* content, *object* flags)
+- **space**(token: *Tokens.Space*): *string*
+- **code**(token: *Tokens.Code*): *string*
+- **blockquote**(token: *Tokens.Blockquote*): *string*
+- **html**(token: *Tokens.HTML | Tokens.Tag*): *string*
+- **heading**(token: *Tokens.Heading*): *string*
+- **hr**(token: *Tokens.Hr*): *string*
+- **list**(token: *Tokens.List*): *string*
+- **listitem**(token: *Tokens.ListItem*): *string*
+- **checkbox**(token: *Tokens.Checkbox*): *string*
+- **paragraph**(token: *Tokens.Paragraph*): *string*
+- **table**(token: *Tokens.Table*): *string*
+- **tablerow**(token: *Tokens.TableRow*): *string*
+- **tablecell**(token: *Tokens.TableCell*): *string*
### Inline-level renderer methods
-- **strong**(*string* text)
-- **em**(*string* text)
-- **codespan**(*string* code)
-- **br**()
-- **del**(*string* text)
-- **link**(*string* href, *string* title, *string* text)
-- **image**(*string* href, *string* title, *string* text)
-- **text**(*string* text)
+- **strong**(token: *Tokens.Strong*): *string*
+- **em**(token: *Tokens.Em*): *string*
+- **codespan**(token: *Tokens.Codespan*): *string*
+- **br**(token: *Tokens.Br*): *string*
+- **del**(token: *Tokens.Del*): *string*
+- **link**(token: *Tokens.Link*): *string*
+- **image**(token: *Tokens.Image*): *string*
+- **text**(token: *Tokens.Text | Tokens.Escape | Tokens.Tag*): *string*
-`flags` has the following properties:
-
-```js
-{
- header: true || false,
- align: 'center' || 'left' || 'right'
-}
-```
+The Tokens.* properties can be found [here](https://github.com/markedjs/marked/blob/master/src/Tokens.ts).
***
@@ -192,33 +186,35 @@ console.log(marked.parse('$ latex code $\n\n` other code `'));
### Block level tokenizer methods
-- **space**(*string* src)
-- **code**(*string* src)
-- **fences**(*string* src)
-- **heading**(*string* src)
-- **hr**(*string* src)
-- **blockquote**(*string* src)
-- **list**(*string* src)
-- **html**(*string* src)
-- **def**(*string* src)
-- **table**(*string* src)
-- **lheading**(*string* src)
-- **paragraph**(*string* src)
-- **text**(*string* src)
+- **space**(src: *string*): *Tokens.Space*
+- **code**(src: *string*): *Tokens.Code*
+- **fences**(src: *string*): *Tokens.Code*
+- **heading**(src: *string*): *Tokens.Heading*
+- **hr**(src: *string*): *Tokens.Hr*
+- **blockquote**(src: *string*): *Tokens.Blockquote*
+- **list**(src: *string*): *Tokens.List*
+- **html**(src: *string*): *Tokens.HTML*
+- **def**(src: *string*): *Tokens.Def*
+- **table**(src: *string*): *Tokens.Table*
+- **lheading**(src: *string*): *Tokens.Heading*
+- **paragraph**(src: *string*): *Tokens.Paragraph*
+- **text**(src: *string*): *Tokens.Text*
### Inline level tokenizer methods
-- **escape**(*string* src)
-- **tag**(*string* src)
-- **link**(*string* src)
-- **reflink**(*string* src, *object* links)
-- **emStrong**(*string* src, *string* maskedSrc, *string* prevChar)
-- **codespan**(*string* src)
-- **br**(*string* src)
-- **del**(*string* src)
-- **autolink**(*string* src)
-- **url**(*string* src)
-- **inlineText**(*string* src)
+- **escape**(src: *string*): *Tokens.Escape*
+- **tag**(src: *string*): *Tokens.Tag*
+- **link**(src: *string*): *Tokens.Link | Tokens.Image*
+- **reflink**(src: *string*, links: *object*): *Tokens.Link | Tokens.Image | Tokens.Text*
+- **emStrong**(src: *string*, maskedSrc: *string*, prevChar: *string*): *Tokens.Em | Tokens.Strong*
+- **codespan**(src: *string*): *Tokens.Codespan*
+- **br**(src: *string*): *Tokens.Br*
+- **del**(src: *string*): *Tokens.Del*
+- **autolink**(src: *string*): *Tokens.Link*
+- **url**(src: *string*): *Tokens.Link*
+- **inlineText**(src: *string*): *Tokens.Text*
+
+The Tokens.* properties can be found [here](https://github.com/markedjs/marked/blob/master/src/Tokens.ts).
***
@@ -263,6 +259,7 @@ Hooks are methods that hook into some part of marked. The following hooks are av
|-----------|-------------|
| `preprocess(markdown: string): string` | Process markdown before sending it to marked. |
| `postprocess(html: string): string` | Process html after marked has finished parsing. |
+| `processAllTokens(tokens: Token[]): Token[]` | Process all tokens before walk tokens. |
`marked.use()` can be called multiple times with different `hooks` functions. Each function will be called in order, starting with the function that was assigned *last*.
From eae8807759888167463d899836a8a013a51324f7 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Thu, 16 May 2024 00:15:06 -0600
Subject: [PATCH 09/14] rename MarkedToken
---
src/Parser.ts | 6 +++---
src/Tokens.ts | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Parser.ts b/src/Parser.ts
index a93887c0c5..dfac9b6d54 100644
--- a/src/Parser.ts
+++ b/src/Parser.ts
@@ -1,7 +1,7 @@
import { _Renderer } from './Renderer.ts';
import { _TextRenderer } from './TextRenderer.ts';
import { _defaults } from './defaults.ts';
-import type { TokenWithoutGeneric, Token, Tokens } from './Tokens.ts';
+import type { MarkedToken, Token, Tokens } from './Tokens.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
/**
@@ -55,7 +55,7 @@ export class _Parser {
}
}
- const token = anyToken as TokenWithoutGeneric;
+ const token = anyToken as MarkedToken;
switch (token.type) {
case 'space': {
@@ -148,7 +148,7 @@ export class _Parser {
}
}
- const token = anyToken as TokenWithoutGeneric;
+ const token = anyToken as MarkedToken;
switch (token.type) {
case 'escape': {
diff --git a/src/Tokens.ts b/src/Tokens.ts
index e2fb1618cf..1dd5a9ea3f 100644
--- a/src/Tokens.ts
+++ b/src/Tokens.ts
@@ -1,6 +1,6 @@
/* eslint-disable no-use-before-define */
-export type TokenWithoutGeneric = (
+export type MarkedToken = (
Tokens.Space
| Tokens.Code
| Tokens.Heading
@@ -24,7 +24,7 @@ export type TokenWithoutGeneric = (
| Tokens.Del);
export type Token = (
- TokenWithoutGeneric
+ MarkedToken
| Tokens.Generic);
export namespace Tokens {
From fe1e46021e56754b6a352a8426ebb69fca64b0fc Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Mon, 10 Jun 2024 00:04:04 -0600
Subject: [PATCH 10/14] renderer extensions can opt in to new renderer
signature
---
src/Instance.ts | 162 ++++++++++++++++++++++++++++++++++++++++++-
src/MarkedOptions.ts | 8 ++-
2 files changed, 167 insertions(+), 3 deletions(-)
diff --git a/src/Instance.ts b/src/Instance.ts
index 5fcd9bd61f..019ae3bb63 100644
--- a/src/Instance.ts
+++ b/src/Instance.ts
@@ -6,7 +6,8 @@ import { _Renderer } from './Renderer.ts';
import { _Tokenizer } from './Tokenizer.ts';
import { _TextRenderer } from './TextRenderer.ts';
import {
- escape
+ escape,
+ unescape
} from './helpers.ts';
import type { MarkedExtension, MarkedOptions } from './MarkedOptions.ts';
import type { Token, Tokens, TokensList } from './Tokens.ts';
@@ -151,10 +152,14 @@ export class Marked {
continue;
}
const rendererProp = prop as Exclude;
- const rendererFunc = pack.renderer[rendererProp] as GenericRendererFunction;
+ let rendererFunc = pack.renderer[rendererProp] as GenericRendererFunction;
const prevRenderer = renderer[rendererProp] as GenericRendererFunction;
// Replace renderer with func to run extension, but fall back if false
renderer[rendererProp] = (...args: unknown[]) => {
+ if (!pack.useNewRenderer) {
+ // Remove this in next major version
+ rendererFunc = this.#convertRendererFunction(rendererFunc, rendererProp, renderer) as GenericRendererFunction;
+ }
let ret = rendererFunc.apply(renderer, args);
if (ret === false) {
ret = prevRenderer.apply(renderer, args);
@@ -250,6 +255,159 @@ export class Marked {
return this;
}
+ #convertRendererFunction(func: GenericRendererFunction, prop: string, renderer: _Renderer) {
+ switch (prop) {
+ case 'heading':
+ return function(token: Tokens.Heading) {
+ return func(
+ renderer.parser.parseInline(token.tokens),
+ token.depth,
+ unescape(renderer.parser.parseInline(token.tokens, renderer.parser.textRenderer))
+ );
+ };
+ case 'code':
+ return function(token: Tokens.Code) {
+ return func(
+ token.text,
+ token.lang,
+ !!token.escaped
+ );
+ };
+ case 'table':
+ return function(this: _Renderer, token: Tokens.Table) {
+ let header = '';
+ // header
+ let cell = '';
+ for (let j = 0; j < token.header.length; j++) {
+ cell += this.tablecell(
+ {
+ text: token.header[j].text,
+ tokens: token.header[j].tokens,
+ header: true,
+ align: token.align[j]
+ }
+ );
+ }
+ header += this.tablerow({ text: cell });
+
+ let body = '';
+ for (let j = 0; j < token.rows.length; j++) {
+ const row = token.rows[j];
+
+ cell = '';
+ for (let k = 0; k < row.length; k++) {
+ cell += this.tablecell(
+ {
+ text: row[k].text,
+ tokens: row[k].tokens,
+ header: false,
+ align: token.align[k]
+ }
+ );
+ }
+
+ body += this.tablerow({ text: cell });
+ }
+
+ return func(header, body);
+ };
+ case 'blockquote':
+ return function(this: _Renderer, token: Tokens.Blockquote) {
+ const body = this.parser.parse(token.tokens);
+ return func(body);
+ };
+ case 'list':
+ return function(this: _Renderer, token: Tokens.List) {
+ const ordered = token.ordered;
+ const start = token.start;
+ const loose = token.loose;
+
+ let body = '';
+ for (let j = 0; j < token.items.length; j++) {
+ const item = token.items[j];
+ const checked = item.checked;
+ const task = item.task;
+
+ let itemBody = '';
+ if (item.task) {
+ const checkbox = this.checkbox({ checked: !!checked });
+ if (loose) {
+ if (item.tokens.length > 0 && item.tokens[0].type === 'paragraph') {
+ item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
+ if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
+ item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
+ }
+ } else {
+ item.tokens.unshift({
+ type: 'text',
+ text: checkbox + ' '
+ } as Tokens.Text);
+ }
+ } else {
+ itemBody += checkbox + ' ';
+ }
+ }
+
+ itemBody += this.parser.parse(item.tokens, loose);
+ body += this.listitem({
+ type: 'list_item',
+ raw: itemBody,
+ text: itemBody,
+ task,
+ checked: !!checked,
+ loose,
+ tokens: item.tokens
+ });
+ }
+
+ return func(body, ordered, start);
+ };
+ case 'html':
+ return function(token: Tokens.HTML) {
+ return func(token.text, token.block);
+ };
+ case 'paragraph':
+ return function(this: _Renderer, token: Tokens.Paragraph) {
+ return func(this.parser.parseInline(token.tokens));
+ };
+ case 'escape':
+ return function(token: Tokens.Escape) {
+ return func(token.text);
+ };
+ case 'link':
+ return function(this: _Renderer, token: Tokens.Link) {
+ return func(token.href, token.title, this.parser.parseInline(token.tokens));
+ };
+ case 'image':
+ return function(token: Tokens.Image) {
+ return func(token.href, token.title, token.text);
+ };
+ case 'strong':
+ return function(this: _Renderer, token: Tokens.Strong) {
+ return func(this.parser.parseInline(token.tokens));
+ };
+ case 'em':
+ return function(this: _Renderer, token: Tokens.Em) {
+ return func(this.parser.parseInline(token.tokens));
+ };
+ case 'codespan':
+ return function(token: Tokens.Codespan) {
+ return func(token.text);
+ };
+ case 'del':
+ return function(this: _Renderer, token: Tokens.Del) {
+ return func(this.parser.parseInline(token.tokens));
+ };
+ case 'text':
+ return function(token: Tokens.Text) {
+ return func(token.text);
+ };
+ default:
+ // do nothing
+ }
+ return func;
+ }
+
setOptions(opt: MarkedOptions) {
this.defaults = { ...this.defaults, ...opt };
return this;
diff --git a/src/MarkedOptions.ts b/src/MarkedOptions.ts
index 6be9d2f5fc..8b0d0ea780 100644
--- a/src/MarkedOptions.ts
+++ b/src/MarkedOptions.ts
@@ -109,9 +109,15 @@ export interface MarkedExtension {
* The return value of the function is ignored.
*/
walkTokens?: ((token: Token) => void | Promise) | undefined | null;
+
+ /**
+ * Use the new renderer that accepts an object instead of individual parameters.
+ * This option will be removed and default to true in the next major version.
+ */
+ useNewRenderer?: boolean | undefined;
}
-export interface MarkedOptions extends Omit {
+export interface MarkedOptions extends Omit {
/**
* Hooks are methods that hook into some part of marked.
*/
From d2b960e8a8db0055cbcfc856ec5d3e83a348d36e Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Mon, 10 Jun 2024 00:16:09 -0600
Subject: [PATCH 11/14] fix tests
---
test/unit/marked.test.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/test/unit/marked.test.js b/test/unit/marked.test.js
index 7cfe2d6928..52fe86c0f0 100644
--- a/test/unit/marked.test.js
+++ b/test/unit/marked.test.js
@@ -489,6 +489,7 @@ describe('marked unit', () => {
return false;
}
},
+ useNewRenderer: true,
renderer: {
heading({ text, depth }) {
if (text === name) {
@@ -691,6 +692,7 @@ used extension2 walked
it('should use renderer', () => {
const extension = {
+ useNewRenderer: true,
renderer: {
paragraph() {
return 'extension';
@@ -772,6 +774,7 @@ used extension2 walked
it('should use last extension function and not override others', () => {
const extension1 = {
+ useNewRenderer: true,
renderer: {
paragraph() {
return 'extension1 paragraph\n';
@@ -782,6 +785,7 @@ used extension2 walked
}
};
const extension2 = {
+ useNewRenderer: true,
renderer: {
paragraph() {
return 'extension2 paragraph\n';
@@ -802,6 +806,7 @@ paragraph
it('should use previous extension when returning false', () => {
const extension1 = {
+ useNewRenderer: true,
renderer: {
paragraph({ text }) {
if (text !== 'original') {
@@ -812,6 +817,7 @@ paragraph
}
};
const extension2 = {
+ useNewRenderer: true,
renderer: {
paragraph({ text }) {
if (text !== 'extension1' && text !== 'original') {
@@ -835,6 +841,7 @@ original
it('should get options with this.options', () => {
const extension = {
+ useNewRenderer: true,
renderer: {
heading: () => {
return this && this.options ? 'arrow options\n' : 'arrow no options\n';
From f0ec308df065b7fbbb89faf6c9157f2b16281234 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Mon, 10 Jun 2024 23:27:19 -0600
Subject: [PATCH 12/14] fix docs
---
src/Instance.ts | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/src/Instance.ts b/src/Instance.ts
index 019ae3bb63..6f372e7615 100644
--- a/src/Instance.ts
+++ b/src/Instance.ts
@@ -255,10 +255,17 @@ export class Marked {
return this;
}
+ // Remove this in next major release
#convertRendererFunction(func: GenericRendererFunction, prop: string, renderer: _Renderer) {
switch (prop) {
case 'heading':
return function(token: Tokens.Heading) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(
renderer.parser.parseInline(token.tokens),
token.depth,
@@ -267,6 +274,12 @@ export class Marked {
};
case 'code':
return function(token: Tokens.Code) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(
token.text,
token.lang,
@@ -275,6 +288,12 @@ export class Marked {
};
case 'table':
return function(this: _Renderer, token: Tokens.Table) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
let header = '';
// header
let cell = '';
@@ -313,11 +332,23 @@ export class Marked {
};
case 'blockquote':
return function(this: _Renderer, token: Tokens.Blockquote) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
const body = this.parser.parse(token.tokens);
return func(body);
};
case 'list':
return function(this: _Renderer, token: Tokens.List) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
const ordered = token.ordered;
const start = token.start;
const loose = token.loose;
@@ -364,42 +395,102 @@ export class Marked {
};
case 'html':
return function(token: Tokens.HTML) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(token.text, token.block);
};
case 'paragraph':
return function(this: _Renderer, token: Tokens.Paragraph) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(this.parser.parseInline(token.tokens));
};
case 'escape':
return function(token: Tokens.Escape) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(token.text);
};
case 'link':
return function(this: _Renderer, token: Tokens.Link) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(token.href, token.title, this.parser.parseInline(token.tokens));
};
case 'image':
return function(token: Tokens.Image) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(token.href, token.title, token.text);
};
case 'strong':
return function(this: _Renderer, token: Tokens.Strong) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(this.parser.parseInline(token.tokens));
};
case 'em':
return function(this: _Renderer, token: Tokens.Em) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(this.parser.parseInline(token.tokens));
};
case 'codespan':
return function(token: Tokens.Codespan) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(token.text);
};
case 'del':
return function(this: _Renderer, token: Tokens.Del) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(this.parser.parseInline(token.tokens));
};
case 'text':
return function(token: Tokens.Text) {
+ if (!token.type || token.type !== prop) {
+ // @ts-ignore
+ // eslint-disable-next-line prefer-rest-params
+ return func.apply(this, arguments);
+ }
+
return func(token.text);
};
default:
From 7f173775703cac4e1240c9502cfe9bcb23704b8b Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Tue, 11 Jun 2024 08:06:34 -0600
Subject: [PATCH 13/14] Update src/Instance.ts
Co-authored-by: Steven
---
src/Instance.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Instance.ts b/src/Instance.ts
index 6f372e7615..d0de96e0b3 100644
--- a/src/Instance.ts
+++ b/src/Instance.ts
@@ -157,7 +157,7 @@ export class Marked {
// Replace renderer with func to run extension, but fall back if false
renderer[rendererProp] = (...args: unknown[]) => {
if (!pack.useNewRenderer) {
- // Remove this in next major version
+ // TODO: Remove this in next major version
rendererFunc = this.#convertRendererFunction(rendererFunc, rendererProp, renderer) as GenericRendererFunction;
}
let ret = rendererFunc.apply(renderer, args);
From b26f7c52282dad52d1c2c1a957760e3ad1eaf7b0 Mon Sep 17 00:00:00 2001
From: Tony Brix
Date: Tue, 11 Jun 2024 08:06:44 -0600
Subject: [PATCH 14/14] Update src/Instance.ts
Co-authored-by: Steven
---
src/Instance.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Instance.ts b/src/Instance.ts
index d0de96e0b3..9019301731 100644
--- a/src/Instance.ts
+++ b/src/Instance.ts
@@ -255,7 +255,7 @@ export class Marked {
return this;
}
- // Remove this in next major release
+ // TODO: Remove this in next major release
#convertRendererFunction(func: GenericRendererFunction, prop: string, renderer: _Renderer) {
switch (prop) {
case 'heading':