@tiptap/extension-code-block-lowlight 3.20.3 → 3.20.4
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/dist/index.cjs +188 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +151 -0
- package/dist/index.js.map +1 -0
- package/package.json +7 -7
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
CodeBlockLowlight: () => CodeBlockLowlight,
|
|
34
|
+
default: () => index_default
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/code-block-lowlight.ts
|
|
39
|
+
var import_extension_code_block = require("@tiptap/extension-code-block");
|
|
40
|
+
|
|
41
|
+
// src/lowlight-plugin.ts
|
|
42
|
+
var import_core = require("@tiptap/core");
|
|
43
|
+
var import_state = require("@tiptap/pm/state");
|
|
44
|
+
var import_view = require("@tiptap/pm/view");
|
|
45
|
+
var import_core2 = __toESM(require("highlight.js/lib/core"), 1);
|
|
46
|
+
function parseNodes(nodes, className = []) {
|
|
47
|
+
return nodes.flatMap((node) => {
|
|
48
|
+
const classes = [...className, ...node.properties ? node.properties.className : []];
|
|
49
|
+
if (node.children) {
|
|
50
|
+
return parseNodes(node.children, classes);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
text: node.value,
|
|
54
|
+
classes
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function getHighlightNodes(result) {
|
|
59
|
+
return result.value || result.children || [];
|
|
60
|
+
}
|
|
61
|
+
function registered(aliasOrLanguage) {
|
|
62
|
+
return Boolean(import_core2.default.getLanguage(aliasOrLanguage));
|
|
63
|
+
}
|
|
64
|
+
function getDecorations({
|
|
65
|
+
doc,
|
|
66
|
+
name,
|
|
67
|
+
lowlight,
|
|
68
|
+
defaultLanguage
|
|
69
|
+
}) {
|
|
70
|
+
const decorations = [];
|
|
71
|
+
(0, import_core.findChildren)(doc, (node) => node.type.name === name).forEach((block) => {
|
|
72
|
+
var _a;
|
|
73
|
+
let from = block.pos + 1;
|
|
74
|
+
const language = block.node.attrs.language || defaultLanguage;
|
|
75
|
+
const languages = lowlight.listLanguages();
|
|
76
|
+
const nodes = language && (languages.includes(language) || registered(language) || ((_a = lowlight.registered) == null ? void 0 : _a.call(lowlight, language))) ? getHighlightNodes(lowlight.highlight(language, block.node.textContent)) : getHighlightNodes(lowlight.highlightAuto(block.node.textContent));
|
|
77
|
+
parseNodes(nodes).forEach((node) => {
|
|
78
|
+
const to = from + node.text.length;
|
|
79
|
+
if (node.classes.length) {
|
|
80
|
+
const decoration = import_view.Decoration.inline(from, to, {
|
|
81
|
+
class: node.classes.join(" ")
|
|
82
|
+
});
|
|
83
|
+
decorations.push(decoration);
|
|
84
|
+
}
|
|
85
|
+
from = to;
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
return import_view.DecorationSet.create(doc, decorations);
|
|
89
|
+
}
|
|
90
|
+
function isFunction(param) {
|
|
91
|
+
return typeof param === "function";
|
|
92
|
+
}
|
|
93
|
+
function LowlightPlugin({
|
|
94
|
+
name,
|
|
95
|
+
lowlight,
|
|
96
|
+
defaultLanguage
|
|
97
|
+
}) {
|
|
98
|
+
if (!["highlight", "highlightAuto", "listLanguages"].every((api) => isFunction(lowlight[api]))) {
|
|
99
|
+
throw Error("You should provide an instance of lowlight to use the code-block-lowlight extension");
|
|
100
|
+
}
|
|
101
|
+
const lowlightPlugin = new import_state.Plugin({
|
|
102
|
+
key: new import_state.PluginKey("lowlight"),
|
|
103
|
+
state: {
|
|
104
|
+
init: (_, { doc }) => getDecorations({
|
|
105
|
+
doc,
|
|
106
|
+
name,
|
|
107
|
+
lowlight,
|
|
108
|
+
defaultLanguage
|
|
109
|
+
}),
|
|
110
|
+
apply: (transaction, decorationSet, oldState, newState) => {
|
|
111
|
+
const oldNodeName = oldState.selection.$head.parent.type.name;
|
|
112
|
+
const newNodeName = newState.selection.$head.parent.type.name;
|
|
113
|
+
const oldNodes = (0, import_core.findChildren)(oldState.doc, (node) => node.type.name === name);
|
|
114
|
+
const newNodes = (0, import_core.findChildren)(newState.doc, (node) => node.type.name === name);
|
|
115
|
+
if (transaction.docChanged && // Apply decorations if:
|
|
116
|
+
// selection includes named node,
|
|
117
|
+
([oldNodeName, newNodeName].includes(name) || // OR transaction adds/removes named node,
|
|
118
|
+
newNodes.length !== oldNodes.length || // OR transaction has changes that completely encapsulte a node
|
|
119
|
+
// (for example, a transaction that affects the entire document).
|
|
120
|
+
// Such transactions can happen during collab syncing via y-prosemirror, for example.
|
|
121
|
+
transaction.steps.some((step) => {
|
|
122
|
+
return (
|
|
123
|
+
// @ts-ignore
|
|
124
|
+
step.from !== void 0 && // @ts-ignore
|
|
125
|
+
step.to !== void 0 && oldNodes.some((node) => {
|
|
126
|
+
return (
|
|
127
|
+
// @ts-ignore
|
|
128
|
+
node.pos >= step.from && // @ts-ignore
|
|
129
|
+
node.pos + node.node.nodeSize <= step.to
|
|
130
|
+
);
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
}))) {
|
|
134
|
+
return getDecorations({
|
|
135
|
+
doc: transaction.doc,
|
|
136
|
+
name,
|
|
137
|
+
lowlight,
|
|
138
|
+
defaultLanguage
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return decorationSet.map(transaction.mapping, transaction.doc);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
props: {
|
|
145
|
+
decorations(state) {
|
|
146
|
+
return lowlightPlugin.getState(state);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return lowlightPlugin;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/code-block-lowlight.ts
|
|
154
|
+
var CodeBlockLowlight = import_extension_code_block.CodeBlock.extend({
|
|
155
|
+
addOptions() {
|
|
156
|
+
var _a;
|
|
157
|
+
return {
|
|
158
|
+
...(_a = this.parent) == null ? void 0 : _a.call(this),
|
|
159
|
+
lowlight: {},
|
|
160
|
+
languageClassPrefix: "language-",
|
|
161
|
+
exitOnTripleEnter: true,
|
|
162
|
+
exitOnArrowDown: true,
|
|
163
|
+
defaultLanguage: null,
|
|
164
|
+
enableTabIndentation: false,
|
|
165
|
+
tabSize: 4,
|
|
166
|
+
HTMLAttributes: {}
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
addProseMirrorPlugins() {
|
|
170
|
+
var _a;
|
|
171
|
+
return [
|
|
172
|
+
...((_a = this.parent) == null ? void 0 : _a.call(this)) || [],
|
|
173
|
+
LowlightPlugin({
|
|
174
|
+
name: this.name,
|
|
175
|
+
lowlight: this.options.lowlight,
|
|
176
|
+
defaultLanguage: this.options.defaultLanguage
|
|
177
|
+
})
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// src/index.ts
|
|
183
|
+
var index_default = CodeBlockLowlight;
|
|
184
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
185
|
+
0 && (module.exports = {
|
|
186
|
+
CodeBlockLowlight
|
|
187
|
+
});
|
|
188
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/code-block-lowlight.ts","../src/lowlight-plugin.ts"],"sourcesContent":["import { CodeBlockLowlight } from './code-block-lowlight.js'\n\nexport * from './code-block-lowlight.js'\n\nexport default CodeBlockLowlight\n","import type { CodeBlockOptions } from '@tiptap/extension-code-block'\nimport { CodeBlock } from '@tiptap/extension-code-block'\n\nimport { LowlightPlugin } from './lowlight-plugin.js'\n\nexport interface CodeBlockLowlightOptions extends CodeBlockOptions {\n /**\n * The lowlight instance.\n */\n lowlight: any\n}\n\n/**\n * This extension allows you to highlight code blocks with lowlight.\n * @see https://tiptap.dev/api/nodes/code-block-lowlight\n */\nexport const CodeBlockLowlight = CodeBlock.extend<CodeBlockLowlightOptions>({\n addOptions() {\n return {\n ...this.parent?.(),\n lowlight: {},\n languageClassPrefix: 'language-',\n exitOnTripleEnter: true,\n exitOnArrowDown: true,\n defaultLanguage: null,\n enableTabIndentation: false,\n tabSize: 4,\n HTMLAttributes: {},\n }\n },\n\n addProseMirrorPlugins() {\n return [\n ...(this.parent?.() || []),\n LowlightPlugin({\n name: this.name,\n lowlight: this.options.lowlight,\n defaultLanguage: this.options.defaultLanguage,\n }),\n ]\n },\n})\n","import { findChildren } from '@tiptap/core'\nimport type { Node as ProsemirrorNode } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n// @ts-ignore\nimport highlight from 'highlight.js/lib/core'\n\nfunction parseNodes(nodes: any[], className: string[] = []): { text: string; classes: string[] }[] {\n return nodes.flatMap(node => {\n const classes = [...className, ...(node.properties ? node.properties.className : [])]\n\n if (node.children) {\n return parseNodes(node.children, classes)\n }\n\n return {\n text: node.value,\n classes,\n }\n })\n}\n\nfunction getHighlightNodes(result: any) {\n // `.value` for lowlight v1, `.children` for lowlight v2\n return result.value || result.children || []\n}\n\nfunction registered(aliasOrLanguage: string) {\n return Boolean(highlight.getLanguage(aliasOrLanguage))\n}\n\nfunction getDecorations({\n doc,\n name,\n lowlight,\n defaultLanguage,\n}: {\n doc: ProsemirrorNode\n name: string\n lowlight: any\n defaultLanguage: string | null | undefined\n}) {\n const decorations: Decoration[] = []\n\n findChildren(doc, node => node.type.name === name).forEach(block => {\n let from = block.pos + 1\n const language = block.node.attrs.language || defaultLanguage\n const languages = lowlight.listLanguages()\n\n const nodes =\n language && (languages.includes(language) || registered(language) || lowlight.registered?.(language))\n ? getHighlightNodes(lowlight.highlight(language, block.node.textContent))\n : getHighlightNodes(lowlight.highlightAuto(block.node.textContent))\n\n parseNodes(nodes).forEach(node => {\n const to = from + node.text.length\n\n if (node.classes.length) {\n const decoration = Decoration.inline(from, to, {\n class: node.classes.join(' '),\n })\n\n decorations.push(decoration)\n }\n\n from = to\n })\n })\n\n return DecorationSet.create(doc, decorations)\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nfunction isFunction(param: any): param is Function {\n return typeof param === 'function'\n}\n\nexport function LowlightPlugin({\n name,\n lowlight,\n defaultLanguage,\n}: {\n name: string\n lowlight: any\n defaultLanguage: string | null | undefined\n}) {\n if (!['highlight', 'highlightAuto', 'listLanguages'].every(api => isFunction(lowlight[api]))) {\n throw Error('You should provide an instance of lowlight to use the code-block-lowlight extension')\n }\n\n const lowlightPlugin: Plugin<any> = new Plugin({\n key: new PluginKey('lowlight'),\n\n state: {\n init: (_, { doc }) =>\n getDecorations({\n doc,\n name,\n lowlight,\n defaultLanguage,\n }),\n apply: (transaction, decorationSet, oldState, newState) => {\n const oldNodeName = oldState.selection.$head.parent.type.name\n const newNodeName = newState.selection.$head.parent.type.name\n const oldNodes = findChildren(oldState.doc, node => node.type.name === name)\n const newNodes = findChildren(newState.doc, node => node.type.name === name)\n\n if (\n transaction.docChanged &&\n // Apply decorations if:\n // selection includes named node,\n ([oldNodeName, newNodeName].includes(name) ||\n // OR transaction adds/removes named node,\n newNodes.length !== oldNodes.length ||\n // OR transaction has changes that completely encapsulte a node\n // (for example, a transaction that affects the entire document).\n // Such transactions can happen during collab syncing via y-prosemirror, for example.\n transaction.steps.some(step => {\n // @ts-ignore\n return (\n // @ts-ignore\n step.from !== undefined &&\n // @ts-ignore\n step.to !== undefined &&\n oldNodes.some(node => {\n // @ts-ignore\n return (\n // @ts-ignore\n node.pos >= step.from &&\n // @ts-ignore\n node.pos + node.node.nodeSize <= step.to\n )\n })\n )\n }))\n ) {\n return getDecorations({\n doc: transaction.doc,\n name,\n lowlight,\n defaultLanguage,\n })\n }\n\n return decorationSet.map(transaction.mapping, transaction.doc)\n },\n },\n\n props: {\n decorations(state) {\n return lowlightPlugin.getState(state)\n },\n },\n })\n\n return lowlightPlugin\n}\n"],"mappings":"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","names":["import_core","highlight"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _tiptap_core from '@tiptap/core';
|
|
2
|
+
import { CodeBlockOptions } from '@tiptap/extension-code-block';
|
|
3
|
+
|
|
4
|
+
interface CodeBlockLowlightOptions extends CodeBlockOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The lowlight instance.
|
|
7
|
+
*/
|
|
8
|
+
lowlight: any;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* This extension allows you to highlight code blocks with lowlight.
|
|
12
|
+
* @see https://tiptap.dev/api/nodes/code-block-lowlight
|
|
13
|
+
*/
|
|
14
|
+
declare const CodeBlockLowlight: _tiptap_core.Node<CodeBlockLowlightOptions, any>;
|
|
15
|
+
|
|
16
|
+
export { CodeBlockLowlight, type CodeBlockLowlightOptions, CodeBlockLowlight as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _tiptap_core from '@tiptap/core';
|
|
2
|
+
import { CodeBlockOptions } from '@tiptap/extension-code-block';
|
|
3
|
+
|
|
4
|
+
interface CodeBlockLowlightOptions extends CodeBlockOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The lowlight instance.
|
|
7
|
+
*/
|
|
8
|
+
lowlight: any;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* This extension allows you to highlight code blocks with lowlight.
|
|
12
|
+
* @see https://tiptap.dev/api/nodes/code-block-lowlight
|
|
13
|
+
*/
|
|
14
|
+
declare const CodeBlockLowlight: _tiptap_core.Node<CodeBlockLowlightOptions, any>;
|
|
15
|
+
|
|
16
|
+
export { CodeBlockLowlight, type CodeBlockLowlightOptions, CodeBlockLowlight as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// src/code-block-lowlight.ts
|
|
2
|
+
import { CodeBlock } from "@tiptap/extension-code-block";
|
|
3
|
+
|
|
4
|
+
// src/lowlight-plugin.ts
|
|
5
|
+
import { findChildren } from "@tiptap/core";
|
|
6
|
+
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
7
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
8
|
+
import highlight from "highlight.js/lib/core";
|
|
9
|
+
function parseNodes(nodes, className = []) {
|
|
10
|
+
return nodes.flatMap((node) => {
|
|
11
|
+
const classes = [...className, ...node.properties ? node.properties.className : []];
|
|
12
|
+
if (node.children) {
|
|
13
|
+
return parseNodes(node.children, classes);
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
text: node.value,
|
|
17
|
+
classes
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
function getHighlightNodes(result) {
|
|
22
|
+
return result.value || result.children || [];
|
|
23
|
+
}
|
|
24
|
+
function registered(aliasOrLanguage) {
|
|
25
|
+
return Boolean(highlight.getLanguage(aliasOrLanguage));
|
|
26
|
+
}
|
|
27
|
+
function getDecorations({
|
|
28
|
+
doc,
|
|
29
|
+
name,
|
|
30
|
+
lowlight,
|
|
31
|
+
defaultLanguage
|
|
32
|
+
}) {
|
|
33
|
+
const decorations = [];
|
|
34
|
+
findChildren(doc, (node) => node.type.name === name).forEach((block) => {
|
|
35
|
+
var _a;
|
|
36
|
+
let from = block.pos + 1;
|
|
37
|
+
const language = block.node.attrs.language || defaultLanguage;
|
|
38
|
+
const languages = lowlight.listLanguages();
|
|
39
|
+
const nodes = language && (languages.includes(language) || registered(language) || ((_a = lowlight.registered) == null ? void 0 : _a.call(lowlight, language))) ? getHighlightNodes(lowlight.highlight(language, block.node.textContent)) : getHighlightNodes(lowlight.highlightAuto(block.node.textContent));
|
|
40
|
+
parseNodes(nodes).forEach((node) => {
|
|
41
|
+
const to = from + node.text.length;
|
|
42
|
+
if (node.classes.length) {
|
|
43
|
+
const decoration = Decoration.inline(from, to, {
|
|
44
|
+
class: node.classes.join(" ")
|
|
45
|
+
});
|
|
46
|
+
decorations.push(decoration);
|
|
47
|
+
}
|
|
48
|
+
from = to;
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
return DecorationSet.create(doc, decorations);
|
|
52
|
+
}
|
|
53
|
+
function isFunction(param) {
|
|
54
|
+
return typeof param === "function";
|
|
55
|
+
}
|
|
56
|
+
function LowlightPlugin({
|
|
57
|
+
name,
|
|
58
|
+
lowlight,
|
|
59
|
+
defaultLanguage
|
|
60
|
+
}) {
|
|
61
|
+
if (!["highlight", "highlightAuto", "listLanguages"].every((api) => isFunction(lowlight[api]))) {
|
|
62
|
+
throw Error("You should provide an instance of lowlight to use the code-block-lowlight extension");
|
|
63
|
+
}
|
|
64
|
+
const lowlightPlugin = new Plugin({
|
|
65
|
+
key: new PluginKey("lowlight"),
|
|
66
|
+
state: {
|
|
67
|
+
init: (_, { doc }) => getDecorations({
|
|
68
|
+
doc,
|
|
69
|
+
name,
|
|
70
|
+
lowlight,
|
|
71
|
+
defaultLanguage
|
|
72
|
+
}),
|
|
73
|
+
apply: (transaction, decorationSet, oldState, newState) => {
|
|
74
|
+
const oldNodeName = oldState.selection.$head.parent.type.name;
|
|
75
|
+
const newNodeName = newState.selection.$head.parent.type.name;
|
|
76
|
+
const oldNodes = findChildren(oldState.doc, (node) => node.type.name === name);
|
|
77
|
+
const newNodes = findChildren(newState.doc, (node) => node.type.name === name);
|
|
78
|
+
if (transaction.docChanged && // Apply decorations if:
|
|
79
|
+
// selection includes named node,
|
|
80
|
+
([oldNodeName, newNodeName].includes(name) || // OR transaction adds/removes named node,
|
|
81
|
+
newNodes.length !== oldNodes.length || // OR transaction has changes that completely encapsulte a node
|
|
82
|
+
// (for example, a transaction that affects the entire document).
|
|
83
|
+
// Such transactions can happen during collab syncing via y-prosemirror, for example.
|
|
84
|
+
transaction.steps.some((step) => {
|
|
85
|
+
return (
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
step.from !== void 0 && // @ts-ignore
|
|
88
|
+
step.to !== void 0 && oldNodes.some((node) => {
|
|
89
|
+
return (
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
node.pos >= step.from && // @ts-ignore
|
|
92
|
+
node.pos + node.node.nodeSize <= step.to
|
|
93
|
+
);
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
}))) {
|
|
97
|
+
return getDecorations({
|
|
98
|
+
doc: transaction.doc,
|
|
99
|
+
name,
|
|
100
|
+
lowlight,
|
|
101
|
+
defaultLanguage
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return decorationSet.map(transaction.mapping, transaction.doc);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
props: {
|
|
108
|
+
decorations(state) {
|
|
109
|
+
return lowlightPlugin.getState(state);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return lowlightPlugin;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/code-block-lowlight.ts
|
|
117
|
+
var CodeBlockLowlight = CodeBlock.extend({
|
|
118
|
+
addOptions() {
|
|
119
|
+
var _a;
|
|
120
|
+
return {
|
|
121
|
+
...(_a = this.parent) == null ? void 0 : _a.call(this),
|
|
122
|
+
lowlight: {},
|
|
123
|
+
languageClassPrefix: "language-",
|
|
124
|
+
exitOnTripleEnter: true,
|
|
125
|
+
exitOnArrowDown: true,
|
|
126
|
+
defaultLanguage: null,
|
|
127
|
+
enableTabIndentation: false,
|
|
128
|
+
tabSize: 4,
|
|
129
|
+
HTMLAttributes: {}
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
addProseMirrorPlugins() {
|
|
133
|
+
var _a;
|
|
134
|
+
return [
|
|
135
|
+
...((_a = this.parent) == null ? void 0 : _a.call(this)) || [],
|
|
136
|
+
LowlightPlugin({
|
|
137
|
+
name: this.name,
|
|
138
|
+
lowlight: this.options.lowlight,
|
|
139
|
+
defaultLanguage: this.options.defaultLanguage
|
|
140
|
+
})
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// src/index.ts
|
|
146
|
+
var index_default = CodeBlockLowlight;
|
|
147
|
+
export {
|
|
148
|
+
CodeBlockLowlight,
|
|
149
|
+
index_default as default
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/code-block-lowlight.ts","../src/lowlight-plugin.ts","../src/index.ts"],"sourcesContent":["import type { CodeBlockOptions } from '@tiptap/extension-code-block'\nimport { CodeBlock } from '@tiptap/extension-code-block'\n\nimport { LowlightPlugin } from './lowlight-plugin.js'\n\nexport interface CodeBlockLowlightOptions extends CodeBlockOptions {\n /**\n * The lowlight instance.\n */\n lowlight: any\n}\n\n/**\n * This extension allows you to highlight code blocks with lowlight.\n * @see https://tiptap.dev/api/nodes/code-block-lowlight\n */\nexport const CodeBlockLowlight = CodeBlock.extend<CodeBlockLowlightOptions>({\n addOptions() {\n return {\n ...this.parent?.(),\n lowlight: {},\n languageClassPrefix: 'language-',\n exitOnTripleEnter: true,\n exitOnArrowDown: true,\n defaultLanguage: null,\n enableTabIndentation: false,\n tabSize: 4,\n HTMLAttributes: {},\n }\n },\n\n addProseMirrorPlugins() {\n return [\n ...(this.parent?.() || []),\n LowlightPlugin({\n name: this.name,\n lowlight: this.options.lowlight,\n defaultLanguage: this.options.defaultLanguage,\n }),\n ]\n },\n})\n","import { findChildren } from '@tiptap/core'\nimport type { Node as ProsemirrorNode } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n// @ts-ignore\nimport highlight from 'highlight.js/lib/core'\n\nfunction parseNodes(nodes: any[], className: string[] = []): { text: string; classes: string[] }[] {\n return nodes.flatMap(node => {\n const classes = [...className, ...(node.properties ? node.properties.className : [])]\n\n if (node.children) {\n return parseNodes(node.children, classes)\n }\n\n return {\n text: node.value,\n classes,\n }\n })\n}\n\nfunction getHighlightNodes(result: any) {\n // `.value` for lowlight v1, `.children` for lowlight v2\n return result.value || result.children || []\n}\n\nfunction registered(aliasOrLanguage: string) {\n return Boolean(highlight.getLanguage(aliasOrLanguage))\n}\n\nfunction getDecorations({\n doc,\n name,\n lowlight,\n defaultLanguage,\n}: {\n doc: ProsemirrorNode\n name: string\n lowlight: any\n defaultLanguage: string | null | undefined\n}) {\n const decorations: Decoration[] = []\n\n findChildren(doc, node => node.type.name === name).forEach(block => {\n let from = block.pos + 1\n const language = block.node.attrs.language || defaultLanguage\n const languages = lowlight.listLanguages()\n\n const nodes =\n language && (languages.includes(language) || registered(language) || lowlight.registered?.(language))\n ? getHighlightNodes(lowlight.highlight(language, block.node.textContent))\n : getHighlightNodes(lowlight.highlightAuto(block.node.textContent))\n\n parseNodes(nodes).forEach(node => {\n const to = from + node.text.length\n\n if (node.classes.length) {\n const decoration = Decoration.inline(from, to, {\n class: node.classes.join(' '),\n })\n\n decorations.push(decoration)\n }\n\n from = to\n })\n })\n\n return DecorationSet.create(doc, decorations)\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nfunction isFunction(param: any): param is Function {\n return typeof param === 'function'\n}\n\nexport function LowlightPlugin({\n name,\n lowlight,\n defaultLanguage,\n}: {\n name: string\n lowlight: any\n defaultLanguage: string | null | undefined\n}) {\n if (!['highlight', 'highlightAuto', 'listLanguages'].every(api => isFunction(lowlight[api]))) {\n throw Error('You should provide an instance of lowlight to use the code-block-lowlight extension')\n }\n\n const lowlightPlugin: Plugin<any> = new Plugin({\n key: new PluginKey('lowlight'),\n\n state: {\n init: (_, { doc }) =>\n getDecorations({\n doc,\n name,\n lowlight,\n defaultLanguage,\n }),\n apply: (transaction, decorationSet, oldState, newState) => {\n const oldNodeName = oldState.selection.$head.parent.type.name\n const newNodeName = newState.selection.$head.parent.type.name\n const oldNodes = findChildren(oldState.doc, node => node.type.name === name)\n const newNodes = findChildren(newState.doc, node => node.type.name === name)\n\n if (\n transaction.docChanged &&\n // Apply decorations if:\n // selection includes named node,\n ([oldNodeName, newNodeName].includes(name) ||\n // OR transaction adds/removes named node,\n newNodes.length !== oldNodes.length ||\n // OR transaction has changes that completely encapsulte a node\n // (for example, a transaction that affects the entire document).\n // Such transactions can happen during collab syncing via y-prosemirror, for example.\n transaction.steps.some(step => {\n // @ts-ignore\n return (\n // @ts-ignore\n step.from !== undefined &&\n // @ts-ignore\n step.to !== undefined &&\n oldNodes.some(node => {\n // @ts-ignore\n return (\n // @ts-ignore\n node.pos >= step.from &&\n // @ts-ignore\n node.pos + node.node.nodeSize <= step.to\n )\n })\n )\n }))\n ) {\n return getDecorations({\n doc: transaction.doc,\n name,\n lowlight,\n defaultLanguage,\n })\n }\n\n return decorationSet.map(transaction.mapping, transaction.doc)\n },\n },\n\n props: {\n decorations(state) {\n return lowlightPlugin.getState(state)\n },\n },\n })\n\n return lowlightPlugin\n}\n","import { CodeBlockLowlight } from './code-block-lowlight.js'\n\nexport * from './code-block-lowlight.js'\n\nexport default CodeBlockLowlight\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/extension-code-block-lowlight",
|
|
3
3
|
"description": "code block extension for tiptap",
|
|
4
|
-
"version": "3.20.
|
|
4
|
+
"version": "3.20.4",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -32,16 +32,16 @@
|
|
|
32
32
|
],
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"lowlight": "^3.3.0",
|
|
35
|
-
"@tiptap/
|
|
36
|
-
"@tiptap/
|
|
37
|
-
"@tiptap/
|
|
35
|
+
"@tiptap/extension-code-block": "^3.20.4",
|
|
36
|
+
"@tiptap/pm": "^3.20.4",
|
|
37
|
+
"@tiptap/core": "^3.20.4"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"lowlight": "^2 || ^3",
|
|
41
41
|
"highlight.js": "^11",
|
|
42
|
-
"@tiptap/core": "^3.20.
|
|
43
|
-
"@tiptap/extension-code-block": "^3.20.
|
|
44
|
-
"@tiptap/pm": "^3.20.
|
|
42
|
+
"@tiptap/core": "^3.20.4",
|
|
43
|
+
"@tiptap/extension-code-block": "^3.20.4",
|
|
44
|
+
"@tiptap/pm": "^3.20.4"
|
|
45
45
|
},
|
|
46
46
|
"repository": {
|
|
47
47
|
"type": "git",
|