@tiptap/extension-code-block 2.0.0-beta.3 → 2.0.0-beta.33

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.
@@ -1,16 +1,18 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tiptap/core'), require('prosemirror-inputrules')) :
3
- typeof define === 'function' && define.amd ? define(['exports', '@tiptap/core', 'prosemirror-inputrules'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global['@tiptap/extension-code-block'] = {}, global.core, global.prosemirrorInputrules));
5
- }(this, (function (exports, core, prosemirrorInputrules) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tiptap/core'), require('prosemirror-state')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@tiptap/core', 'prosemirror-state'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/extension-code-block"] = {}, global.core, global.prosemirrorState));
5
+ })(this, (function (exports, core, prosemirrorState) { 'use strict';
6
6
 
7
- const backtickInputRegex = /^```(?<language>[a-z]*)? $/;
8
- const tildeInputRegex = /^~~~(?<language>[a-z]*)? $/;
7
+ const backtickInputRegex = /^```(?<language>[a-z]*)?[\s\n]$/;
8
+ const tildeInputRegex = /^~~~(?<language>[a-z]*)?[\s\n]$/;
9
9
  const CodeBlock = core.Node.create({
10
10
  name: 'codeBlock',
11
- defaultOptions: {
12
- languageClassPrefix: 'language-',
13
- HTMLAttributes: {},
11
+ addOptions() {
12
+ return {
13
+ languageClassPrefix: 'language-',
14
+ HTMLAttributes: {},
15
+ };
14
16
  },
15
17
  content: 'text*',
16
18
  marks: '',
@@ -23,14 +25,16 @@
23
25
  default: null,
24
26
  parseHTML: element => {
25
27
  var _a;
26
- const classAttribute = (_a = element.firstElementChild) === null || _a === void 0 ? void 0 : _a.getAttribute('class');
27
- if (!classAttribute) {
28
+ const { languageClassPrefix } = this.options;
29
+ const classNames = [...((_a = element.firstElementChild) === null || _a === void 0 ? void 0 : _a.classList) || []];
30
+ const languages = classNames
31
+ .filter(className => className.startsWith(languageClassPrefix))
32
+ .map(className => className.replace(languageClassPrefix, ''));
33
+ const language = languages[0];
34
+ if (!language) {
28
35
  return null;
29
36
  }
30
- const regexLanguageClassPrefix = new RegExp(`^(${this.options.languageClassPrefix})`);
31
- return {
32
- language: classAttribute.replace(regexLanguageClassPrefix, ''),
33
- };
37
+ return language;
34
38
  },
35
39
  renderHTML: attributes => {
36
40
  if (!attributes.language) {
@@ -57,10 +61,10 @@
57
61
  addCommands() {
58
62
  return {
59
63
  setCodeBlock: attributes => ({ commands }) => {
60
- return commands.setNode('codeBlock', attributes);
64
+ return commands.setNode(this.name, attributes);
61
65
  },
62
66
  toggleCodeBlock: attributes => ({ commands }) => {
63
- return commands.toggleNode('codeBlock', 'paragraph', attributes);
67
+ return commands.toggleNode(this.name, 'paragraph', attributes);
64
68
  },
65
69
  };
66
70
  },
@@ -68,10 +72,10 @@
68
72
  return {
69
73
  'Mod-Alt-c': () => this.editor.commands.toggleCodeBlock(),
70
74
  // remove code block when at start of document or code block is empty
71
- Backspace: state => {
72
- const { empty, $anchor } = state.selection;
75
+ Backspace: () => {
76
+ const { empty, $anchor } = this.editor.state.selection;
73
77
  const isAtStart = $anchor.pos === 1;
74
- if (!empty || $anchor.parent.type.name !== 'codeBlock') {
78
+ if (!empty || $anchor.parent.type.name !== this.name) {
75
79
  return false;
76
80
  }
77
81
  if (isAtStart || !$anchor.parent.textContent.length) {
@@ -79,22 +83,118 @@
79
83
  }
80
84
  return false;
81
85
  },
86
+ // escape node on triple enter
87
+ Enter: ({ editor }) => {
88
+ const { state } = editor;
89
+ const { selection } = state;
90
+ const { $from, empty } = selection;
91
+ if (!empty || $from.parent.type !== this.type) {
92
+ return false;
93
+ }
94
+ const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2;
95
+ const endsWithDoubleNewline = $from.parent.textContent.endsWith('\n\n');
96
+ if (!isAtEnd || !endsWithDoubleNewline) {
97
+ return false;
98
+ }
99
+ return editor
100
+ .chain()
101
+ .command(({ tr }) => {
102
+ tr.delete($from.pos - 2, $from.pos);
103
+ return true;
104
+ })
105
+ .exitCode()
106
+ .run();
107
+ },
108
+ // escape node on arrow down
109
+ ArrowDown: ({ editor }) => {
110
+ const { state } = editor;
111
+ const { selection, doc } = state;
112
+ const { $from, empty } = selection;
113
+ if (!empty || $from.parent.type !== this.type) {
114
+ return false;
115
+ }
116
+ const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2;
117
+ if (!isAtEnd) {
118
+ return false;
119
+ }
120
+ const after = $from.after();
121
+ if (after === undefined) {
122
+ return false;
123
+ }
124
+ const nodeAfter = doc.nodeAt(after);
125
+ if (nodeAfter) {
126
+ return false;
127
+ }
128
+ return editor.commands.exitCode();
129
+ },
82
130
  };
83
131
  },
84
132
  addInputRules() {
85
133
  return [
86
- prosemirrorInputrules.textblockTypeInputRule(backtickInputRegex, this.type, ({ groups }) => groups),
87
- prosemirrorInputrules.textblockTypeInputRule(tildeInputRegex, this.type, ({ groups }) => groups),
134
+ core.textblockTypeInputRule({
135
+ find: backtickInputRegex,
136
+ type: this.type,
137
+ getAttributes: ({ groups }) => groups,
138
+ }),
139
+ core.textblockTypeInputRule({
140
+ find: tildeInputRegex,
141
+ type: this.type,
142
+ getAttributes: ({ groups }) => groups,
143
+ }),
144
+ ];
145
+ },
146
+ addProseMirrorPlugins() {
147
+ return [
148
+ // this plugin creates a code block for pasted content from VS Code
149
+ // we can also detect the copied code language
150
+ new prosemirrorState.Plugin({
151
+ key: new prosemirrorState.PluginKey('codeBlockVSCodeHandler'),
152
+ props: {
153
+ handlePaste: (view, event) => {
154
+ if (!event.clipboardData) {
155
+ return false;
156
+ }
157
+ // don’t create a new code block within code blocks
158
+ if (this.editor.isActive(this.type.name)) {
159
+ return false;
160
+ }
161
+ const text = event.clipboardData.getData('text/plain');
162
+ const vscode = event.clipboardData.getData('vscode-editor-data');
163
+ const vscodeData = vscode
164
+ ? JSON.parse(vscode)
165
+ : undefined;
166
+ const language = vscodeData === null || vscodeData === void 0 ? void 0 : vscodeData.mode;
167
+ if (!text || !language) {
168
+ return false;
169
+ }
170
+ const { tr } = view.state;
171
+ // create an empty code block
172
+ tr.replaceSelectionWith(this.type.create({ language }));
173
+ // put cursor inside the newly created code block
174
+ tr.setSelection(prosemirrorState.TextSelection.near(tr.doc.resolve(Math.max(0, tr.selection.from - 2))));
175
+ // add text to code block
176
+ // strip carriage return chars from text pasted as code
177
+ // see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd
178
+ tr.insertText(text.replace(/\r\n?/g, '\n'));
179
+ // store meta information
180
+ // this is useful for other plugins that depends on the paste event
181
+ // like the paste rule plugin
182
+ tr.setMeta('paste', true);
183
+ view.dispatch(tr);
184
+ return true;
185
+ },
186
+ },
187
+ }),
88
188
  ];
89
189
  },
90
190
  });
91
191
 
92
192
  exports.CodeBlock = CodeBlock;
93
193
  exports.backtickInputRegex = backtickInputRegex;
94
- exports.default = CodeBlock;
194
+ exports["default"] = CodeBlock;
95
195
  exports.tildeInputRegex = tildeInputRegex;
96
196
 
97
197
  Object.defineProperty(exports, '__esModule', { value: true });
98
198
 
99
- })));
199
+ }));
100
200
  //# sourceMappingURL=tiptap-extension-code-block.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tiptap-extension-code-block.umd.js","sources":["../src/code-block.ts"],"sourcesContent":["import { Command, Node } from '@tiptap/core'\nimport { textblockTypeInputRule } from 'prosemirror-inputrules'\n\nexport interface CodeBlockOptions {\n languageClassPrefix: string,\n HTMLAttributes: {\n [key: string]: any\n },\n}\n\ndeclare module '@tiptap/core' {\n interface Commands {\n codeBlock: {\n /**\n * Set a code block\n */\n setCodeBlock: (attributes?: { language: string }) => Command,\n /**\n * Toggle a code block\n */\n toggleCodeBlock: (attributes?: { language: string }) => Command,\n }\n }\n}\n\nexport const backtickInputRegex = /^```(?<language>[a-z]*)? $/\nexport const tildeInputRegex = /^~~~(?<language>[a-z]*)? $/\n\nexport const CodeBlock = Node.create<CodeBlockOptions>({\n name: 'codeBlock',\n\n defaultOptions: {\n languageClassPrefix: 'language-',\n HTMLAttributes: {},\n },\n\n content: 'text*',\n\n marks: '',\n\n group: 'block',\n\n code: true,\n\n defining: true,\n\n addAttributes() {\n return {\n language: {\n default: null,\n parseHTML: element => {\n const classAttribute = element.firstElementChild?.getAttribute('class')\n\n if (!classAttribute) {\n return null\n }\n\n const regexLanguageClassPrefix = new RegExp(`^(${this.options.languageClassPrefix})`)\n\n return {\n language: classAttribute.replace(regexLanguageClassPrefix, ''),\n }\n },\n renderHTML: attributes => {\n if (!attributes.language) {\n return null\n }\n\n return {\n class: this.options.languageClassPrefix + attributes.language,\n }\n },\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'pre',\n preserveWhitespace: 'full',\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['pre', this.options.HTMLAttributes, ['code', HTMLAttributes, 0]]\n },\n\n addCommands() {\n return {\n setCodeBlock: attributes => ({ commands }) => {\n return commands.setNode('codeBlock', attributes)\n },\n toggleCodeBlock: attributes => ({ commands }) => {\n return commands.toggleNode('codeBlock', 'paragraph', attributes)\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Alt-c': () => this.editor.commands.toggleCodeBlock(),\n\n // remove code block when at start of document or code block is empty\n Backspace: state => {\n const { empty, $anchor } = state.selection\n const isAtStart = $anchor.pos === 1\n\n if (!empty || $anchor.parent.type.name !== 'codeBlock') {\n return false\n }\n\n if (isAtStart || !$anchor.parent.textContent.length) {\n return this.editor.commands.clearNodes()\n }\n\n return false\n },\n }\n },\n\n addInputRules() {\n return [\n textblockTypeInputRule(backtickInputRegex, this.type, ({ groups }: any) => groups),\n textblockTypeInputRule(tildeInputRegex, this.type, ({ groups }: any) => groups),\n ]\n },\n})\n"],"names":["Node","textblockTypeInputRule"],"mappings":"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"}
1
+ {"version":3,"file":"tiptap-extension-code-block.umd.js","sources":["../src/code-block.ts"],"sourcesContent":["import { Node, textblockTypeInputRule } from '@tiptap/core'\nimport { Plugin, PluginKey, TextSelection } from 'prosemirror-state'\n\nexport interface CodeBlockOptions {\n languageClassPrefix: string,\n HTMLAttributes: Record<string, any>,\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n codeBlock: {\n /**\n * Set a code block\n */\n setCodeBlock: (attributes?: { language: string }) => ReturnType,\n /**\n * Toggle a code block\n */\n toggleCodeBlock: (attributes?: { language: string }) => ReturnType,\n }\n }\n}\n\nexport const backtickInputRegex = /^```(?<language>[a-z]*)?[\\s\\n]$/\nexport const tildeInputRegex = /^~~~(?<language>[a-z]*)?[\\s\\n]$/\n\nexport const CodeBlock = Node.create<CodeBlockOptions>({\n name: 'codeBlock',\n\n addOptions() {\n return {\n languageClassPrefix: 'language-',\n HTMLAttributes: {},\n }\n },\n\n content: 'text*',\n\n marks: '',\n\n group: 'block',\n\n code: true,\n\n defining: true,\n\n addAttributes() {\n return {\n language: {\n default: null,\n parseHTML: element => {\n const { languageClassPrefix } = this.options\n const classNames = [...element.firstElementChild?.classList || []]\n const languages = classNames\n .filter(className => className.startsWith(languageClassPrefix))\n .map(className => className.replace(languageClassPrefix, ''))\n const language = languages[0]\n\n if (!language) {\n return null\n }\n\n return language\n },\n renderHTML: attributes => {\n if (!attributes.language) {\n return null\n }\n\n return {\n class: this.options.languageClassPrefix + attributes.language,\n }\n },\n },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'pre',\n preserveWhitespace: 'full',\n },\n ]\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['pre', this.options.HTMLAttributes, ['code', HTMLAttributes, 0]]\n },\n\n addCommands() {\n return {\n setCodeBlock: attributes => ({ commands }) => {\n return commands.setNode(this.name, attributes)\n },\n toggleCodeBlock: attributes => ({ commands }) => {\n return commands.toggleNode(this.name, 'paragraph', attributes)\n },\n }\n },\n\n addKeyboardShortcuts() {\n return {\n 'Mod-Alt-c': () => this.editor.commands.toggleCodeBlock(),\n\n // remove code block when at start of document or code block is empty\n Backspace: () => {\n const { empty, $anchor } = this.editor.state.selection\n const isAtStart = $anchor.pos === 1\n\n if (!empty || $anchor.parent.type.name !== this.name) {\n return false\n }\n\n if (isAtStart || !$anchor.parent.textContent.length) {\n return this.editor.commands.clearNodes()\n }\n\n return false\n },\n\n // escape node on triple enter\n Enter: ({ editor }) => {\n const { state } = editor\n const { selection } = state\n const { $from, empty } = selection\n\n if (!empty || $from.parent.type !== this.type) {\n return false\n }\n\n const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2\n const endsWithDoubleNewline = $from.parent.textContent.endsWith('\\n\\n')\n\n if (!isAtEnd || !endsWithDoubleNewline) {\n return false\n }\n\n return editor\n .chain()\n .command(({ tr }) => {\n tr.delete($from.pos - 2, $from.pos)\n\n return true\n })\n .exitCode()\n .run()\n },\n\n // escape node on arrow down\n ArrowDown: ({ editor }) => {\n const { state } = editor\n const { selection, doc } = state\n const { $from, empty } = selection\n\n if (!empty || $from.parent.type !== this.type) {\n return false\n }\n\n const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2\n\n if (!isAtEnd) {\n return false\n }\n\n const after = $from.after()\n\n if (after === undefined) {\n return false\n }\n\n const nodeAfter = doc.nodeAt(after)\n\n if (nodeAfter) {\n return false\n }\n\n return editor.commands.exitCode()\n },\n }\n },\n\n addInputRules() {\n return [\n textblockTypeInputRule({\n find: backtickInputRegex,\n type: this.type,\n getAttributes: ({ groups }) => groups,\n }),\n textblockTypeInputRule({\n find: tildeInputRegex,\n type: this.type,\n getAttributes: ({ groups }) => groups,\n }),\n ]\n },\n\n addProseMirrorPlugins() {\n return [\n // this plugin creates a code block for pasted content from VS Code\n // we can also detect the copied code language\n new Plugin({\n key: new PluginKey('codeBlockVSCodeHandler'),\n props: {\n handlePaste: (view, event) => {\n if (!event.clipboardData) {\n return false\n }\n\n // don’t create a new code block within code blocks\n if (this.editor.isActive(this.type.name)) {\n return false\n }\n\n const text = event.clipboardData.getData('text/plain')\n const vscode = event.clipboardData.getData('vscode-editor-data')\n const vscodeData = vscode\n ? JSON.parse(vscode)\n : undefined\n const language = vscodeData?.mode\n\n if (!text || !language) {\n return false\n }\n\n const { tr } = view.state\n\n // create an empty code block\n tr.replaceSelectionWith(this.type.create({ language }))\n\n // put cursor inside the newly created code block\n tr.setSelection(TextSelection.near(tr.doc.resolve(Math.max(0, tr.selection.from - 2))))\n\n // add text to code block\n // strip carriage return chars from text pasted as code\n // see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd\n tr.insertText(text.replace(/\\r\\n?/g, '\\n'))\n\n // store meta information\n // this is useful for other plugins that depends on the paste event\n // like the paste rule plugin\n tr.setMeta('paste', true)\n\n view.dispatch(tr)\n\n return true\n },\n },\n }),\n ]\n },\n})\n"],"names":["Node","textblockTypeInputRule","Plugin","PluginKey","TextSelection"],"mappings":";;;;;;QAuBa,kBAAkB,GAAG,kCAAiC;QACtD,eAAe,GAAG,kCAAiC;QAEnD,SAAS,GAAGA,SAAI,CAAC,MAAM,CAAmB;MACrD,IAAI,EAAE,WAAW;MAEjB,UAAU;UACR,OAAO;cACL,mBAAmB,EAAE,WAAW;cAChC,cAAc,EAAE,EAAE;WACnB,CAAA;OACF;MAED,OAAO,EAAE,OAAO;MAEhB,KAAK,EAAE,EAAE;MAET,KAAK,EAAE,OAAO;MAEd,IAAI,EAAE,IAAI;MAEV,QAAQ,EAAE,IAAI;MAEd,aAAa;UACX,OAAO;cACL,QAAQ,EAAE;kBACR,OAAO,EAAE,IAAI;kBACb,SAAS,EAAE,OAAO;;sBAChB,MAAM,EAAE,mBAAmB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;sBAC5C,MAAM,UAAU,GAAG,CAAC,GAAG,CAAA,MAAA,OAAO,CAAC,iBAAiB,0CAAE,SAAS,KAAI,EAAE,CAAC,CAAA;sBAClE,MAAM,SAAS,GAAG,UAAU;2BACzB,MAAM,CAAC,SAAS,IAAI,SAAS,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;2BAC9D,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAA;sBAC/D,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;sBAE7B,IAAI,CAAC,QAAQ,EAAE;0BACb,OAAO,IAAI,CAAA;uBACZ;sBAED,OAAO,QAAQ,CAAA;mBAChB;kBACD,UAAU,EAAE,UAAU;sBACpB,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE;0BACxB,OAAO,IAAI,CAAA;uBACZ;sBAED,OAAO;0BACL,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB,GAAG,UAAU,CAAC,QAAQ;uBAC9D,CAAA;mBACF;eACF;WACF,CAAA;OACF;MAED,SAAS;UACP,OAAO;cACL;kBACE,GAAG,EAAE,KAAK;kBACV,kBAAkB,EAAE,MAAM;eAC3B;WACF,CAAA;OACF;MAED,UAAU,CAAC,EAAE,cAAc,EAAE;UAC3B,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,CAAA;OACzE;MAED,WAAW;UACT,OAAO;cACL,YAAY,EAAE,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE;kBACvC,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;eAC/C;cACD,eAAe,EAAE,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE;kBAC1C,OAAO,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;eAC/D;WACF,CAAA;OACF;MAED,oBAAoB;UAClB,OAAO;cACL,WAAW,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE;;cAGzD,SAAS,EAAE;kBACT,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAA;kBACtD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,KAAK,CAAC,CAAA;kBAEnC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;sBACpD,OAAO,KAAK,CAAA;mBACb;kBAED,IAAI,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE;sBACnD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAA;mBACzC;kBAED,OAAO,KAAK,CAAA;eACb;;cAGD,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE;kBAChB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAA;kBACxB,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAA;kBAC3B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,SAAS,CAAA;kBAElC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;sBAC7C,OAAO,KAAK,CAAA;mBACb;kBAED,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAA;kBAChE,MAAM,qBAAqB,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;kBAEvE,IAAI,CAAC,OAAO,IAAI,CAAC,qBAAqB,EAAE;sBACtC,OAAO,KAAK,CAAA;mBACb;kBAED,OAAO,MAAM;uBACV,KAAK,EAAE;uBACP,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;sBACd,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;sBAEnC,OAAO,IAAI,CAAA;mBACZ,CAAC;uBACD,QAAQ,EAAE;uBACV,GAAG,EAAE,CAAA;eACT;;cAGD,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE;kBACpB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAA;kBACxB,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,KAAK,CAAA;kBAChC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,SAAS,CAAA;kBAElC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE;sBAC7C,OAAO,KAAK,CAAA;mBACb;kBAED,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAA;kBAEhE,IAAI,CAAC,OAAO,EAAE;sBACZ,OAAO,KAAK,CAAA;mBACb;kBAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;kBAE3B,IAAI,KAAK,KAAK,SAAS,EAAE;sBACvB,OAAO,KAAK,CAAA;mBACb;kBAED,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;kBAEnC,IAAI,SAAS,EAAE;sBACb,OAAO,KAAK,CAAA;mBACb;kBAED,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAA;eAClC;WACF,CAAA;OACF;MAED,aAAa;UACX,OAAO;cACLC,2BAAsB,CAAC;kBACrB,IAAI,EAAE,kBAAkB;kBACxB,IAAI,EAAE,IAAI,CAAC,IAAI;kBACf,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM;eACtC,CAAC;cACFA,2BAAsB,CAAC;kBACrB,IAAI,EAAE,eAAe;kBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;kBACf,aAAa,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM;eACtC,CAAC;WACH,CAAA;OACF;MAED,qBAAqB;UACnB,OAAO;;;cAGL,IAAIC,uBAAM,CAAC;kBACT,GAAG,EAAE,IAAIC,0BAAS,CAAC,wBAAwB,CAAC;kBAC5C,KAAK,EAAE;sBACL,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK;0BACvB,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE;8BACxB,OAAO,KAAK,CAAA;2BACb;;0BAGD,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;8BACxC,OAAO,KAAK,CAAA;2BACb;0BAED,MAAM,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;0BACtD,MAAM,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;0BAChE,MAAM,UAAU,GAAG,MAAM;gCACrB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;gCAClB,SAAS,CAAA;0BACb,MAAM,QAAQ,GAAG,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,IAAI,CAAA;0BAEjC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;8BACtB,OAAO,KAAK,CAAA;2BACb;0BAED,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;;0BAGzB,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;;0BAGvD,EAAE,CAAC,YAAY,CAACC,8BAAa,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;;;;0BAKvF,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;;;;0BAK3C,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;0BAEzB,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;0BAEjB,OAAO,IAAI,CAAA;uBACZ;mBACF;eACF,CAAC;WACH,CAAA;OACF;GACF;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiptap/extension-code-block",
3
3
  "description": "code block extension for tiptap",
4
- "version": "2.0.0-beta.3",
4
+ "version": "2.0.0-beta.33",
5
5
  "homepage": "https://tiptap.dev",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -15,7 +15,6 @@
15
15
  "main": "dist/tiptap-extension-code-block.cjs.js",
16
16
  "umd": "dist/tiptap-extension-code-block.umd.js",
17
17
  "module": "dist/tiptap-extension-code-block.esm.js",
18
- "unpkg": "dist/tiptap-extension-code-block.bundle.umd.min.js",
19
18
  "types": "dist/packages/extension-code-block/src/index.d.ts",
20
19
  "files": [
21
20
  "src",
@@ -25,7 +24,12 @@
25
24
  "@tiptap/core": "^2.0.0-beta.1"
26
25
  },
27
26
  "dependencies": {
28
- "prosemirror-inputrules": "^1.1.3"
27
+ "prosemirror-state": "^1.3.4"
29
28
  },
30
- "gitHead": "cdf977a547a4d1a5c9120a0a6388e4c6c2285538"
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/ueberdosis/tiptap",
32
+ "directory": "packages/extension-code-block"
33
+ },
34
+ "gitHead": "8844627773ac1cfb0d01eaf1f52b3be937701b2d"
31
35
  }
