@doist/typist 10.0.2 → 11.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/helpers/serializer.js +34 -9
- package/dist/helpers/serializer.js.map +1 -1
- package/dist/serializers/html/html.d.ts.map +1 -1
- package/dist/serializers/html/html.js +5 -6
- package/dist/serializers/html/html.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-code-block.js +1 -1
- package/dist/serializers/html/plugins/rehype-code-block.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-image.js +1 -1
- package/dist/serializers/html/plugins/rehype-image.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-suggestions.js +3 -3
- package/dist/serializers/html/plugins/rehype-suggestions.js.map +1 -1
- package/dist/serializers/html/plugins/rehype-task-list.js +1 -1
- package/dist/serializers/html/plugins/rehype-task-list.js.map +1 -1
- package/dist/serializers/html/plugins/remark-autolink-literal.d.ts +2 -2
- package/dist/serializers/html/plugins/remark-autolink-literal.js +5 -5
- package/dist/serializers/html/plugins/remark-autolink-literal.js.map +1 -1
- package/dist/serializers/html/plugins/remark-disable-constructs.js +1 -1
- package/dist/serializers/html/plugins/remark-disable-constructs.js.map +1 -1
- package/dist/serializers/html/plugins/remark-strikethrough.d.ts +2 -2
- package/dist/serializers/html/plugins/remark-strikethrough.js +5 -5
- package/dist/serializers/html/plugins/remark-strikethrough.js.map +1 -1
- package/dist/serializers/markdown/markdown.d.ts +2 -2
- package/dist/serializers/markdown/markdown.d.ts.map +1 -1
- package/dist/serializers/markdown/markdown.js +84 -53
- package/dist/serializers/markdown/markdown.js.map +1 -1
- package/dist/serializers/markdown/plugins/rehype-image.js +36 -0
- package/dist/serializers/markdown/plugins/rehype-image.js.map +1 -0
- package/dist/serializers/markdown/plugins/rehype-suggestions.js +38 -0
- package/dist/serializers/markdown/plugins/rehype-suggestions.js.map +1 -0
- package/dist/serializers/markdown/plugins/rehype-task-list.js +32 -0
- package/dist/serializers/markdown/plugins/rehype-task-list.js.map +1 -0
- package/dist/serializers/markdown/plugins/remark-strikethrough.js +20 -0
- package/dist/serializers/markdown/plugins/remark-strikethrough.js.map +1 -0
- package/dist/serializers/markdown/plugins/remark-task-list.js +20 -0
- package/dist/serializers/markdown/plugins/remark-task-list.js.map +1 -0
- package/package.json +10 -8
- package/dist/serializers/markdown/plugins/image.js +0 -34
- package/dist/serializers/markdown/plugins/image.js.map +0 -1
- package/dist/serializers/markdown/plugins/list-item.js +0 -37
- package/dist/serializers/markdown/plugins/list-item.js.map +0 -1
- package/dist/serializers/markdown/plugins/paragraph.js +0 -23
- package/dist/serializers/markdown/plugins/paragraph.js.map +0 -1
- package/dist/serializers/markdown/plugins/strikethrough.js +0 -27
- package/dist/serializers/markdown/plugins/strikethrough.js.map +0 -1
- package/dist/serializers/markdown/plugins/suggestion.js +0 -25
- package/dist/serializers/markdown/plugins/suggestion.js.map +0 -1
- package/dist/serializers/markdown/plugins/task-item.js +0 -36
- package/dist/serializers/markdown/plugins/task-item.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [10.0.3](https://github.com/Doist/typist/compare/v10.0.2...v10.0.3) (2026-05-23)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **serializers:** follow-up fixes to suggestion HTML output ([#1342](https://github.com/Doist/typist/issues/1342)) ([86ebb2a](https://github.com/Doist/typist/commit/86ebb2af196630dab99c7508f08317cb664c3dbe))
|
|
6
|
+
|
|
1
7
|
## [10.0.2](https://github.com/Doist/typist/compare/v10.0.1...v10.0.2) (2026-05-22)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import { kebabCase } from "lodash-es";
|
|
2
2
|
//#region src/helpers/serializer.ts
|
|
3
3
|
/**
|
|
4
|
+
* Extracts the URL scheme used by a suggestion node (e.g. `mention`, `channel`) from its node
|
|
5
|
+
* name (e.g. `mentionSuggestion`, `channelSuggestion`).
|
|
6
|
+
*
|
|
7
|
+
* @param node The suggestion node type.
|
|
8
|
+
*
|
|
9
|
+
* @returns The URL scheme as a kebab-case string.
|
|
10
|
+
*/
|
|
11
|
+
function getSuggestionUrlScheme(node) {
|
|
12
|
+
return kebabCase(node.name.replace(/Suggestion$/, ""));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns all suggestion nodes available in the given editor schema (e.g. `mentionSuggestion`,
|
|
16
|
+
* `channelSuggestion`).
|
|
17
|
+
*
|
|
18
|
+
* @param schema The editor schema to be used for suggestion nodes detection.
|
|
19
|
+
*
|
|
20
|
+
* @returns An array of `NodeType` objects for the available suggestion nodes.
|
|
21
|
+
*/
|
|
22
|
+
function getSuggestionNodes(schema) {
|
|
23
|
+
return Object.values(schema.nodes).filter((node) => node.name.endsWith("Suggestion"));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
4
26
|
* Builds the information derived from all the suggestion nodes available in the given editor
|
|
5
27
|
* schema, in a single iteration. Returns `null` if there are no suggestion nodes in the schema.
|
|
6
28
|
*
|
|
@@ -9,26 +31,29 @@ import { kebabCase } from "lodash-es";
|
|
|
9
31
|
* @returns A `SuggestionSchemaInfo` object, or `null` if there are no suggestion nodes.
|
|
10
32
|
*/
|
|
11
33
|
function buildSuggestionSchemaInfo(schema) {
|
|
12
|
-
const suggestionNodes =
|
|
34
|
+
const suggestionNodes = getSuggestionNodes(schema);
|
|
13
35
|
if (suggestionNodes.length === 0) return null;
|
|
14
|
-
const triggerCharByScheme = new Map(suggestionNodes.map((node) => [
|
|
36
|
+
const triggerCharByScheme = new Map(suggestionNodes.map((node) => [getSuggestionUrlScheme(node), String(node.spec.triggerChar ?? "@")]));
|
|
15
37
|
return {
|
|
16
38
|
urlSchemeRegex: `(?:${[...triggerCharByScheme.keys()].join("|")})://`,
|
|
17
39
|
triggerCharByScheme
|
|
18
40
|
};
|
|
19
41
|
}
|
|
20
42
|
/**
|
|
21
|
-
*
|
|
43
|
+
* Computes a string ID that identifies the configured trigger characters of all the suggestion
|
|
44
|
+
* nodes in the given editor schema. Used to discriminate cache keys for serializers whose output
|
|
45
|
+
* depends on the trigger character (e.g. the HTML serializer).
|
|
22
46
|
*
|
|
23
|
-
* @param
|
|
47
|
+
* @param schema The current editor document schema.
|
|
24
48
|
*
|
|
25
|
-
* @returns
|
|
49
|
+
* @returns A string ID matching the suggestion trigger characters in the schema.
|
|
26
50
|
*/
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
51
|
+
function computeSuggestionTriggerCharsId(schema) {
|
|
52
|
+
const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema);
|
|
53
|
+
if (!suggestionSchemaInfo) return "";
|
|
54
|
+
return [...suggestionSchemaInfo.triggerCharByScheme].map(([scheme, triggerChar]) => `${scheme}=${triggerChar}`).join();
|
|
30
55
|
}
|
|
31
56
|
//#endregion
|
|
32
|
-
export { buildSuggestionSchemaInfo,
|
|
57
|
+
export { buildSuggestionSchemaInfo, computeSuggestionTriggerCharsId };
|
|
33
58
|
|
|
34
59
|
//# sourceMappingURL=serializer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.js","names":[],"sources":["../../src/helpers/serializer.ts"],"sourcesContent":["import { kebabCase } from 'lodash-es'\n\nimport { DEFAULT_SUGGESTION_TRIGGER_CHAR } from '../constants/suggestions'\n\nimport type { ParseRule, Schema } from '@tiptap/pm/model'\n\n/**\n * Information derived from the suggestion nodes available in the editor schema, used by the\n * HTML serializer to identify and transform suggestion links into spans.\n */\ntype SuggestionSchemaInfo = {\n /**\n * A partial regular expression that matches the URL schemes used by all the available\n * suggestion nodes (e.g. `(?:mention|channel)://`).\n */\n urlSchemeRegex: string\n\n /**\n * A map from each URL scheme (e.g. `mention`, `channel`) to its configured trigger character\n * (e.g. `@`, `#`).\n */\n triggerCharByScheme: Map<string, string>\n}\n\n/**\n * Builds the information derived from all the suggestion nodes available in the given editor\n * schema, in a single iteration. Returns `null` if there are no suggestion nodes in the schema.\n *\n * @param schema The editor schema to be used for suggestion nodes detection.\n *\n * @returns A `SuggestionSchemaInfo` object, or `null` if there are no suggestion nodes.\n */\nfunction buildSuggestionSchemaInfo(schema: Schema): SuggestionSchemaInfo | null {\n const suggestionNodes =
|
|
1
|
+
{"version":3,"file":"serializer.js","names":[],"sources":["../../src/helpers/serializer.ts"],"sourcesContent":["import { kebabCase } from 'lodash-es'\n\nimport { DEFAULT_SUGGESTION_TRIGGER_CHAR } from '../constants/suggestions'\n\nimport type { NodeType, ParseRule, Schema } from '@tiptap/pm/model'\n\n/**\n * Extracts the URL scheme used by a suggestion node (e.g. `mention`, `channel`) from its node\n * name (e.g. `mentionSuggestion`, `channelSuggestion`).\n *\n * @param node The suggestion node type.\n *\n * @returns The URL scheme as a kebab-case string.\n */\nfunction getSuggestionUrlScheme(node: NodeType): string {\n return kebabCase(node.name.replace(/Suggestion$/, ''))\n}\n\n/**\n * Information derived from the suggestion nodes available in the editor schema, used by the\n * HTML serializer to identify and transform suggestion links into spans.\n */\ntype SuggestionSchemaInfo = {\n /**\n * A partial regular expression that matches the URL schemes used by all the available\n * suggestion nodes (e.g. `(?:mention|channel)://`).\n */\n urlSchemeRegex: string\n\n /**\n * A map from each URL scheme (e.g. `mention`, `channel`) to its configured trigger character\n * (e.g. `@`, `#`).\n */\n triggerCharByScheme: Map<string, string>\n}\n\n/**\n * Returns all suggestion nodes available in the given editor schema (e.g. `mentionSuggestion`,\n * `channelSuggestion`).\n *\n * @param schema The editor schema to be used for suggestion nodes detection.\n *\n * @returns An array of `NodeType` objects for the available suggestion nodes.\n */\nfunction getSuggestionNodes(schema: Schema): NodeType[] {\n return Object.values(schema.nodes).filter((node) => node.name.endsWith('Suggestion'))\n}\n\n/**\n * Builds the information derived from all the suggestion nodes available in the given editor\n * schema, in a single iteration. Returns `null` if there are no suggestion nodes in the schema.\n *\n * @param schema The editor schema to be used for suggestion nodes detection.\n *\n * @returns A `SuggestionSchemaInfo` object, or `null` if there are no suggestion nodes.\n */\nfunction buildSuggestionSchemaInfo(schema: Schema): SuggestionSchemaInfo | null {\n const suggestionNodes = getSuggestionNodes(schema)\n\n if (suggestionNodes.length === 0) {\n return null\n }\n\n const triggerCharByScheme = new Map(\n suggestionNodes.map((node) => [\n getSuggestionUrlScheme(node),\n String(\n (node.spec as { triggerChar?: string }).triggerChar ??\n DEFAULT_SUGGESTION_TRIGGER_CHAR,\n ),\n ]),\n )\n\n const urlSchemes = [...triggerCharByScheme.keys()]\n\n return {\n urlSchemeRegex: `(?:${urlSchemes.join('|')})://`,\n triggerCharByScheme,\n }\n}\n\n/**\n * Computes a string ID that identifies the configured trigger characters of all the suggestion\n * nodes in the given editor schema. Used to discriminate cache keys for serializers whose output\n * depends on the trigger character (e.g. the HTML serializer).\n *\n * @param schema The current editor document schema.\n *\n * @returns A string ID matching the suggestion trigger characters in the schema.\n */\nfunction computeSuggestionTriggerCharsId(schema: Schema): string {\n const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema)\n\n if (!suggestionSchemaInfo) {\n return ''\n }\n\n return [...suggestionSchemaInfo.triggerCharByScheme]\n .map(([scheme, triggerChar]) => `${scheme}=${triggerChar}`)\n .join()\n}\n\n/**\n * Extract all tags from the given parse rules argument, and returns an array of said tags.\n *\n * @param parseRules The parse rules for a DOM node or inline style.\n *\n * @returns An array of tags extracted from the parse rules.\n */\nfunction extractTagsFromParseRules(\n parseRules?: readonly ParseRule[],\n): (keyof HTMLElementTagNameMap)[] {\n if (!parseRules || parseRules.length === 0) {\n return []\n }\n\n return parseRules\n .filter((rule) => rule.tag)\n .map((rule) => rule.tag as keyof HTMLElementTagNameMap)\n}\n\nexport {\n buildSuggestionSchemaInfo,\n computeSuggestionTriggerCharsId,\n extractTagsFromParseRules,\n getSuggestionNodes,\n getSuggestionUrlScheme,\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAS,uBAAuB,MAAwB;CACpD,OAAO,UAAU,KAAK,KAAK,QAAQ,eAAe,GAAG,CAAC;;;;;;;;;;AA6B1D,SAAS,mBAAmB,QAA4B;CACpD,OAAO,OAAO,OAAO,OAAO,MAAM,CAAC,QAAQ,SAAS,KAAK,KAAK,SAAS,aAAa,CAAC;;;;;;;;;;AAWzF,SAAS,0BAA0B,QAA6C;CAC5E,MAAM,kBAAkB,mBAAmB,OAAO;CAElD,IAAI,gBAAgB,WAAW,GAC3B,OAAO;CAGX,MAAM,sBAAsB,IAAI,IAC5B,gBAAgB,KAAK,SAAS,CAC1B,uBAAuB,KAAK,EAC5B,OACK,KAAK,KAAkC,eAAA,IAE3C,CACJ,CAAC,CACL;CAID,OAAO;EACH,gBAAgB,MAAM,CAHN,GAAG,oBAAoB,MAAM,CAGb,CAAC,KAAK,IAAI,CAAC;EAC3C;EACH;;;;;;;;;;;AAYL,SAAS,gCAAgC,QAAwB;CAC7D,MAAM,uBAAuB,0BAA0B,OAAO;CAE9D,IAAI,CAAC,sBACD,OAAO;CAGX,OAAO,CAAC,GAAG,qBAAqB,oBAAoB,CAC/C,KAAK,CAAC,QAAQ,iBAAiB,GAAG,OAAO,GAAG,cAAc,CAC1D,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.d.ts","names":[],"sources":["../../../src/serializers/html/html.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"html.d.ts","names":[],"sources":["../../../src/serializers/html/html.ts"],"mappings":";;;;;AAsB8C;KAKzC,wBAAA;;;;AAQ2B;;;;EAA5B,SAAA,GAAY,QAAA;AAAA;;;;AAqDuD;;;;;;iBAA9D,oBAAA,CAAqB,MAAA,EAAQ,MAAA,GAAS,wBAAA;;;;;;;;iBA+FtC,yBAAA,CAA0B,MAAA,EAAQ,MAAA,GAAM,wBAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { computeSchemaId, isPlainTextDocument } from "../../helpers/schema.js";
|
|
2
|
+
import { buildSuggestionSchemaInfo, computeSuggestionTriggerCharsId } from "../../helpers/serializer.js";
|
|
2
3
|
import { rehypeCodeBlock } from "./plugins/rehype-code-block.js";
|
|
3
4
|
import { rehypeImage } from "./plugins/rehype-image.js";
|
|
4
5
|
import { rehypeSuggestions } from "./plugins/rehype-suggestions.js";
|
|
@@ -6,7 +7,7 @@ import { rehypeTaskList } from "./plugins/rehype-task-list.js";
|
|
|
6
7
|
import { remarkAutolinkLiteral } from "./plugins/remark-autolink-literal.js";
|
|
7
8
|
import { remarkDisableConstructs } from "./plugins/remark-disable-constructs.js";
|
|
8
9
|
import { remarkStrikethrough } from "./plugins/remark-strikethrough.js";
|
|
9
|
-
import { escape
|
|
10
|
+
import { escape } from "lodash-es";
|
|
10
11
|
import rehypeMinifyWhitespace from "rehype-minify-whitespace";
|
|
11
12
|
import rehypeStringify from "rehype-stringify";
|
|
12
13
|
import remarkBreaks from "remark-breaks";
|
|
@@ -24,10 +25,8 @@ import { unified } from "unified";
|
|
|
24
25
|
function createHTMLSerializerForPlainTextEditor(schema) {
|
|
25
26
|
return { serialize(markdown) {
|
|
26
27
|
let htmlResult = escape(markdown);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
htmlResult = htmlResult.replace(new RegExp(`\\[([^\\[]+)\\]\\((?:${linkSchema}):\\/\\/([^\\s)]+)\\)`, "gm"), `<span data-${linkSchema} data-id="$2" data-label="$1"></span>`);
|
|
30
|
-
});
|
|
28
|
+
const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema);
|
|
29
|
+
if (suggestionSchemaInfo) for (const [linkSchema, triggerChar] of suggestionSchemaInfo.triggerCharByScheme) htmlResult = htmlResult.replace(new RegExp(`\\[([^\\[]+)\\]\\((?:${linkSchema}):\\/\\/([^\\s)]+)\\)`, "gm"), (_, label, id) => `<span data-${linkSchema} data-id="${id}" data-label="${label}">${triggerChar}${label}</span>`);
|
|
31
30
|
return htmlResult.replace(/^([^\n]+)\n?|\n+/gm, `<p>$1</p>`);
|
|
32
31
|
} };
|
|
33
32
|
}
|
|
@@ -69,7 +68,7 @@ const htmlSerializerInstanceById = {};
|
|
|
69
68
|
* @returns The HTML serializer instance for the given editor schema.
|
|
70
69
|
*/
|
|
71
70
|
function getHTMLSerializerInstance(schema) {
|
|
72
|
-
const id = computeSchemaId(schema);
|
|
71
|
+
const id = [computeSchemaId(schema), computeSuggestionTriggerCharsId(schema)].join("|");
|
|
73
72
|
if (!htmlSerializerInstanceById[id]) htmlSerializerInstanceById[id] = createHTMLSerializer(schema);
|
|
74
73
|
return htmlSerializerInstanceById[id];
|
|
75
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","names":[],"sources":["../../../src/serializers/html/html.ts"],"sourcesContent":["import { escape
|
|
1
|
+
{"version":3,"file":"html.js","names":[],"sources":["../../../src/serializers/html/html.ts"],"sourcesContent":["import { escape } from 'lodash-es'\nimport rehypeMinifyWhitespace from 'rehype-minify-whitespace'\nimport rehypeStringify from 'rehype-stringify'\nimport remarkBreaks from 'remark-breaks'\nimport remarkParse from 'remark-parse'\nimport remarkRehype from 'remark-rehype'\nimport { unified } from 'unified'\n\nimport { computeSchemaId, isPlainTextDocument } from '../../helpers/schema'\nimport {\n buildSuggestionSchemaInfo,\n computeSuggestionTriggerCharsId,\n} from '../../helpers/serializer'\n\nimport { rehypeCodeBlock } from './plugins/rehype-code-block'\nimport { rehypeImage } from './plugins/rehype-image'\nimport { rehypeSuggestions } from './plugins/rehype-suggestions'\nimport { rehypeTaskList } from './plugins/rehype-task-list'\nimport { remarkAutolinkLiteral } from './plugins/remark-autolink-literal'\nimport { remarkDisableConstructs } from './plugins/remark-disable-constructs'\nimport { remarkStrikethrough } from './plugins/remark-strikethrough'\n\nimport type { Schema } from '@tiptap/pm/model'\n\n/**\n * The return type for the `createHTMLSerializer` function.\n */\ntype HTMLSerializerReturnType = {\n /**\n * Serializes an input Markdown string to an output HTML string.\n *\n * @param markdown The Markdown string to serialize.\n *\n * @returns The serialized HTML.\n */\n serialize: (markdown: string) => string\n}\n\n/**\n * The type for the object that holds multiple HTML serializer instances.\n */\ntype HTMLSerializerInstanceById = {\n [id: string]: HTMLSerializerReturnType\n}\n\n/**\n * Create a custom Markdown to HTML serializer for plain-text editors only.\n *\n * @param schema The editor schema to be used for nodes and marks detection.\n *\n * @returns A normalized object for the HTML serializer.\n */\nfunction createHTMLSerializerForPlainTextEditor(schema: Schema) {\n return {\n serialize(markdown: string) {\n // Converts special characters (i.e. `&`, `<`, `>`, `\"`, and `'`) to their corresponding\n // HTML entities because we need to output the full content as valid HTML (i.e. the\n // editor should not drop invalid HTML).\n let htmlResult = escape(markdown)\n\n // Serialize all suggestion links if any suggestion node exists in the schema\n const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema)\n\n if (suggestionSchemaInfo) {\n for (const [linkSchema, triggerChar] of suggestionSchemaInfo.triggerCharByScheme) {\n htmlResult = htmlResult.replace(\n new RegExp(`\\\\[([^\\\\[]+)\\\\]\\\\((?:${linkSchema}):\\\\/\\\\/([^\\\\s)]+)\\\\)`, 'gm'),\n (_, label, id) =>\n `<span data-${linkSchema} data-id=\"${id}\" data-label=\"${label}\">${triggerChar}${label}</span>`,\n )\n }\n }\n\n // Return the serialized HTML with every line wrapped in a paragraph element\n return htmlResult.replace(/^([^\\n]+)\\n?|\\n+/gm, `<p>$1</p>`)\n },\n }\n}\n\n/**\n * Create a Markdown to HTML serializer with the unified ecosystem for a rich-text editor, or use a\n * custom serializer for a plain-text editor. The editor schema is used to detect which nodes and\n * marks are available in the editor, and only parses the input with the minimal required plugins.\n *\n * @param schema The editor schema to be used for nodes and marks detection.\n *\n * @returns A normalized object for the HTML serializer.\n */\nfunction createHTMLSerializer(schema: Schema): HTMLSerializerReturnType {\n // Returns a custom HTML serializer for plain-text editors\n if (isPlainTextDocument(schema)) {\n return createHTMLSerializerForPlainTextEditor(schema)\n }\n\n // Initialize a unified processor with a remark plugin for parsing Markdown\n const unifiedProcessor = unified().use(remarkParse)\n\n // Configure the unified processor to use a custom plugin to disable constructs based on the\n // supported extensions that are enabled in the editor schema\n unifiedProcessor.use(remarkDisableConstructs, schema)\n\n // Configure the unified processor to use a third-party plugin to turn soft line endings into\n // hard breaks (i.e. `<br>`), which will display user content closer to how it was authored\n // (although not CommonMark compliant, this resembles the behaviour we always supported)\n if (schema.nodes.hardBreak) {\n unifiedProcessor.use(remarkBreaks)\n }\n\n // Configure the unified processor to use a custom plugin to add support for the strikethrough\n // extension from the GitHub Flavored Markdown (GFM) specification\n if (schema.marks.strike) {\n unifiedProcessor.use(remarkStrikethrough, { singleTilde: false })\n }\n\n // Configure the unified processor to use a custom plugin to add support for the autolink\n // literals extension from the GitHub Flavored Markdown (GFM) specification\n if (schema.marks.link) {\n unifiedProcessor.use(remarkAutolinkLiteral)\n }\n\n // Configure the unified processor with an official plugin to convert Markdown into HTML to\n // support rehype (a tool that transforms HTML with plugins), followed by another official\n // plugin to minify whitespace between tags (prevents line feeds from appearing as blank)\n unifiedProcessor\n .use(remarkRehype, {\n // Persist raw HTML (disables support for custom elements/tags)\n // ref: https://github.com/Doist/Issues/issues/5689\n allowDangerousHtml: true,\n })\n // This must come before all rehype plugins that transform the HTML output\n .use(rehypeMinifyWhitespace, {\n // Preserve line breaks when collapsing whitespace (e.g., line feeds)\n newlines: true,\n })\n\n // Configure the unified processor with a custom plugin to remove the trailing newline from code\n // blocks (i.e. the newline between the last code line and `</code></pre>`)\n if (schema.nodes.codeBlock) {\n unifiedProcessor.use(rehypeCodeBlock)\n }\n\n // Configure the unified processor with a custom plugin to remove the wrapping paragraph from\n // images and to remove all inline images based on inline images support in the editor schema\n if (schema.nodes.paragraph && schema.nodes.image) {\n unifiedProcessor.use(rehypeImage, schema)\n }\n\n // Configure the unified processor with a custom plugin to add support Tiptap task lists\n if (schema.nodes.taskList && schema.nodes.taskItem) {\n unifiedProcessor.use(rehypeTaskList)\n }\n\n // Configure the unified processor with a custom plugin to add support for suggestions nodes\n unifiedProcessor.use(rehypeSuggestions, schema)\n\n // Configure the unified processor with an official plugin that defines how to take a syntax\n // tree as input and turn it into serialized HTML\n unifiedProcessor.use(rehypeStringify, {\n characterReferences: {\n // Compatibility with the previous implementation in Marked\n useNamedReferences: true,\n },\n })\n\n return {\n serialize(markdown: string) {\n return unifiedProcessor.processSync(markdown).toString()\n },\n }\n}\n\n/**\n * Object that holds multiple HTML serializer instances based on a given ID.\n */\nconst htmlSerializerInstanceById: HTMLSerializerInstanceById = {}\n\n/**\n * Returns a singleton instance of a HTML serializer based on the provided editor schema.\n *\n * @param schema The editor schema connected to the HTML serializer instance.\n *\n * @returns The HTML serializer instance for the given editor schema.\n */\nfunction getHTMLSerializerInstance(schema: Schema) {\n const schemaId = computeSchemaId(schema)\n const triggerCharsId = computeSuggestionTriggerCharsId(schema)\n\n const id = [schemaId, triggerCharsId].join('|')\n\n if (!htmlSerializerInstanceById[id]) {\n htmlSerializerInstanceById[id] = createHTMLSerializer(schema)\n }\n\n return htmlSerializerInstanceById[id]\n}\n\nexport { createHTMLSerializer, getHTMLSerializerInstance }\n\nexport type { HTMLSerializerReturnType }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAoDA,SAAS,uCAAuC,QAAgB;CAC5D,OAAO,EACH,UAAU,UAAkB;EAIxB,IAAI,aAAa,OAAO,SAAS;EAGjC,MAAM,uBAAuB,0BAA0B,OAAO;EAE9D,IAAI,sBACA,KAAK,MAAM,CAAC,YAAY,gBAAgB,qBAAqB,qBACzD,aAAa,WAAW,QACpB,IAAI,OAAO,wBAAwB,WAAW,wBAAwB,KAAK,GAC1E,GAAG,OAAO,OACP,cAAc,WAAW,YAAY,GAAG,gBAAgB,MAAM,IAAI,cAAc,MAAM,SAC7F;EAKT,OAAO,WAAW,QAAQ,sBAAsB,YAAY;IAEnE;;;;;;;;;;;AAYL,SAAS,qBAAqB,QAA0C;CAEpE,IAAI,oBAAoB,OAAO,EAC3B,OAAO,uCAAuC,OAAO;CAIzD,MAAM,mBAAmB,SAAS,CAAC,IAAI,YAAY;CAInD,iBAAiB,IAAI,yBAAyB,OAAO;CAKrD,IAAI,OAAO,MAAM,WACb,iBAAiB,IAAI,aAAa;CAKtC,IAAI,OAAO,MAAM,QACb,iBAAiB,IAAI,qBAAqB,EAAE,aAAa,OAAO,CAAC;CAKrE,IAAI,OAAO,MAAM,MACb,iBAAiB,IAAI,sBAAsB;CAM/C,iBACK,IAAI,cAAc,EAGf,oBAAoB,MACvB,CAAC,CAED,IAAI,wBAAwB,EAEzB,UAAU,MACb,CAAC;CAIN,IAAI,OAAO,MAAM,WACb,iBAAiB,IAAI,gBAAgB;CAKzC,IAAI,OAAO,MAAM,aAAa,OAAO,MAAM,OACvC,iBAAiB,IAAI,aAAa,OAAO;CAI7C,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UACtC,iBAAiB,IAAI,eAAe;CAIxC,iBAAiB,IAAI,mBAAmB,OAAO;CAI/C,iBAAiB,IAAI,iBAAiB,EAClC,qBAAqB,EAEjB,oBAAoB,MACvB,EACJ,CAAC;CAEF,OAAO,EACH,UAAU,UAAkB;EACxB,OAAO,iBAAiB,YAAY,SAAS,CAAC,UAAU;IAE/D;;;;;AAML,MAAM,6BAAyD,EAAE;;;;;;;;AASjE,SAAS,0BAA0B,QAAgB;CAI/C,MAAM,KAAK,CAHM,gBAAgB,OAGb,EAFG,gCAAgC,OAEnB,CAAC,CAAC,KAAK,IAAI;CAE/C,IAAI,CAAC,2BAA2B,KAC5B,2BAA2B,MAAM,qBAAqB,OAAO;CAGjE,OAAO,2BAA2B"}
|
|
@@ -8,7 +8,7 @@ import { visit } from "unist-util-visit";
|
|
|
8
8
|
* the end of the code block.
|
|
9
9
|
*/
|
|
10
10
|
function rehypeCodeBlock() {
|
|
11
|
-
return (
|
|
11
|
+
return (tree) => {
|
|
12
12
|
visit(tree, "element", (node) => {
|
|
13
13
|
if (isHastElementNode(node, "pre") && isHastElementNode(node.children[0], "code") && isHastTextNode(node.children[0].children[0])) node.children[0].children[0].value = node.children[0].children[0].value.replace(/\n$/, "");
|
|
14
14
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rehype-code-block.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-code-block.ts"],"sourcesContent":["import { visit } from 'unist-util-visit'\n\nimport { isHastElementNode, isHastTextNode } from '../../../helpers/unified'\n\nimport type { Node as HastNode } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to remove the trailing newline from code blocks (i.e. the newline between the\n * last code line and `</code></pre>`). Although that newline is part of the CommonMark\n * specification, this custom plugin is required to prevent Tiptap from rendering a blank line at\n * the end of the code block.\n */\nfunction rehypeCodeBlock(): Transformer {\n return (
|
|
1
|
+
{"version":3,"file":"rehype-code-block.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-code-block.ts"],"sourcesContent":["import { visit } from 'unist-util-visit'\n\nimport { isHastElementNode, isHastTextNode } from '../../../helpers/unified'\n\nimport type { Node as HastNode } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to remove the trailing newline from code blocks (i.e. the newline between the\n * last code line and `</code></pre>`). Although that newline is part of the CommonMark\n * specification, this custom plugin is required to prevent Tiptap from rendering a blank line at\n * the end of the code block.\n */\nfunction rehypeCodeBlock(): Transformer {\n return (tree: HastNode) => {\n visit(tree, 'element', (node: HastNode) => {\n if (\n isHastElementNode(node, 'pre') &&\n isHastElementNode(node.children[0], 'code') &&\n isHastTextNode(node.children[0].children[0])\n ) {\n node.children[0].children[0].value = node.children[0].children[0].value.replace(\n /\\n$/,\n '',\n )\n }\n })\n\n return tree\n }\n}\n\nexport { rehypeCodeBlock }\n"],"mappings":";;;;;;;;;AAaA,SAAS,kBAA+B;CACpC,QAAQ,SAAmB;EACvB,MAAM,MAAM,YAAY,SAAmB;GACvC,IACI,kBAAkB,MAAM,MAAM,IAC9B,kBAAkB,KAAK,SAAS,IAAI,OAAO,IAC3C,eAAe,KAAK,SAAS,GAAG,SAAS,GAAG,EAE5C,KAAK,SAAS,GAAG,SAAS,GAAG,QAAQ,KAAK,SAAS,GAAG,SAAS,GAAG,MAAM,QACpE,OACA,GACH;IAEP;EAEF,OAAO"}
|
|
@@ -10,7 +10,7 @@ import { remove } from "unist-util-remove";
|
|
|
10
10
|
*/
|
|
11
11
|
function rehypeImage(schema) {
|
|
12
12
|
if (schema.nodes.image ? schema.nodes.image.spec.inline : false) return (tree) => tree;
|
|
13
|
-
return (
|
|
13
|
+
return (tree) => {
|
|
14
14
|
visit(tree, "element", (node, index, parent) => {
|
|
15
15
|
if (isHastElementNode(node, "p")) if (node.children.every((c) => isHastElementNode(c, "img"))) parent.children.splice(index, 1, ...node.children);
|
|
16
16
|
else remove(node, (n) => isHastElementNode(n, "img"));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rehype-image.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-image.ts"],"sourcesContent":["import { remove } from 'unist-util-remove'\nimport { visit } from 'unist-util-visit'\n\nimport { isHastElementNode } from '../../../helpers/unified'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { Node as HastNode, Parent as HastParent } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to remove the wrapping paragraph from images and to remove all inline images if\n * the editor was configured without inline image support (Tiptap default).\n *\n * @param schema The editor schema to be used for nodes and marks detection.\n */\nfunction rehypeImage(schema: Schema): Transformer {\n const allowInlineImages = schema.nodes.image ? schema.nodes.image.spec.inline : false\n\n // Return the tree as-is if the editor does not support inline images\n if (allowInlineImages) {\n return (tree) => tree\n }\n\n return (
|
|
1
|
+
{"version":3,"file":"rehype-image.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-image.ts"],"sourcesContent":["import { remove } from 'unist-util-remove'\nimport { visit } from 'unist-util-visit'\n\nimport { isHastElementNode } from '../../../helpers/unified'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { Node as HastNode, Parent as HastParent } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to remove the wrapping paragraph from images and to remove all inline images if\n * the editor was configured without inline image support (Tiptap default).\n *\n * @param schema The editor schema to be used for nodes and marks detection.\n */\nfunction rehypeImage(schema: Schema): Transformer {\n const allowInlineImages = schema.nodes.image ? schema.nodes.image.spec.inline : false\n\n // Return the tree as-is if the editor does not support inline images\n if (allowInlineImages) {\n return (tree) => tree\n }\n\n return (tree: HastNode) => {\n visit(tree, 'element', (node: HastNode, index: number, parent: HastParent) => {\n if (isHastElementNode(node, 'p')) {\n const areAllChildrenImages = node.children.every((c) => isHastElementNode(c, 'img'))\n\n // Replace the paragraph with the image children if all children are images, or\n // remove all images from the paragraph if it contains non-image children since the\n // editor does not support inline images\n if (areAllChildrenImages) {\n parent.children.splice(index, 1, ...node.children)\n } else {\n remove(node, (n) => isHastElementNode(n, 'img'))\n }\n }\n })\n\n return tree\n }\n}\n\nexport { rehypeImage }\n"],"mappings":";;;;;;;;;;AAeA,SAAS,YAAY,QAA6B;CAI9C,IAH0B,OAAO,MAAM,QAAQ,OAAO,MAAM,MAAM,KAAK,SAAS,OAI5E,QAAQ,SAAS;CAGrB,QAAQ,SAAmB;EACvB,MAAM,MAAM,YAAY,MAAgB,OAAe,WAAuB;GAC1E,IAAI,kBAAkB,MAAM,IAAI,EAM5B,IAL6B,KAAK,SAAS,OAAO,MAAM,kBAAkB,GAAG,MAAM,CAK3D,EACpB,OAAO,SAAS,OAAO,OAAO,GAAG,GAAG,KAAK,SAAS;QAElD,OAAO,OAAO,MAAM,kBAAkB,GAAG,MAAM,CAAC;IAG1D;EAEF,OAAO"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isHastElementNode, isHastTextNode } from "../../../helpers/unified.js";
|
|
2
1
|
import { buildSuggestionSchemaInfo } from "../../../helpers/serializer.js";
|
|
2
|
+
import { isHastElementNode, isHastTextNode } from "../../../helpers/unified.js";
|
|
3
3
|
import { visit } from "unist-util-visit";
|
|
4
4
|
//#region src/serializers/html/plugins/rehype-suggestions.ts
|
|
5
5
|
/**
|
|
@@ -10,8 +10,8 @@ import { visit } from "unist-util-visit";
|
|
|
10
10
|
function rehypeSuggestions(schema) {
|
|
11
11
|
const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema);
|
|
12
12
|
if (!suggestionSchemaInfo) return (tree) => tree;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const suggestionSchemaRegex = new RegExp(`^${suggestionSchemaInfo.urlSchemeRegex}`);
|
|
14
|
+
return (tree) => {
|
|
15
15
|
visit(tree, "element", (node) => {
|
|
16
16
|
if (isHastElementNode(node, "a") && suggestionSchemaRegex.test(String(node.properties?.href))) {
|
|
17
17
|
const [, urlScheme, id] = /^([a-z-]+):\/\/(\S+)$/i.exec(String(node.properties?.href)) || [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rehype-suggestions.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-suggestions.ts"],"sourcesContent":["import { visit } from 'unist-util-visit'\n\nimport { buildSuggestionSchemaInfo } from '../../../helpers/serializer'\nimport { isHastElementNode, isHastTextNode } from '../../../helpers/unified'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { Node as HastNode } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to add support for suggestions nodes (e.g., `@username` or `#channel).\n *\n * @param schema The editor schema to be used for suggestion nodes detection.\n */\nfunction rehypeSuggestions(schema: Schema): Transformer {\n const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema)\n\n // Return the tree as-is if the editor does not support suggestions\n if (!suggestionSchemaInfo) {\n return (tree: HastNode) => tree\n }\n\n
|
|
1
|
+
{"version":3,"file":"rehype-suggestions.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-suggestions.ts"],"sourcesContent":["import { visit } from 'unist-util-visit'\n\nimport { buildSuggestionSchemaInfo } from '../../../helpers/serializer'\nimport { isHastElementNode, isHastTextNode } from '../../../helpers/unified'\n\nimport type { Schema } from '@tiptap/pm/model'\nimport type { Node as HastNode } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to add support for suggestions nodes (e.g., `@username` or `#channel).\n *\n * @param schema The editor schema to be used for suggestion nodes detection.\n */\nfunction rehypeSuggestions(schema: Schema): Transformer {\n const suggestionSchemaInfo = buildSuggestionSchemaInfo(schema)\n\n // Return the tree as-is if the editor does not support suggestions\n if (!suggestionSchemaInfo) {\n return (tree: HastNode) => tree\n }\n\n const suggestionSchemaRegex = new RegExp(`^${suggestionSchemaInfo.urlSchemeRegex}`)\n\n return (tree: HastNode) => {\n visit(tree, 'element', (node: HastNode) => {\n if (\n isHastElementNode(node, 'a') &&\n suggestionSchemaRegex.test(String(node.properties?.href))\n ) {\n const [, urlScheme, id] =\n /^([a-z-]+):\\/\\/(\\S+)$/i.exec(String(node.properties?.href)) || []\n\n // Replace the link element with a span containing the suggestion attributes,\n // keeping the visible label (prefixed with the trigger character) as text content\n // so the span renders correctly when used outside of an editor.\n if (urlScheme && id && isHastTextNode(node.children[0])) {\n const label = node.children[0].value\n\n // The URL scheme was matched against the regex built from the same map of\n // suggestion nodes, so the trigger character is guaranteed to exist\n const triggerChar = suggestionSchemaInfo.triggerCharByScheme.get(\n urlScheme,\n ) as string\n\n node.tagName = 'span'\n node.properties = {\n [`data-${urlScheme}`]: '',\n 'data-id': id,\n 'data-label': label,\n }\n node.children[0].value = `${triggerChar}${label}`\n }\n }\n })\n\n return tree\n }\n}\n\nexport { rehypeSuggestions }\n"],"mappings":";;;;;;;;;AAcA,SAAS,kBAAkB,QAA6B;CACpD,MAAM,uBAAuB,0BAA0B,OAAO;CAG9D,IAAI,CAAC,sBACD,QAAQ,SAAmB;CAG/B,MAAM,wBAAwB,IAAI,OAAO,IAAI,qBAAqB,iBAAiB;CAEnF,QAAQ,SAAmB;EACvB,MAAM,MAAM,YAAY,SAAmB;GACvC,IACI,kBAAkB,MAAM,IAAI,IAC5B,sBAAsB,KAAK,OAAO,KAAK,YAAY,KAAK,CAAC,EAC3D;IACE,MAAM,GAAG,WAAW,MAChB,yBAAyB,KAAK,OAAO,KAAK,YAAY,KAAK,CAAC,IAAI,EAAE;IAKtE,IAAI,aAAa,MAAM,eAAe,KAAK,SAAS,GAAG,EAAE;KACrD,MAAM,QAAQ,KAAK,SAAS,GAAG;KAI/B,MAAM,cAAc,qBAAqB,oBAAoB,IACzD,UACH;KAED,KAAK,UAAU;KACf,KAAK,aAAa;OACb,QAAQ,cAAc;MACvB,WAAW;MACX,cAAc;MACjB;KACD,KAAK,SAAS,GAAG,QAAQ,GAAG,cAAc;;;IAGpD;EAEF,OAAO"}
|
|
@@ -5,7 +5,7 @@ import { visit } from "unist-util-visit";
|
|
|
5
5
|
* A rehype plugin to add support for Tiptap task lists (i.e., `* [ ] Task`).
|
|
6
6
|
*/
|
|
7
7
|
function rehypeTaskList() {
|
|
8
|
-
return (
|
|
8
|
+
return (tree) => {
|
|
9
9
|
visit(tree, "element", (node) => {
|
|
10
10
|
if (isHastElementNode(node, "ul")) {
|
|
11
11
|
if (node.children.every((c) => isHastElementNode(c, "li") && isHastTextNode(c.children[0]) && /^\[[ x]\] /i.test(c.children[0].value))) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rehype-task-list.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-task-list.ts"],"sourcesContent":["import { visit } from 'unist-util-visit'\n\nimport { isHastElementNode, isHastTextNode } from '../../../helpers/unified'\n\nimport type { Node as HastNode } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to add support for Tiptap task lists (i.e., `* [ ] Task`).\n */\nfunction rehypeTaskList(): Transformer {\n return (
|
|
1
|
+
{"version":3,"file":"rehype-task-list.js","names":[],"sources":["../../../../src/serializers/html/plugins/rehype-task-list.ts"],"sourcesContent":["import { visit } from 'unist-util-visit'\n\nimport { isHastElementNode, isHastTextNode } from '../../../helpers/unified'\n\nimport type { Node as HastNode } from 'hast'\nimport type { Transformer } from 'unified'\n\n/**\n * A rehype plugin to add support for Tiptap task lists (i.e., `* [ ] Task`).\n */\nfunction rehypeTaskList(): Transformer {\n return (tree: HastNode) => {\n visit(tree, 'element', (node: HastNode) => {\n if (isHastElementNode(node, 'ul')) {\n const areAllChildrenTaskItems = node.children.every(\n (c) =>\n isHastElementNode(c, 'li') &&\n isHastTextNode(c.children[0]) &&\n /^\\[[ x]\\] /i.test(c.children[0].value),\n )\n\n // Add the required attributes to the list and list items if all children are tasks,\n // removing the `[ ] ` or `[x] ` at the beginning of the task item text\n if (areAllChildrenTaskItems) {\n node.properties = {\n ...node.properties,\n 'data-type': 'taskList',\n }\n\n node.children.forEach((c) => {\n if (isHastElementNode(c, 'li') && isHastTextNode(c.children[0])) {\n c.properties = {\n ...c.properties,\n 'data-type': 'taskItem',\n 'data-checked': String(/^\\[x\\]/i.test(c.children[0].value)),\n }\n\n c.children[0].value = c.children[0].value.substring(4).trim()\n }\n })\n }\n }\n })\n\n return tree\n }\n}\n\nexport { rehypeTaskList }\n"],"mappings":";;;;;;AAUA,SAAS,iBAA8B;CACnC,QAAQ,SAAmB;EACvB,MAAM,MAAM,YAAY,SAAmB;GACvC,IAAI,kBAAkB,MAAM,KAAK;QACG,KAAK,SAAS,OACzC,MACG,kBAAkB,GAAG,KAAK,IAC1B,eAAe,EAAE,SAAS,GAAG,IAC7B,cAAc,KAAK,EAAE,SAAS,GAAG,MAAM,CAKpB,EAAE;KACzB,KAAK,aAAa;MACd,GAAG,KAAK;MACR,aAAa;MAChB;KAED,KAAK,SAAS,SAAS,MAAM;MACzB,IAAI,kBAAkB,GAAG,KAAK,IAAI,eAAe,EAAE,SAAS,GAAG,EAAE;OAC7D,EAAE,aAAa;QACX,GAAG,EAAE;QACL,aAAa;QACb,gBAAgB,OAAO,UAAU,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;QAC9D;OAED,EAAE,SAAS,GAAG,QAAQ,EAAE,SAAS,GAAG,MAAM,UAAU,EAAE,CAAC,MAAM;;OAEnE;;;IAGZ;EAEF,OAAO"}
|
|
@@ -9,8 +9,8 @@ import { Processor } from "unified";
|
|
|
9
9
|
* `micromark-extension-gfm-autolink-literal` packages, and the implementation is inspired by the
|
|
10
10
|
* third-party `remark-gfm` plugin.
|
|
11
11
|
*
|
|
12
|
-
* The reason why we don't use `remark-gfm` directly is because we
|
|
13
|
-
* GFM features
|
|
12
|
+
* The reason why we don't use `remark-gfm` directly is because we only want to opt into the
|
|
13
|
+
* specific GFM features the editor supports, rather than enabling all of them at once.
|
|
14
14
|
*
|
|
15
15
|
* @param options Configuration options for the plugin.
|
|
16
16
|
*/
|
|
@@ -9,16 +9,16 @@ import { gfmAutolinkLiteral } from "micromark-extension-gfm-autolink-literal";
|
|
|
9
9
|
* `micromark-extension-gfm-autolink-literal` packages, and the implementation is inspired by the
|
|
10
10
|
* third-party `remark-gfm` plugin.
|
|
11
11
|
*
|
|
12
|
-
* The reason why we don't use `remark-gfm` directly is because we
|
|
13
|
-
* GFM features
|
|
12
|
+
* The reason why we don't use `remark-gfm` directly is because we only want to opt into the
|
|
13
|
+
* specific GFM features the editor supports, rather than enabling all of them at once.
|
|
14
14
|
*
|
|
15
15
|
* @param options Configuration options for the plugin.
|
|
16
16
|
*/
|
|
17
17
|
function remarkAutolinkLiteral() {
|
|
18
18
|
const data = this.data();
|
|
19
|
-
const micromarkExtensions = data.micromarkExtensions
|
|
20
|
-
const fromMarkdownExtensions = data.fromMarkdownExtensions
|
|
21
|
-
const toMarkdownExtensions = data.toMarkdownExtensions
|
|
19
|
+
const micromarkExtensions = data.micromarkExtensions ?? (data.micromarkExtensions = []);
|
|
20
|
+
const fromMarkdownExtensions = data.fromMarkdownExtensions ?? (data.fromMarkdownExtensions = []);
|
|
21
|
+
const toMarkdownExtensions = data.toMarkdownExtensions ?? (data.toMarkdownExtensions = []);
|
|
22
22
|
micromarkExtensions.push(gfmAutolinkLiteral());
|
|
23
23
|
fromMarkdownExtensions.push(gfmAutolinkLiteralFromMarkdown());
|
|
24
24
|
toMarkdownExtensions.push(gfmAutolinkLiteralToMarkdown());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remark-autolink-literal.js","names":[],"sources":["../../../../src/serializers/html/plugins/remark-autolink-literal.ts"],"sourcesContent":["import {\n gfmAutolinkLiteralFromMarkdown,\n gfmAutolinkLiteralToMarkdown,\n} from 'mdast-util-gfm-autolink-literal'\nimport { gfmAutolinkLiteral } from 'micromark-extension-gfm-autolink-literal'\n\nimport type { Processor } from 'unified'\n\n/**\n * A remark plugin to add support for the autolink literals extension extension from the GitHub\n * Flavored Markdown (GFM) specification.\n *\n * This is an standalone plugin which makes use of both the `mdast-util-gfm-autolink-literal` and\n * `micromark-extension-gfm-autolink-literal` packages, and the implementation is inspired by the\n * third-party `remark-gfm` plugin.\n *\n * The reason why we don't use `remark-gfm` directly is because we
|
|
1
|
+
{"version":3,"file":"remark-autolink-literal.js","names":[],"sources":["../../../../src/serializers/html/plugins/remark-autolink-literal.ts"],"sourcesContent":["import {\n gfmAutolinkLiteralFromMarkdown,\n gfmAutolinkLiteralToMarkdown,\n} from 'mdast-util-gfm-autolink-literal'\nimport { gfmAutolinkLiteral } from 'micromark-extension-gfm-autolink-literal'\n\nimport type { Processor } from 'unified'\n\n/**\n * A remark plugin to add support for the autolink literals extension extension from the GitHub\n * Flavored Markdown (GFM) specification.\n *\n * This is an standalone plugin which makes use of both the `mdast-util-gfm-autolink-literal` and\n * `micromark-extension-gfm-autolink-literal` packages, and the implementation is inspired by the\n * third-party `remark-gfm` plugin.\n *\n * The reason why we don't use `remark-gfm` directly is because we only want to opt into the\n * specific GFM features the editor supports, rather than enabling all of them at once.\n *\n * @param options Configuration options for the plugin.\n */\nfunction remarkAutolinkLiteral(this: Processor) {\n const data = this.data()\n\n const micromarkExtensions = data.micromarkExtensions ?? (data.micromarkExtensions = [])\n const fromMarkdownExtensions = data.fromMarkdownExtensions ?? (data.fromMarkdownExtensions = [])\n const toMarkdownExtensions = data.toMarkdownExtensions ?? (data.toMarkdownExtensions = [])\n\n micromarkExtensions.push(gfmAutolinkLiteral())\n fromMarkdownExtensions.push(gfmAutolinkLiteralFromMarkdown())\n toMarkdownExtensions.push(gfmAutolinkLiteralToMarkdown())\n}\n\nexport { remarkAutolinkLiteral }\n"],"mappings":";;;;;;;;;;;;;;;;AAqBA,SAAS,wBAAuC;CAC5C,MAAM,OAAO,KAAK,MAAM;CAExB,MAAM,sBAAsB,KAAK,wBAAwB,KAAK,sBAAsB,EAAE;CACtF,MAAM,yBAAyB,KAAK,2BAA2B,KAAK,yBAAyB,EAAE;CAC/F,MAAM,uBAAuB,KAAK,yBAAyB,KAAK,uBAAuB,EAAE;CAEzF,oBAAoB,KAAK,oBAAoB,CAAC;CAC9C,uBAAuB,KAAK,gCAAgC,CAAC;CAC7D,qBAAqB,KAAK,8BAA8B,CAAC"}
|
|
@@ -17,7 +17,7 @@ function remarkDisableConstructs(schema) {
|
|
|
17
17
|
if (!schema.nodes.horizontalRule) disabledConstructs.push("thematicBreak");
|
|
18
18
|
if (!schema.nodes.image) disabledConstructs.push("labelStartImage");
|
|
19
19
|
if (!schema.marks.link) disabledConstructs.push("labelStartLink");
|
|
20
|
-
(data.micromarkExtensions
|
|
20
|
+
(data.micromarkExtensions ?? (data.micromarkExtensions = [])).push({ disable: { null: disabledConstructs } });
|
|
21
21
|
}
|
|
22
22
|
//#endregion
|
|
23
23
|
export { remarkDisableConstructs };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remark-disable-constructs.js","names":[],"sources":["../../../../src/serializers/html/plugins/remark-disable-constructs.ts"],"sourcesContent":["import type { Schema } from '@tiptap/pm/model'\nimport type { Processor } from 'unified'\n\n/**\n * A remark plugin to disable multiple language constructs based on the availability of marks and/or\n * nodes in the given editor schema.\n *\n * @param schema The editor schema to be used for nodes and marks detection.\n */\nfunction remarkDisableConstructs(this: Processor, schema: Schema) {\n const data = this.data()\n\n const disabledConstructs: string[] = []\n\n if (!schema.nodes.blockquote) {\n disabledConstructs.push('blockQuote')\n }\n\n if (!schema.marks.bold || !schema.marks.italic) {\n disabledConstructs.push('attention')\n }\n\n if (!schema.nodes.bulletList || !schema.nodes.orderedList) {\n disabledConstructs.push('list')\n }\n\n if (!schema.marks.code) {\n disabledConstructs.push('codeText')\n }\n\n if (!schema.nodes.codeBlock) {\n disabledConstructs.push('codeFenced', 'codeIndented')\n }\n\n if (!schema.nodes.heading) {\n disabledConstructs.push('headingAtx')\n }\n\n if (!schema.nodes.horizontalRule) {\n disabledConstructs.push('thematicBreak')\n }\n\n if (!schema.nodes.image) {\n disabledConstructs.push('labelStartImage')\n }\n\n if (!schema.marks.link) {\n disabledConstructs.push('labelStartLink')\n }\n\n const micromarkExtensions = data.micromarkExtensions
|
|
1
|
+
{"version":3,"file":"remark-disable-constructs.js","names":[],"sources":["../../../../src/serializers/html/plugins/remark-disable-constructs.ts"],"sourcesContent":["import type { Schema } from '@tiptap/pm/model'\nimport type { Processor } from 'unified'\n\n/**\n * A remark plugin to disable multiple language constructs based on the availability of marks and/or\n * nodes in the given editor schema.\n *\n * @param schema The editor schema to be used for nodes and marks detection.\n */\nfunction remarkDisableConstructs(this: Processor, schema: Schema) {\n const data = this.data()\n\n const disabledConstructs: string[] = []\n\n if (!schema.nodes.blockquote) {\n disabledConstructs.push('blockQuote')\n }\n\n if (!schema.marks.bold || !schema.marks.italic) {\n disabledConstructs.push('attention')\n }\n\n if (!schema.nodes.bulletList || !schema.nodes.orderedList) {\n disabledConstructs.push('list')\n }\n\n if (!schema.marks.code) {\n disabledConstructs.push('codeText')\n }\n\n if (!schema.nodes.codeBlock) {\n disabledConstructs.push('codeFenced', 'codeIndented')\n }\n\n if (!schema.nodes.heading) {\n disabledConstructs.push('headingAtx')\n }\n\n if (!schema.nodes.horizontalRule) {\n disabledConstructs.push('thematicBreak')\n }\n\n if (!schema.nodes.image) {\n disabledConstructs.push('labelStartImage')\n }\n\n if (!schema.marks.link) {\n disabledConstructs.push('labelStartLink')\n }\n\n const micromarkExtensions = data.micromarkExtensions ?? (data.micromarkExtensions = [])\n\n // https://github.com/micromark/micromark#case-turn-off-constructs\n micromarkExtensions.push({\n disable: {\n null: disabledConstructs,\n },\n })\n}\n\nexport { remarkDisableConstructs }\n"],"mappings":";;;;;;;AASA,SAAS,wBAAyC,QAAgB;CAC9D,MAAM,OAAO,KAAK,MAAM;CAExB,MAAM,qBAA+B,EAAE;CAEvC,IAAI,CAAC,OAAO,MAAM,YACd,mBAAmB,KAAK,aAAa;CAGzC,IAAI,CAAC,OAAO,MAAM,QAAQ,CAAC,OAAO,MAAM,QACpC,mBAAmB,KAAK,YAAY;CAGxC,IAAI,CAAC,OAAO,MAAM,cAAc,CAAC,OAAO,MAAM,aAC1C,mBAAmB,KAAK,OAAO;CAGnC,IAAI,CAAC,OAAO,MAAM,MACd,mBAAmB,KAAK,WAAW;CAGvC,IAAI,CAAC,OAAO,MAAM,WACd,mBAAmB,KAAK,cAAc,eAAe;CAGzD,IAAI,CAAC,OAAO,MAAM,SACd,mBAAmB,KAAK,aAAa;CAGzC,IAAI,CAAC,OAAO,MAAM,gBACd,mBAAmB,KAAK,gBAAgB;CAG5C,IAAI,CAAC,OAAO,MAAM,OACd,mBAAmB,KAAK,kBAAkB;CAG9C,IAAI,CAAC,OAAO,MAAM,MACd,mBAAmB,KAAK,iBAAiB;CAM7C,CAH4B,KAAK,wBAAwB,KAAK,sBAAsB,EAAE,GAGlE,KAAK,EACrB,SAAS,EACL,MAAM,oBACT,EACJ,CAAC"}
|
|
@@ -10,8 +10,8 @@ import { Options } from "micromark-extension-gfm-strikethrough";
|
|
|
10
10
|
* `micromark-extension-gfm-strikethrough` packages, and the implementation is inspired by the
|
|
11
11
|
* third-party `remark-gfm` plugin.
|
|
12
12
|
*
|
|
13
|
-
* The reason why we don't use `remark-gfm` directly is because we
|
|
14
|
-
* GFM features
|
|
13
|
+
* The reason why we don't use `remark-gfm` directly is because we only want to opt into the
|
|
14
|
+
* specific GFM features the editor supports, rather than enabling all of them at once.
|
|
15
15
|
*
|
|
16
16
|
* @param options Configuration options for the plugin.
|
|
17
17
|
*/
|
|
@@ -9,16 +9,16 @@ import { gfmStrikethrough } from "micromark-extension-gfm-strikethrough";
|
|
|
9
9
|
* `micromark-extension-gfm-strikethrough` packages, and the implementation is inspired by the
|
|
10
10
|
* third-party `remark-gfm` plugin.
|
|
11
11
|
*
|
|
12
|
-
* The reason why we don't use `remark-gfm` directly is because we
|
|
13
|
-
* GFM features
|
|
12
|
+
* The reason why we don't use `remark-gfm` directly is because we only want to opt into the
|
|
13
|
+
* specific GFM features the editor supports, rather than enabling all of them at once.
|
|
14
14
|
*
|
|
15
15
|
* @param options Configuration options for the plugin.
|
|
16
16
|
*/
|
|
17
17
|
function remarkStrikethrough(options = {}) {
|
|
18
18
|
const data = this.data();
|
|
19
|
-
const micromarkExtensions = data.micromarkExtensions
|
|
20
|
-
const fromMarkdownExtensions = data.fromMarkdownExtensions
|
|
21
|
-
const toMarkdownExtensions = data.toMarkdownExtensions
|
|
19
|
+
const micromarkExtensions = data.micromarkExtensions ?? (data.micromarkExtensions = []);
|
|
20
|
+
const fromMarkdownExtensions = data.fromMarkdownExtensions ?? (data.fromMarkdownExtensions = []);
|
|
21
|
+
const toMarkdownExtensions = data.toMarkdownExtensions ?? (data.toMarkdownExtensions = []);
|
|
22
22
|
micromarkExtensions.push(gfmStrikethrough(options));
|
|
23
23
|
fromMarkdownExtensions.push(gfmStrikethroughFromMarkdown());
|
|
24
24
|
toMarkdownExtensions.push(gfmStrikethroughToMarkdown());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remark-strikethrough.js","names":[],"sources":["../../../../src/serializers/html/plugins/remark-strikethrough.ts"],"sourcesContent":["import {\n gfmStrikethroughFromMarkdown,\n gfmStrikethroughToMarkdown,\n} from 'mdast-util-gfm-strikethrough'\nimport { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough'\n\nimport type { Options } from 'micromark-extension-gfm-strikethrough'\nimport type { Processor } from 'unified'\n\n/**\n * A remark plugin to add support for the strikethrough extension from the GitHub Flavored Markdown\n * (GFM) specification.\n *\n * This is an standalone plugin which makes use of both the `mdast-util-gfm-strikethrough` and\n * `micromark-extension-gfm-strikethrough` packages, and the implementation is inspired by the\n * third-party `remark-gfm` plugin.\n *\n * The reason why we don't use `remark-gfm` directly is because we
|
|
1
|
+
{"version":3,"file":"remark-strikethrough.js","names":[],"sources":["../../../../src/serializers/html/plugins/remark-strikethrough.ts"],"sourcesContent":["import {\n gfmStrikethroughFromMarkdown,\n gfmStrikethroughToMarkdown,\n} from 'mdast-util-gfm-strikethrough'\nimport { gfmStrikethrough } from 'micromark-extension-gfm-strikethrough'\n\nimport type { Options } from 'micromark-extension-gfm-strikethrough'\nimport type { Processor } from 'unified'\n\n/**\n * A remark plugin to add support for the strikethrough extension from the GitHub Flavored Markdown\n * (GFM) specification.\n *\n * This is an standalone plugin which makes use of both the `mdast-util-gfm-strikethrough` and\n * `micromark-extension-gfm-strikethrough` packages, and the implementation is inspired by the\n * third-party `remark-gfm` plugin.\n *\n * The reason why we don't use `remark-gfm` directly is because we only want to opt into the\n * specific GFM features the editor supports, rather than enabling all of them at once.\n *\n * @param options Configuration options for the plugin.\n */\nfunction remarkStrikethrough(this: Processor, options: Options = {}) {\n const data = this.data()\n\n const micromarkExtensions = data.micromarkExtensions ?? (data.micromarkExtensions = [])\n const fromMarkdownExtensions = data.fromMarkdownExtensions ?? (data.fromMarkdownExtensions = [])\n const toMarkdownExtensions = data.toMarkdownExtensions ?? (data.toMarkdownExtensions = [])\n\n micromarkExtensions.push(gfmStrikethrough(options))\n fromMarkdownExtensions.push(gfmStrikethroughFromMarkdown())\n toMarkdownExtensions.push(gfmStrikethroughToMarkdown())\n}\n\nexport { remarkStrikethrough }\n"],"mappings":";;;;;;;;;;;;;;;;AAsBA,SAAS,oBAAqC,UAAmB,EAAE,EAAE;CACjE,MAAM,OAAO,KAAK,MAAM;CAExB,MAAM,sBAAsB,KAAK,wBAAwB,KAAK,sBAAsB,EAAE;CACtF,MAAM,yBAAyB,KAAK,2BAA2B,KAAK,yBAAyB,EAAE;CAC/F,MAAM,uBAAuB,KAAK,yBAAyB,KAAK,uBAAuB,EAAE;CAEzF,oBAAoB,KAAK,iBAAiB,QAAQ,CAAC;CACnD,uBAAuB,KAAK,8BAA8B,CAAC;CAC3D,qBAAqB,KAAK,4BAA4B,CAAC"}
|
|
@@ -18,9 +18,9 @@ type MarkdownSerializerReturnType = {
|
|
|
18
18
|
* The bullet list marker for both standard and task list items.
|
|
19
19
|
*/
|
|
20
20
|
/**
|
|
21
|
-
* Create an HTML to Markdown serializer with the
|
|
21
|
+
* Create an HTML to Markdown serializer with the unified ecosystem for both a rich-text editor, and
|
|
22
22
|
* a plain-text editor. The editor schema is used to detect which nodes and marks are available in
|
|
23
|
-
* the editor, and only parses the input with the minimal required
|
|
23
|
+
* the editor, and only parses the input with the minimal required plugins.
|
|
24
24
|
*
|
|
25
25
|
* **Note:** Unlike the HTML serializer, built-in rules that are not supported by the schema are not
|
|
26
26
|
* disabled because if the schema does not support certain nodes/marks, the parsing rules don't have
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","names":[],"sources":["../../../src/serializers/markdown/markdown.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","names":[],"sources":["../../../src/serializers/markdown/markdown.ts"],"mappings":";;;;;AAc8C;KAUzC,4BAAA;;;;AAqBmB;;;;EAbpB,SAAA,GAAY,IAAA;AAAA;;;;;;;;;;;;;;;;;iBAgJP,wBAAA,CAAyB,MAAA,EAAQ,MAAA,GAAS,4BAAA;;;;;;;;iBAuE1C,6BAAA,CAA8B,MAAA,EAAQ,MAAA,GAAM,4BAAA"}
|