@ckeditor/ckeditor5-markdown-gfm 40.0.0 → 40.2.0
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 +25 -25
- package/LICENSE.md +4 -4
- package/build/markdown-gfm.js +1 -1
- package/package.json +2 -2
- package/src/augmentation.d.ts +11 -10
- package/src/augmentation.js +5 -5
- package/src/gfmdataprocessor.d.ts +62 -62
- package/src/gfmdataprocessor.js +72 -72
- package/src/html2markdown/html2markdown.d.ts +10 -10
- package/src/html2markdown/html2markdown.js +126 -126
- package/src/index.d.ts +10 -9
- package/src/index.js +10 -9
- package/src/markdown.d.ts +23 -23
- package/src/markdown.js +29 -29
- package/src/markdown2html/markdown2html.d.ts +13 -13
- package/src/markdown2html/markdown2html.js +44 -44
- package/src/pastefrommarkdownexperimental.d.ts +74 -0
- package/src/pastefrommarkdownexperimental.js +147 -0
- package/build/markdown-gfm.js.map +0 -1
package/src/markdown.js
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module markdown-gfm/markdown
|
7
|
-
*/
|
8
|
-
import { Plugin } from 'ckeditor5/src/core';
|
9
|
-
import GFMDataProcessor from './gfmdataprocessor';
|
10
|
-
/**
|
11
|
-
* The GitHub Flavored Markdown (GFM) plugin.
|
12
|
-
*
|
13
|
-
* For a detailed overview, check the {@glink features/markdown Markdown feature} guide.
|
14
|
-
*/
|
15
|
-
export default class Markdown extends Plugin {
|
16
|
-
/**
|
17
|
-
* @inheritDoc
|
18
|
-
*/
|
19
|
-
constructor(editor) {
|
20
|
-
super(editor);
|
21
|
-
editor.data.processor = new GFMDataProcessor(editor.data.viewDocument);
|
22
|
-
}
|
23
|
-
/**
|
24
|
-
* @inheritDoc
|
25
|
-
*/
|
26
|
-
static get pluginName() {
|
27
|
-
return 'Markdown';
|
28
|
-
}
|
29
|
-
}
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module markdown-gfm/markdown
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import GFMDataProcessor from './gfmdataprocessor';
|
10
|
+
/**
|
11
|
+
* The GitHub Flavored Markdown (GFM) plugin.
|
12
|
+
*
|
13
|
+
* For a detailed overview, check the {@glink features/markdown Markdown feature} guide.
|
14
|
+
*/
|
15
|
+
export default class Markdown extends Plugin {
|
16
|
+
/**
|
17
|
+
* @inheritDoc
|
18
|
+
*/
|
19
|
+
constructor(editor) {
|
20
|
+
super(editor);
|
21
|
+
editor.data.processor = new GFMDataProcessor(editor.data.viewDocument);
|
22
|
+
}
|
23
|
+
/**
|
24
|
+
* @inheritDoc
|
25
|
+
*/
|
26
|
+
static get pluginName() {
|
27
|
+
return 'Markdown';
|
28
|
+
}
|
29
|
+
}
|
@@ -1,13 +1,13 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module markdown-gfm/markdown2html/markdown2html
|
7
|
-
*/
|
8
|
-
import { marked } from 'marked';
|
9
|
-
/**
|
10
|
-
* Parses markdown string to an HTML.
|
11
|
-
*/
|
12
|
-
export default function markdown2html(markdown: string): string;
|
13
|
-
export { marked };
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module markdown-gfm/markdown2html/markdown2html
|
7
|
+
*/
|
8
|
+
import { marked } from 'marked';
|
9
|
+
/**
|
10
|
+
* Parses markdown string to an HTML.
|
11
|
+
*/
|
12
|
+
export default function markdown2html(markdown: string): string;
|
13
|
+
export { marked };
|
@@ -1,44 +1,44 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module markdown-gfm/markdown2html/markdown2html
|
7
|
-
*/
|
8
|
-
import { marked } from 'marked';
|
9
|
-
// Overrides.
|
10
|
-
marked.use({
|
11
|
-
tokenizer: {
|
12
|
-
// Disable the autolink rule in the lexer.
|
13
|
-
autolink: () => null,
|
14
|
-
url: () => null
|
15
|
-
},
|
16
|
-
renderer: {
|
17
|
-
checkbox(...args) {
|
18
|
-
// Remove bogus space after <input type="checkbox"> because it would be preserved
|
19
|
-
// by DomConverter as it's next to an inline object.
|
20
|
-
return Object.getPrototypeOf(this).checkbox.call(this, ...args).trimRight();
|
21
|
-
},
|
22
|
-
code(...args) {
|
23
|
-
// Since marked v1.2.8, every <code> gets a trailing "\n" whether it originally
|
24
|
-
// ended with one or not (see https://github.com/markedjs/marked/issues/1884 to learn why).
|
25
|
-
// This results in a redundant soft break in the model when loaded into the editor, which
|
26
|
-
// is best prevented at this stage. See https://github.com/ckeditor/ckeditor5/issues/11124.
|
27
|
-
return Object.getPrototypeOf(this).code.call(this, ...args).replace('\n</code>', '</code>');
|
28
|
-
}
|
29
|
-
}
|
30
|
-
});
|
31
|
-
/**
|
32
|
-
* Parses markdown string to an HTML.
|
33
|
-
*/
|
34
|
-
export default function markdown2html(markdown) {
|
35
|
-
const options = {
|
36
|
-
gfm: true,
|
37
|
-
breaks: true,
|
38
|
-
tables: true,
|
39
|
-
xhtml: true,
|
40
|
-
headerIds: false
|
41
|
-
};
|
42
|
-
return marked.parse(markdown, options);
|
43
|
-
}
|
44
|
-
export { marked };
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module markdown-gfm/markdown2html/markdown2html
|
7
|
+
*/
|
8
|
+
import { marked } from 'marked';
|
9
|
+
// Overrides.
|
10
|
+
marked.use({
|
11
|
+
tokenizer: {
|
12
|
+
// Disable the autolink rule in the lexer.
|
13
|
+
autolink: () => null,
|
14
|
+
url: () => null
|
15
|
+
},
|
16
|
+
renderer: {
|
17
|
+
checkbox(...args) {
|
18
|
+
// Remove bogus space after <input type="checkbox"> because it would be preserved
|
19
|
+
// by DomConverter as it's next to an inline object.
|
20
|
+
return Object.getPrototypeOf(this).checkbox.call(this, ...args).trimRight();
|
21
|
+
},
|
22
|
+
code(...args) {
|
23
|
+
// Since marked v1.2.8, every <code> gets a trailing "\n" whether it originally
|
24
|
+
// ended with one or not (see https://github.com/markedjs/marked/issues/1884 to learn why).
|
25
|
+
// This results in a redundant soft break in the model when loaded into the editor, which
|
26
|
+
// is best prevented at this stage. See https://github.com/ckeditor/ckeditor5/issues/11124.
|
27
|
+
return Object.getPrototypeOf(this).code.call(this, ...args).replace('\n</code>', '</code>');
|
28
|
+
}
|
29
|
+
}
|
30
|
+
});
|
31
|
+
/**
|
32
|
+
* Parses markdown string to an HTML.
|
33
|
+
*/
|
34
|
+
export default function markdown2html(markdown) {
|
35
|
+
const options = {
|
36
|
+
gfm: true,
|
37
|
+
breaks: true,
|
38
|
+
tables: true,
|
39
|
+
xhtml: true,
|
40
|
+
headerIds: false
|
41
|
+
};
|
42
|
+
return marked.parse(markdown, options);
|
43
|
+
}
|
44
|
+
export { marked };
|
@@ -0,0 +1,74 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module markdown-gfm/pastefrommarkdownexperimental
|
7
|
+
*/
|
8
|
+
import { Plugin, type Editor } from 'ckeditor5/src/core';
|
9
|
+
import { ClipboardPipeline } from 'ckeditor5/src/clipboard';
|
10
|
+
/**
|
11
|
+
* The GitHub Flavored Markdown (GFM) paste plugin.
|
12
|
+
*
|
13
|
+
* For a detailed overview, check the {@glink features/pasting/paste-markdown Paste Markdown feature} guide.
|
14
|
+
*/
|
15
|
+
export default class PasteFromMarkdownExperimental extends Plugin {
|
16
|
+
/**
|
17
|
+
* @internal
|
18
|
+
*/
|
19
|
+
private _gfmDataProcessor;
|
20
|
+
/**
|
21
|
+
* @inheritDoc
|
22
|
+
*/
|
23
|
+
constructor(editor: Editor);
|
24
|
+
/**
|
25
|
+
* @inheritDoc
|
26
|
+
*/
|
27
|
+
static get pluginName(): "PasteFromMarkdownExperimental";
|
28
|
+
/**
|
29
|
+
* @inheritDoc
|
30
|
+
*/
|
31
|
+
static get requires(): readonly [typeof ClipboardPipeline];
|
32
|
+
/**
|
33
|
+
* @inheritDoc
|
34
|
+
*/
|
35
|
+
init(): void;
|
36
|
+
/**
|
37
|
+
* Determines if code copied from a website in `text/html` type can be parsed as markdown.
|
38
|
+
* It removes any OS specific HTML tags e.g. <meta> on Mac OS and <!--StartFragment--> on Windows.
|
39
|
+
* Then removes a single wrapper HTML tag or wrappers for sibling tags, and if there are no more tags left,
|
40
|
+
* returns the remaining text. Returns null, if there are any remaining HTML tags detected.
|
41
|
+
*
|
42
|
+
* @param htmlString Clipboard content in `text/html` type format.
|
43
|
+
*/
|
44
|
+
private _parseMarkdownFromHtml;
|
45
|
+
/**
|
46
|
+
* Removes OS specific tags.
|
47
|
+
*
|
48
|
+
* @param htmlString Clipboard content in `text/html` type format.
|
49
|
+
*/
|
50
|
+
private _removeOsSpecificTags;
|
51
|
+
/**
|
52
|
+
* If the input HTML string contains any first level formatting tags
|
53
|
+
* like <b>, <strong> or <i>, then we should not treat it as markdown.
|
54
|
+
*
|
55
|
+
* @param htmlString Clipboard content.
|
56
|
+
*/
|
57
|
+
private _containsOnlyAllowedFirstLevelTags;
|
58
|
+
/**
|
59
|
+
* Removes multiple HTML wrapper tags from a list of sibling HTML tags.
|
60
|
+
*
|
61
|
+
* @param htmlString Clipboard content without any OS specific tags.
|
62
|
+
*/
|
63
|
+
private _removeFirstLevelWrapperTagsAndBrs;
|
64
|
+
/**
|
65
|
+
* Determines if string contains any HTML tags.
|
66
|
+
*/
|
67
|
+
private _containsAnyRemainingHtmlTags;
|
68
|
+
/**
|
69
|
+
* Replaces the reserved HTML entities with the actual characters.
|
70
|
+
*
|
71
|
+
* @param htmlString Clipboard content without any tags.
|
72
|
+
*/
|
73
|
+
private _replaceHtmlReservedEntitiesWithCharacters;
|
74
|
+
}
|
@@ -0,0 +1,147 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module markdown-gfm/pastefrommarkdownexperimental
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import { ClipboardPipeline } from 'ckeditor5/src/clipboard';
|
10
|
+
import GFMDataProcessor from './gfmdataprocessor';
|
11
|
+
const ALLOWED_MARKDOWN_FIRST_LEVEL_TAGS = ['SPAN', 'BR', 'PRE', 'CODE'];
|
12
|
+
/**
|
13
|
+
* The GitHub Flavored Markdown (GFM) paste plugin.
|
14
|
+
*
|
15
|
+
* For a detailed overview, check the {@glink features/pasting/paste-markdown Paste Markdown feature} guide.
|
16
|
+
*/
|
17
|
+
export default class PasteFromMarkdownExperimental extends Plugin {
|
18
|
+
/**
|
19
|
+
* @inheritDoc
|
20
|
+
*/
|
21
|
+
constructor(editor) {
|
22
|
+
super(editor);
|
23
|
+
this._gfmDataProcessor = new GFMDataProcessor(editor.data.viewDocument);
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* @inheritDoc
|
27
|
+
*/
|
28
|
+
static get pluginName() {
|
29
|
+
return 'PasteFromMarkdownExperimental';
|
30
|
+
}
|
31
|
+
/**
|
32
|
+
* @inheritDoc
|
33
|
+
*/
|
34
|
+
static get requires() {
|
35
|
+
return [ClipboardPipeline];
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* @inheritDoc
|
39
|
+
*/
|
40
|
+
init() {
|
41
|
+
const editor = this.editor;
|
42
|
+
const view = editor.editing.view;
|
43
|
+
const viewDocument = view.document;
|
44
|
+
const clipboardPipeline = editor.plugins.get('ClipboardPipeline');
|
45
|
+
let shiftPressed = false;
|
46
|
+
this.listenTo(viewDocument, 'keydown', (evt, data) => {
|
47
|
+
shiftPressed = data.shiftKey;
|
48
|
+
});
|
49
|
+
this.listenTo(clipboardPipeline, 'inputTransformation', (evt, data) => {
|
50
|
+
if (shiftPressed) {
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
const dataAsTextHtml = data.dataTransfer.getData('text/html');
|
54
|
+
if (!dataAsTextHtml) {
|
55
|
+
const dataAsTextPlain = data.dataTransfer.getData('text/plain');
|
56
|
+
data.content = this._gfmDataProcessor.toView(dataAsTextPlain);
|
57
|
+
return;
|
58
|
+
}
|
59
|
+
const markdownFromHtml = this._parseMarkdownFromHtml(dataAsTextHtml);
|
60
|
+
if (markdownFromHtml) {
|
61
|
+
data.content = this._gfmDataProcessor.toView(markdownFromHtml);
|
62
|
+
}
|
63
|
+
});
|
64
|
+
}
|
65
|
+
/**
|
66
|
+
* Determines if code copied from a website in `text/html` type can be parsed as markdown.
|
67
|
+
* It removes any OS specific HTML tags e.g. <meta> on Mac OS and <!--StartFragment--> on Windows.
|
68
|
+
* Then removes a single wrapper HTML tag or wrappers for sibling tags, and if there are no more tags left,
|
69
|
+
* returns the remaining text. Returns null, if there are any remaining HTML tags detected.
|
70
|
+
*
|
71
|
+
* @param htmlString Clipboard content in `text/html` type format.
|
72
|
+
*/
|
73
|
+
_parseMarkdownFromHtml(htmlString) {
|
74
|
+
const withoutOsSpecificTags = this._removeOsSpecificTags(htmlString);
|
75
|
+
if (!this._containsOnlyAllowedFirstLevelTags(withoutOsSpecificTags)) {
|
76
|
+
return null;
|
77
|
+
}
|
78
|
+
const withoutWrapperTag = this._removeFirstLevelWrapperTagsAndBrs(withoutOsSpecificTags);
|
79
|
+
if (this._containsAnyRemainingHtmlTags(withoutWrapperTag)) {
|
80
|
+
return null;
|
81
|
+
}
|
82
|
+
return this._replaceHtmlReservedEntitiesWithCharacters(withoutWrapperTag);
|
83
|
+
}
|
84
|
+
/**
|
85
|
+
* Removes OS specific tags.
|
86
|
+
*
|
87
|
+
* @param htmlString Clipboard content in `text/html` type format.
|
88
|
+
*/
|
89
|
+
_removeOsSpecificTags(htmlString) {
|
90
|
+
// Removing <meta> tag present on Mac.
|
91
|
+
const withoutMetaTag = htmlString.replace(/^<meta\b[^>]*>/, '').trim();
|
92
|
+
// Removing <html> tag present on Windows.
|
93
|
+
const withoutHtmlTag = withoutMetaTag.replace(/^<html>/, '').replace(/<\/html>$/, '').trim();
|
94
|
+
// Removing <body> tag present on Windows.
|
95
|
+
const withoutBodyTag = withoutHtmlTag.replace(/^<body>/, '').replace(/<\/body>$/, '').trim();
|
96
|
+
// Removing <!--StartFragment--> tag present on Windows.
|
97
|
+
return withoutBodyTag.replace(/^<!--StartFragment-->/, '').replace(/<!--EndFragment-->$/, '').trim();
|
98
|
+
}
|
99
|
+
/**
|
100
|
+
* If the input HTML string contains any first level formatting tags
|
101
|
+
* like <b>, <strong> or <i>, then we should not treat it as markdown.
|
102
|
+
*
|
103
|
+
* @param htmlString Clipboard content.
|
104
|
+
*/
|
105
|
+
_containsOnlyAllowedFirstLevelTags(htmlString) {
|
106
|
+
const parser = new DOMParser();
|
107
|
+
const { body: tempElement } = parser.parseFromString(htmlString, 'text/html');
|
108
|
+
const tagNames = Array.from(tempElement.children).map(el => el.tagName);
|
109
|
+
return tagNames.every(el => ALLOWED_MARKDOWN_FIRST_LEVEL_TAGS.includes(el));
|
110
|
+
}
|
111
|
+
/**
|
112
|
+
* Removes multiple HTML wrapper tags from a list of sibling HTML tags.
|
113
|
+
*
|
114
|
+
* @param htmlString Clipboard content without any OS specific tags.
|
115
|
+
*/
|
116
|
+
_removeFirstLevelWrapperTagsAndBrs(htmlString) {
|
117
|
+
const parser = new DOMParser();
|
118
|
+
const { body: tempElement } = parser.parseFromString(htmlString, 'text/html');
|
119
|
+
const brElements = tempElement.querySelectorAll('br');
|
120
|
+
for (const br of brElements) {
|
121
|
+
br.replaceWith('\n');
|
122
|
+
}
|
123
|
+
const outerElements = tempElement.querySelectorAll(':scope > *');
|
124
|
+
for (const element of outerElements) {
|
125
|
+
const elementClone = element.cloneNode(true);
|
126
|
+
element.replaceWith(...elementClone.childNodes);
|
127
|
+
}
|
128
|
+
return tempElement.innerHTML;
|
129
|
+
}
|
130
|
+
/**
|
131
|
+
* Determines if string contains any HTML tags.
|
132
|
+
*/
|
133
|
+
_containsAnyRemainingHtmlTags(str) {
|
134
|
+
return str.includes('<');
|
135
|
+
}
|
136
|
+
/**
|
137
|
+
* Replaces the reserved HTML entities with the actual characters.
|
138
|
+
*
|
139
|
+
* @param htmlString Clipboard content without any tags.
|
140
|
+
*/
|
141
|
+
_replaceHtmlReservedEntitiesWithCharacters(htmlString) {
|
142
|
+
return htmlString
|
143
|
+
.replace(/>/g, '>')
|
144
|
+
.replace(/</g, '<')
|
145
|
+
.replace(/ /g, ' ');
|
146
|
+
}
|
147
|
+
}
|