package/src/code-block.ts CHANGED
@@ -1,37 +1,37 @@
1
- import { Command, Node } from '@tiptap/core'
2
- import { textblockTypeInputRule } from 'prosemirror-inputrules'
1
+ import { Node, textblockTypeInputRule } from '@tiptap/core'
2
+ import { Plugin, PluginKey, TextSelection } from 'prosemirror-state'
3
3
 
4
4
  export interface CodeBlockOptions {
5
5
  languageClassPrefix: string,
6
- HTMLAttributes: {
7
- [key: string]: any
8
- },
6
+ HTMLAttributes: Record<string, any>,
9
7
  }
10
8
 
11
9
  declare module '@tiptap/core' {
12
- interface Commands {
10
+ interface Commands<ReturnType> {
13
11
  codeBlock: {
14
12
  /**
15
13
  * Set a code block
16
14
  */
17
- setCodeBlock: (attributes?: { language: string }) => Command,
15
+ setCodeBlock: (attributes?: { language: string }) => ReturnType,
18
16
  /**
19
17
  * Toggle a code block
20
18
  */
21
- toggleCodeBlock: (attributes?: { language: string }) => Command,
19
+ toggleCodeBlock: (attributes?: { language: string }) => ReturnType,
22
20
  }
23
21
  }
24
22
  }
25
23
 
26
- export const backtickInputRegex = /^```(?<language>[a-z]*)? $/
27
- export const tildeInputRegex = /^~~~(?<language>[a-z]*)? $/
24
+ export const backtickInputRegex = /^```(?<language>[a-z]*)?[\s\n]$/
25
+ export const tildeInputRegex = /^~~~(?<language>[a-z]*)?[\s\n]$/
28
26
 
29
27
  export const CodeBlock = Node.create<CodeBlockOptions>({
30
28
  name: 'codeBlock',
31
29
 
32
- defaultOptions: {
33
- languageClassPrefix: 'language-',
34
- HTMLAttributes: {},
30
+ addOptions() {
31
+ return {
32
+ languageClassPrefix: 'language-',
33
+ HTMLAttributes: {},
34
+ }
35
35
  },
36
36
 
37
37
  content: 'text*',
@@ -49,17 +49,18 @@ export const CodeBlock = Node.create<CodeBlockOptions>({
49
49
  language: {
50
50
  default: null,
51
51
  parseHTML: element => {
52
- const classAttribute = element.firstElementChild?.getAttribute('class')
53
-
54
- if (!classAttribute) {
52
+ const { languageClassPrefix } = this.options
53
+ const classNames = [...element.firstElementChild?.classList || []]
54
+ const languages = classNames
55
+ .filter(className => className.startsWith(languageClassPrefix))
56
+ .map(className => className.replace(languageClassPrefix, ''))
57
+ const language = languages[0]
58
+
59
+ if (!language) {
55
60
  return null
56
61
  }
57
62
 
58
- const regexLanguageClassPrefix = new RegExp(`^(${this.options.languageClassPrefix})`)
59
-
60
- return {
61
- language: classAttribute.replace(regexLanguageClassPrefix, ''),
62
- }
63
+ return language
63
64
  },
64
65
  renderHTML: attributes => {
65
66
  if (!attributes.language) {
@@ -90,10 +91,10 @@ export const CodeBlock = Node.create<CodeBlockOptions>({
90
91
  addCommands() {
91
92
  return {
92
93
  setCodeBlock: attributes => ({ commands }) => {
93
- return commands.setNode('codeBlock', attributes)
94
+ return commands.setNode(this.name, attributes)
94
95
  },
95
96
  toggleCodeBlock: attributes => ({ commands }) => {
96
- return commands.toggleNode('codeBlock', 'paragraph', attributes)
97
+ return commands.toggleNode(this.name, 'paragraph', attributes)
97
98
  },
98
99
  }
99
100
  },
@@ -103,11 +104,11 @@ export const CodeBlock = Node.create<CodeBlockOptions>({
103
104
  'Mod-Alt-c': () => this.editor.commands.toggleCodeBlock(),
104
105
 
105
106
  // remove code block when at start of document or code block is empty
106
- Backspace: state => {
107
- const { empty, $anchor } = state.selection
107
+ Backspace: () => {
108
+ const { empty, $anchor } = this.editor.state.selection
108
109
  const isAtStart = $anchor.pos === 1
109
110
 
110
- if (!empty || $anchor.parent.type.name !== 'codeBlock') {
111
+ if (!empty || $anchor.parent.type.name !== this.name) {
111
112
  return false
112
113
  }
113
114
 
@@ -117,13 +118,135 @@ export const CodeBlock = Node.create<CodeBlockOptions>({
117
118
 
118
119
  return false
119
120
  },
121
+
122
+ // escape node on triple enter
123
+ Enter: ({ editor }) => {
124
+ const { state } = editor
125
+ const { selection } = state
126
+ const { $from, empty } = selection
127
+
128
+ if (!empty || $from.parent.type !== this.type) {
129
+ return false
130
+ }
131
+
132
+ const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2
133
+ const endsWithDoubleNewline = $from.parent.textContent.endsWith('\n\n')
134
+
135
+ if (!isAtEnd || !endsWithDoubleNewline) {
136
+ return false
137
+ }
138
+
139
+ return editor
140
+ .chain()
141
+ .command(({ tr }) => {
142
+ tr.delete($from.pos - 2, $from.pos)
143
+
144
+ return true
145
+ })
146
+ .exitCode()
147
+ .run()
148
+ },
149
+
150
+ // escape node on arrow down
151
+ ArrowDown: ({ editor }) => {
152
+ const { state } = editor
153
+ const { selection, doc } = state
154
+ const { $from, empty } = selection
155
+
156
+ if (!empty || $from.parent.type !== this.type) {
157
+ return false
158
+ }
159
+
160
+ const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2
161
+
162
+ if (!isAtEnd) {
163
+ return false
164
+ }
165
+
166
+ const after = $from.after()
167
+
168
+ if (after === undefined) {
169
+ return false
170
+ }
171
+
172
+ const nodeAfter = doc.nodeAt(after)
173
+
174
+ if (nodeAfter) {
175
+ return false
176
+ }
177
+
178
+ return editor.commands.exitCode()
179
+ },
120
180
  }
121
181
  },
122
182
 
123
183
  addInputRules() {
124
184
  return [
125
- textblockTypeInputRule(backtickInputRegex, this.type, ({ groups }: any) => groups),
126
- textblockTypeInputRule(tildeInputRegex, this.type, ({ groups }: any) => groups),
185
+ textblockTypeInputRule({
186
+ find: backtickInputRegex,
187
+ type: this.type,
188
+ getAttributes: ({ groups }) => groups,
189
+ }),
190
+ textblockTypeInputRule({
191
+ find: tildeInputRegex,
192
+ type: this.type,
193
+ getAttributes: ({ groups }) => groups,
194
+ }),
195
+ ]
196
+ },
197
+
198
+ addProseMirrorPlugins() {
199
+ return [
200
+ // this plugin creates a code block for pasted content from VS Code
201
+ // we can also detect the copied code language
202
+ new Plugin({
203
+ key: new PluginKey('codeBlockVSCodeHandler'),
204
+ props: {
205
+ handlePaste: (view, event) => {
206
+ if (!event.clipboardData) {
207
+ return false
208
+ }
209
+
210
+ // don’t create a new code block within code blocks
211
+ if (this.editor.isActive(this.type.name)) {
212
+ return false
213
+ }
214
+
215
+ const text = event.clipboardData.getData('text/plain')
216
+ const vscode = event.clipboardData.getData('vscode-editor-data')
217
+ const vscodeData = vscode
218
+ ? JSON.parse(vscode)
219
+ : undefined
220
+ const language = vscodeData?.mode
221
+
222
+ if (!text || !language) {
223
+ return false
224
+ }
225
+
226
+ const { tr } = view.state
227
+
228
+ // create an empty code block
229
+ tr.replaceSelectionWith(this.type.create({ language }))
230
+
231
+ // put cursor inside the newly created code block
232
+ tr.setSelection(TextSelection.near(tr.doc.resolve(Math.max(0, tr.selection.from - 2))))
233
+
234
+ // add text to code block
235
+ // strip carriage return chars from text pasted as code
236
+ // see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd
237
+ tr.insertText(text.replace(/\r\n?/g, '\n'))
238
+
239
+ // store meta information
240
+ // this is useful for other plugins that depends on the paste event
241
+ // like the paste rule plugin
242
+ tr.setMeta('paste', true)
243
+
244
+ view.dispatch(tr)
245
+
246
+ return true
247
+ },
248
+ },
249
+ }),
127
250
  ]
128
251
  },
129
252
  })
package/CHANGELOG.md DELETED
@@ -1,134 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
- See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
-
6
- # [2.0.0-beta.3](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-beta.2...@tiptap/extension-code-block@2.0.0-beta.3) (2021-04-11)
7
-
8
-
9
- ### Bug Fixes
10
-
11
- * remove codeblock when at start of document, fix [#262](https://github.com/ueberdosis/tiptap-next/issues/262) ([92f6ea2](https://github.com/ueberdosis/tiptap-next/commit/92f6ea25cc7623d0bd34f5a2342be6f5aae951aa))
12
-
13
-
14
-
15
-
16
-
17
- # [2.0.0-beta.2](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-beta.1...@tiptap/extension-code-block@2.0.0-beta.2) (2021-04-02)
18
-
19
- **Note:** Version bump only for package @tiptap/extension-code-block
20
-
21
-
22
-
23
-
24
-
25
- # [2.0.0-beta.1](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.11...@tiptap/extension-code-block@2.0.0-beta.1) (2021-03-05)
26
-
27
- **Note:** Version bump only for package @tiptap/extension-code-block
28
-
29
-
30
-
31
-
32
-
33
- # [2.0.0-alpha.11](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.10...@tiptap/extension-code-block@2.0.0-alpha.11) (2021-02-16)
34
-
35
- **Note:** Version bump only for package @tiptap/extension-code-block
36
-
37
-
38
-
39
-
40
-
41
- # [2.0.0-alpha.10](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.9...@tiptap/extension-code-block@2.0.0-alpha.10) (2021-02-07)
42
-
43
- **Note:** Version bump only for package @tiptap/extension-code-block
44
-
45
-
46
-
47
-
48
-
49
- # [2.0.0-alpha.9](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.8...@tiptap/extension-code-block@2.0.0-alpha.9) (2021-02-05)
50
-
51
- **Note:** Version bump only for package @tiptap/extension-code-block
52
-
53
-
54
-
55
-
56
-
57
- # [2.0.0-alpha.8](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.7...@tiptap/extension-code-block@2.0.0-alpha.8) (2021-01-29)
58
-
59
- **Note:** Version bump only for package @tiptap/extension-code-block
60
-
61
-
62
-
63
-
64
-
65
- # [2.0.0-alpha.7](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.6...@tiptap/extension-code-block@2.0.0-alpha.7) (2021-01-29)
66
-
67
- **Note:** Version bump only for package @tiptap/extension-code-block
68
-
69
-
70
-
71
-
72
-
73
- # [2.0.0-alpha.6](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.5...@tiptap/extension-code-block@2.0.0-alpha.6) (2021-01-28)
74
-
75
- **Note:** Version bump only for package @tiptap/extension-code-block
76
-
77
-
78
-
79
-
80
-
81
- # [2.0.0-alpha.5](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.4...@tiptap/extension-code-block@2.0.0-alpha.5) (2020-12-18)
82
-
83
- **Note:** Version bump only for package @tiptap/extension-code-block
84
-
85
-
86
-
87
-
88
-
89
- # [2.0.0-alpha.4](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.3...@tiptap/extension-code-block@2.0.0-alpha.4) (2020-12-02)
90
-
91
- **Note:** Version bump only for package @tiptap/extension-code-block
92
-
93
-
94
-
95
-
96
-
97
- # [2.0.0-alpha.3](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.2...@tiptap/extension-code-block@2.0.0-alpha.3) (2020-11-19)
98
-
99
- **Note:** Version bump only for package @tiptap/extension-code-block
100
-
101
-
102
-
103
-
104
-
105
- # [2.0.0-alpha.2](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@2.0.0-alpha.1...@tiptap/extension-code-block@2.0.0-alpha.2) (2020-11-19)
106
-
107
- **Note:** Version bump only for package @tiptap/extension-code-block
108
-
109
-
110
-
111
-
112
-
113
- # [2.0.0-alpha.1](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@1.0.0-alpha.2...@tiptap/extension-code-block@2.0.0-alpha.1) (2020-11-18)
114
-
115
- **Note:** Version bump only for package @tiptap/extension-code-block
116
-
117
-
118
-
119
-
120
-
121
- # [1.0.0-alpha.2](https://github.com/ueberdosis/tiptap-next/compare/@tiptap/extension-code-block@1.0.0-alpha.1...@tiptap/extension-code-block@1.0.0-alpha.2) (2020-11-16)
122
-
123
- **Note:** Version bump only for package @tiptap/extension-code-block
124
-
125
-
126
-
127
-
128
-
129
- # 1.0.0-alpha.1 (2020-11-16)
130
-
131
-
132
- ### Reverts
133
-
134
- * Revert "use global namespace" ([0c9ce26](https://github.com/ueberdosis/tiptap-next/commit/0c9ce26c02c07d88a757c01b0a9d7f9e2b0b7502))