@ckeditor/ckeditor5-markdown-gfm 0.0.0-internal-20241017.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 +4 -0
- package/LICENSE.md +23 -0
- package/README.md +27 -0
- package/build/markdown-gfm.js +4 -0
- package/ckeditor5-metadata.json +11 -0
- package/dist/augmentation.d.ts +15 -0
- package/dist/gfmdataprocessor.d.ts +74 -0
- package/dist/html2markdown/html2markdown.d.ts +23 -0
- package/dist/index-content.css +4 -0
- package/dist/index-editor.css +4 -0
- package/dist/index.css +4 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +402 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +31 -0
- package/dist/markdown2html/markdown2html.d.ts +17 -0
- package/dist/pastefrommarkdownexperimental.d.ts +82 -0
- package/package.json +44 -0
- package/src/augmentation.d.ts +11 -0
- package/src/augmentation.js +5 -0
- package/src/gfmdataprocessor.d.ts +70 -0
- package/src/gfmdataprocessor.js +74 -0
- package/src/html2markdown/html2markdown.d.ts +19 -0
- package/src/html2markdown/html2markdown.js +134 -0
- package/src/index.d.ts +10 -0
- package/src/index.js +10 -0
- package/src/markdown.d.ts +27 -0
- package/src/markdown.js +35 -0
- package/src/markdown2html/markdown2html.d.ts +13 -0
- package/src/markdown2html/markdown2html.js +48 -0
- package/src/pastefrommarkdownexperimental.d.ts +78 -0
- package/src/pastefrommarkdownexperimental.js +153 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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
|
+
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
|
7
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @module markdown-gfm/pastefrommarkdownexperimental
|
|
11
|
+
*/
|
|
12
|
+
import { Plugin, type Editor } from 'ckeditor5/src/core.js';
|
|
13
|
+
import { ClipboardPipeline } from 'ckeditor5/src/clipboard.js';
|
|
14
|
+
/**
|
|
15
|
+
* The GitHub Flavored Markdown (GFM) paste plugin.
|
|
16
|
+
*
|
|
17
|
+
* For a detailed overview, check the {@glink features/pasting/paste-markdown Paste Markdown feature} guide.
|
|
18
|
+
*/
|
|
19
|
+
export default class PasteFromMarkdownExperimental extends Plugin {
|
|
20
|
+
/**
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
private _gfmDataProcessor;
|
|
24
|
+
/**
|
|
25
|
+
* @inheritDoc
|
|
26
|
+
*/
|
|
27
|
+
constructor(editor: Editor);
|
|
28
|
+
/**
|
|
29
|
+
* @inheritDoc
|
|
30
|
+
*/
|
|
31
|
+
static get pluginName(): "PasteFromMarkdownExperimental";
|
|
32
|
+
/**
|
|
33
|
+
* @inheritDoc
|
|
34
|
+
*/
|
|
35
|
+
static get isOfficialPlugin(): true;
|
|
36
|
+
/**
|
|
37
|
+
* @inheritDoc
|
|
38
|
+
*/
|
|
39
|
+
static get requires(): readonly [typeof ClipboardPipeline];
|
|
40
|
+
/**
|
|
41
|
+
* @inheritDoc
|
|
42
|
+
*/
|
|
43
|
+
init(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Determines if the code copied from a website in the `text/html` type can be parsed as Markdown.
|
|
46
|
+
* It removes any OS-specific HTML tags, for example, <meta> on macOS and <!--StartFragment--> on Windows.
|
|
47
|
+
* Then removes a single wrapper HTML tag or wrappers for sibling tags, and if there are no more tags left,
|
|
48
|
+
* returns the remaining text. Returns null if there are any remaining HTML tags detected.
|
|
49
|
+
*
|
|
50
|
+
* @param htmlString Clipboard content in the `text/html` type format.
|
|
51
|
+
*/
|
|
52
|
+
private _parseMarkdownFromHtml;
|
|
53
|
+
/**
|
|
54
|
+
* Removes OS-specific tags.
|
|
55
|
+
*
|
|
56
|
+
* @param htmlString Clipboard content in the `text/html` type format.
|
|
57
|
+
*/
|
|
58
|
+
private _removeOsSpecificTags;
|
|
59
|
+
/**
|
|
60
|
+
* If the input HTML string contains any first-level formatting tags
|
|
61
|
+
* like <b>, <strong>, or <i>, we should not treat it as Markdown.
|
|
62
|
+
*
|
|
63
|
+
* @param htmlString Clipboard content.
|
|
64
|
+
*/
|
|
65
|
+
private _containsOnlyAllowedFirstLevelTags;
|
|
66
|
+
/**
|
|
67
|
+
* Removes multiple HTML wrapper tags from a list of sibling HTML tags.
|
|
68
|
+
*
|
|
69
|
+
* @param htmlString Clipboard content without any OS-specific tags.
|
|
70
|
+
*/
|
|
71
|
+
private _removeFirstLevelWrapperTagsAndBrs;
|
|
72
|
+
/**
|
|
73
|
+
* Determines if a string contains any HTML tags.
|
|
74
|
+
*/
|
|
75
|
+
private _containsAnyRemainingHtmlTags;
|
|
76
|
+
/**
|
|
77
|
+
* Replaces the reserved HTML entities with the actual characters.
|
|
78
|
+
*
|
|
79
|
+
* @param htmlString Clipboard content without any tags.
|
|
80
|
+
*/
|
|
81
|
+
private _replaceHtmlReservedEntitiesWithCharacters;
|
|
82
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ckeditor/ckeditor5-markdown-gfm",
|
|
3
|
+
"version": "0.0.0-internal-20241017.0",
|
|
4
|
+
"description": "GitHub Flavored Markdown data processor for CKEditor 5.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ckeditor",
|
|
7
|
+
"ckeditor5",
|
|
8
|
+
"ckeditor 5",
|
|
9
|
+
"ckeditor5-feature",
|
|
10
|
+
"ckeditor5-plugin",
|
|
11
|
+
"ckeditor5-dll"
|
|
12
|
+
],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "src/index.js",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@ckeditor/ckeditor5-clipboard": "0.0.0-internal-20241017.0",
|
|
17
|
+
"@ckeditor/ckeditor5-core": "0.0.0-internal-20241017.0",
|
|
18
|
+
"@ckeditor/ckeditor5-engine": "0.0.0-internal-20241017.0",
|
|
19
|
+
"ckeditor5": "0.0.0-internal-20241017.0",
|
|
20
|
+
"marked": "4.0.12",
|
|
21
|
+
"turndown": "7.2.0",
|
|
22
|
+
"turndown-plugin-gfm": "1.0.2"
|
|
23
|
+
},
|
|
24
|
+
"author": "CKSource (http://cksource.com/)",
|
|
25
|
+
"license": "GPL-2.0-or-later",
|
|
26
|
+
"homepage": "https://ckeditor.com/ckeditor-5",
|
|
27
|
+
"bugs": "https://github.com/ckeditor/ckeditor5/issues",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/ckeditor/ckeditor5.git",
|
|
31
|
+
"directory": "packages/ckeditor5-markdown-gfm"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"lang",
|
|
36
|
+
"src/**/*.js",
|
|
37
|
+
"src/**/*.d.ts",
|
|
38
|
+
"theme",
|
|
39
|
+
"build",
|
|
40
|
+
"ckeditor5-metadata.json",
|
|
41
|
+
"CHANGELOG.md"
|
|
42
|
+
],
|
|
43
|
+
"types": "src/index.d.ts"
|
|
44
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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
|
+
import type { Markdown, PasteFromMarkdownExperimental } from './index.js';
|
|
6
|
+
declare module '@ckeditor/ckeditor5-core' {
|
|
7
|
+
interface PluginsMap {
|
|
8
|
+
[Markdown.pluginName]: Markdown;
|
|
9
|
+
[PasteFromMarkdownExperimental.pluginName]: PasteFromMarkdownExperimental;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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/gfmdataprocessor
|
|
7
|
+
*/
|
|
8
|
+
import { type DataProcessor, type ViewDocument, type ViewDocumentFragment, type MatcherPattern } from 'ckeditor5/src/engine.js';
|
|
9
|
+
/**
|
|
10
|
+
* This data processor implementation uses GitHub Flavored Markdown as input/output data.
|
|
11
|
+
*
|
|
12
|
+
* See the {@glink features/markdown Markdown output} guide to learn more on how to enable it.
|
|
13
|
+
*/
|
|
14
|
+
export default class GFMDataProcessor implements DataProcessor {
|
|
15
|
+
/**
|
|
16
|
+
* HTML data processor used to process HTML produced by the Markdown-to-HTML converter and the other way.
|
|
17
|
+
*/
|
|
18
|
+
private _htmlDP;
|
|
19
|
+
/**
|
|
20
|
+
* Helper for converting Markdown to HTML.
|
|
21
|
+
*/
|
|
22
|
+
private _markdown2html;
|
|
23
|
+
/**
|
|
24
|
+
* Helper for converting HTML to Markdown.
|
|
25
|
+
*/
|
|
26
|
+
private _html2markdown;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new instance of the Markdown data processor class.
|
|
29
|
+
*/
|
|
30
|
+
constructor(document: ViewDocument);
|
|
31
|
+
/**
|
|
32
|
+
* Keeps the specified element in the output as HTML. This is useful if the editor contains
|
|
33
|
+
* features producing HTML that is not a part of the Markdown standard.
|
|
34
|
+
*
|
|
35
|
+
* By default, all HTML tags are removed.
|
|
36
|
+
*
|
|
37
|
+
* @param element The element name to be kept.
|
|
38
|
+
*/
|
|
39
|
+
keepHtml(element: keyof HTMLElementTagNameMap): void;
|
|
40
|
+
/**
|
|
41
|
+
* Converts the provided Markdown string to a view tree.
|
|
42
|
+
*
|
|
43
|
+
* @param data A Markdown string.
|
|
44
|
+
* @returns The converted view element.
|
|
45
|
+
*/
|
|
46
|
+
toView(data: string): ViewDocumentFragment;
|
|
47
|
+
/**
|
|
48
|
+
* Converts the provided {@link module:engine/view/documentfragment~DocumentFragment} to data format – in this
|
|
49
|
+
* case to a Markdown string.
|
|
50
|
+
*
|
|
51
|
+
* @returns Markdown string.
|
|
52
|
+
*/
|
|
53
|
+
toData(viewFragment: ViewDocumentFragment): string;
|
|
54
|
+
/**
|
|
55
|
+
* Registers a {@link module:engine/view/matcher~MatcherPattern} for view elements whose content should be treated as raw data
|
|
56
|
+
* and not processed during the conversion from Markdown to view elements.
|
|
57
|
+
*
|
|
58
|
+
* The raw data can be later accessed by a
|
|
59
|
+
* {@link module:engine/view/element~Element#getCustomProperty custom property of a view element} called `"$rawContent"`.
|
|
60
|
+
*
|
|
61
|
+
* @param pattern The pattern matching all view elements whose content should
|
|
62
|
+
* be treated as raw data.
|
|
63
|
+
*/
|
|
64
|
+
registerRawContentMatcher(pattern: MatcherPattern): void;
|
|
65
|
+
/**
|
|
66
|
+
* This method does not have any effect on the data processor result. It exists for compatibility with the
|
|
67
|
+
* {@link module:engine/dataprocessor/dataprocessor~DataProcessor `DataProcessor` interface}.
|
|
68
|
+
*/
|
|
69
|
+
useFillerType(): void;
|
|
70
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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/gfmdataprocessor
|
|
7
|
+
*/
|
|
8
|
+
import { HtmlDataProcessor } from 'ckeditor5/src/engine.js';
|
|
9
|
+
import { MarkdownToHtml } from './markdown2html/markdown2html.js';
|
|
10
|
+
import { HtmlToMarkdown } from './html2markdown/html2markdown.js';
|
|
11
|
+
/**
|
|
12
|
+
* This data processor implementation uses GitHub Flavored Markdown as input/output data.
|
|
13
|
+
*
|
|
14
|
+
* See the {@glink features/markdown Markdown output} guide to learn more on how to enable it.
|
|
15
|
+
*/
|
|
16
|
+
export default class GFMDataProcessor {
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new instance of the Markdown data processor class.
|
|
19
|
+
*/
|
|
20
|
+
constructor(document) {
|
|
21
|
+
this._htmlDP = new HtmlDataProcessor(document);
|
|
22
|
+
this._markdown2html = new MarkdownToHtml();
|
|
23
|
+
this._html2markdown = new HtmlToMarkdown();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Keeps the specified element in the output as HTML. This is useful if the editor contains
|
|
27
|
+
* features producing HTML that is not a part of the Markdown standard.
|
|
28
|
+
*
|
|
29
|
+
* By default, all HTML tags are removed.
|
|
30
|
+
*
|
|
31
|
+
* @param element The element name to be kept.
|
|
32
|
+
*/
|
|
33
|
+
keepHtml(element) {
|
|
34
|
+
this._html2markdown.keep([element]);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Converts the provided Markdown string to a view tree.
|
|
38
|
+
*
|
|
39
|
+
* @param data A Markdown string.
|
|
40
|
+
* @returns The converted view element.
|
|
41
|
+
*/
|
|
42
|
+
toView(data) {
|
|
43
|
+
const html = this._markdown2html.parse(data);
|
|
44
|
+
return this._htmlDP.toView(html);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Converts the provided {@link module:engine/view/documentfragment~DocumentFragment} to data format – in this
|
|
48
|
+
* case to a Markdown string.
|
|
49
|
+
*
|
|
50
|
+
* @returns Markdown string.
|
|
51
|
+
*/
|
|
52
|
+
toData(viewFragment) {
|
|
53
|
+
const html = this._htmlDP.toData(viewFragment);
|
|
54
|
+
return this._html2markdown.parse(html);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Registers a {@link module:engine/view/matcher~MatcherPattern} for view elements whose content should be treated as raw data
|
|
58
|
+
* and not processed during the conversion from Markdown to view elements.
|
|
59
|
+
*
|
|
60
|
+
* The raw data can be later accessed by a
|
|
61
|
+
* {@link module:engine/view/element~Element#getCustomProperty custom property of a view element} called `"$rawContent"`.
|
|
62
|
+
*
|
|
63
|
+
* @param pattern The pattern matching all view elements whose content should
|
|
64
|
+
* be treated as raw data.
|
|
65
|
+
*/
|
|
66
|
+
registerRawContentMatcher(pattern) {
|
|
67
|
+
this._htmlDP.registerRawContentMatcher(pattern);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* This method does not have any effect on the data processor result. It exists for compatibility with the
|
|
71
|
+
* {@link module:engine/dataprocessor/dataprocessor~DataProcessor `DataProcessor` interface}.
|
|
72
|
+
*/
|
|
73
|
+
useFillerType() { }
|
|
74
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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/html2markdown/html2markdown
|
|
7
|
+
*/
|
|
8
|
+
import Turndown from 'turndown';
|
|
9
|
+
/**
|
|
10
|
+
* This is a helper class used by the {@link module:markdown-gfm/markdown Markdown feature} to convert HTML to Markdown.
|
|
11
|
+
*/
|
|
12
|
+
export declare class HtmlToMarkdown {
|
|
13
|
+
private _parser;
|
|
14
|
+
constructor();
|
|
15
|
+
parse(html: string): string;
|
|
16
|
+
keep(elements: Turndown.Filter): void;
|
|
17
|
+
private _createParser;
|
|
18
|
+
private _todoList;
|
|
19
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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/html2markdown/html2markdown
|
|
7
|
+
*/
|
|
8
|
+
import Turndown from 'turndown';
|
|
9
|
+
// There no avaialble types for 'turndown-plugin-gfm' module and it's not worth to generate them on our own.
|
|
10
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
import { gfm } from 'turndown-plugin-gfm';
|
|
13
|
+
const autolinkRegex = /* #__PURE__ */ new RegExp(
|
|
14
|
+
// Prefix.
|
|
15
|
+
/\b(?:(?:https?|ftp):\/\/|www\.)/.source +
|
|
16
|
+
// Domain name.
|
|
17
|
+
/(?![-_])(?:[-_a-z0-9\u00a1-\uffff]{1,63}\.)+(?:[a-z\u00a1-\uffff]{2,63})/.source +
|
|
18
|
+
// The rest.
|
|
19
|
+
/(?:[^\s<>]*)/.source, 'gi');
|
|
20
|
+
class UpdatedTurndown extends Turndown {
|
|
21
|
+
escape(string) {
|
|
22
|
+
const originalEscape = super.escape;
|
|
23
|
+
function escape(string) {
|
|
24
|
+
string = originalEscape(string);
|
|
25
|
+
// Escape "<".
|
|
26
|
+
string = string.replace(/</g, '\\<');
|
|
27
|
+
return string;
|
|
28
|
+
}
|
|
29
|
+
// Urls should not be escaped. Our strategy is using a regex to find them and escape everything
|
|
30
|
+
// which is out of the matches parts.
|
|
31
|
+
let escaped = '';
|
|
32
|
+
let lastLinkEnd = 0;
|
|
33
|
+
for (const match of this._matchAutolink(string)) {
|
|
34
|
+
const index = match.index;
|
|
35
|
+
// Append the substring between the last match and the current one (if anything).
|
|
36
|
+
if (index > lastLinkEnd) {
|
|
37
|
+
escaped += escape(string.substring(lastLinkEnd, index));
|
|
38
|
+
}
|
|
39
|
+
const matchedURL = match[0];
|
|
40
|
+
escaped += matchedURL;
|
|
41
|
+
lastLinkEnd = index + matchedURL.length;
|
|
42
|
+
}
|
|
43
|
+
// Add text after the last link or at the string start if no matches.
|
|
44
|
+
if (lastLinkEnd < string.length) {
|
|
45
|
+
escaped += escape(string.substring(lastLinkEnd, string.length));
|
|
46
|
+
}
|
|
47
|
+
return escaped;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Trimming end of link.
|
|
51
|
+
* https://github.github.com/gfm/#autolinks-extension-
|
|
52
|
+
*/
|
|
53
|
+
*_matchAutolink(string) {
|
|
54
|
+
for (const match of string.matchAll(autolinkRegex)) {
|
|
55
|
+
const matched = match[0];
|
|
56
|
+
const length = this._autolinkFindEnd(matched);
|
|
57
|
+
yield Object.assign([matched.substring(0, length)], { index: match.index });
|
|
58
|
+
// We could adjust regex.lastIndex but it's not needed because what we skipped is for sure not a valid URL.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns the new length of the link (after it would trim trailing characters).
|
|
63
|
+
*/
|
|
64
|
+
_autolinkFindEnd(string) {
|
|
65
|
+
let length = string.length;
|
|
66
|
+
while (length > 0) {
|
|
67
|
+
const char = string[length - 1];
|
|
68
|
+
if ('?!.,:*_~\'"'.includes(char)) {
|
|
69
|
+
length--;
|
|
70
|
+
}
|
|
71
|
+
else if (char == ')') {
|
|
72
|
+
let openBrackets = 0;
|
|
73
|
+
for (let i = 0; i < length; i++) {
|
|
74
|
+
if (string[i] == '(') {
|
|
75
|
+
openBrackets++;
|
|
76
|
+
}
|
|
77
|
+
else if (string[i] == ')') {
|
|
78
|
+
openBrackets--;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// If there is fewer opening brackets then closing ones we should remove a closing bracket.
|
|
82
|
+
if (openBrackets < 0) {
|
|
83
|
+
length--;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return length;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* This is a helper class used by the {@link module:markdown-gfm/markdown Markdown feature} to convert HTML to Markdown.
|
|
98
|
+
*/
|
|
99
|
+
export class HtmlToMarkdown {
|
|
100
|
+
constructor() {
|
|
101
|
+
this._parser = this._createParser();
|
|
102
|
+
}
|
|
103
|
+
parse(html) {
|
|
104
|
+
return this._parser.turndown(html);
|
|
105
|
+
}
|
|
106
|
+
keep(elements) {
|
|
107
|
+
this._parser.keep(elements);
|
|
108
|
+
}
|
|
109
|
+
_createParser() {
|
|
110
|
+
const parser = new UpdatedTurndown({
|
|
111
|
+
codeBlockStyle: 'fenced',
|
|
112
|
+
hr: '---',
|
|
113
|
+
headingStyle: 'atx'
|
|
114
|
+
});
|
|
115
|
+
parser.use([
|
|
116
|
+
gfm,
|
|
117
|
+
this._todoList
|
|
118
|
+
]);
|
|
119
|
+
return parser;
|
|
120
|
+
}
|
|
121
|
+
// This is a copy of the original taskListItems rule from turndown-plugin-gfm, with minor changes.
|
|
122
|
+
_todoList(turndown) {
|
|
123
|
+
turndown.addRule('taskListItems', {
|
|
124
|
+
filter(node) {
|
|
125
|
+
return node.type === 'checkbox' &&
|
|
126
|
+
// Changes here as CKEditor outputs a deeper structure.
|
|
127
|
+
(node.parentNode.nodeName === 'LI' || node.parentNode.parentNode.nodeName === 'LI');
|
|
128
|
+
},
|
|
129
|
+
replacement(content, node) {
|
|
130
|
+
return (node.checked ? '[x]' : '[ ]') + ' ';
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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
|
|
7
|
+
*/
|
|
8
|
+
export { default as Markdown } from './markdown.js';
|
|
9
|
+
export { default as PasteFromMarkdownExperimental } from './pastefrommarkdownexperimental.js';
|
|
10
|
+
import './augmentation.js';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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
|
|
7
|
+
*/
|
|
8
|
+
export { default as Markdown } from './markdown.js';
|
|
9
|
+
export { default as PasteFromMarkdownExperimental } from './pastefrommarkdownexperimental.js';
|
|
10
|
+
import './augmentation.js';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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, type Editor } from 'ckeditor5/src/core.js';
|
|
9
|
+
/**
|
|
10
|
+
* The GitHub Flavored Markdown (GFM) plugin.
|
|
11
|
+
*
|
|
12
|
+
* For a detailed overview, check the {@glink features/markdown Markdown feature} guide.
|
|
13
|
+
*/
|
|
14
|
+
export default class Markdown extends Plugin {
|
|
15
|
+
/**
|
|
16
|
+
* @inheritDoc
|
|
17
|
+
*/
|
|
18
|
+
constructor(editor: Editor);
|
|
19
|
+
/**
|
|
20
|
+
* @inheritDoc
|
|
21
|
+
*/
|
|
22
|
+
static get pluginName(): "Markdown";
|
|
23
|
+
/**
|
|
24
|
+
* @inheritDoc
|
|
25
|
+
*/
|
|
26
|
+
static get isOfficialPlugin(): true;
|
|
27
|
+
}
|
package/src/markdown.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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.js';
|
|
9
|
+
import GFMDataProcessor from './gfmdataprocessor.js';
|
|
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
|
+
/**
|
|
30
|
+
* @inheritDoc
|
|
31
|
+
*/
|
|
32
|
+
static get isOfficialPlugin() {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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
|
+
* This is a helper class used by the {@link module:markdown-gfm/markdown Markdown feature} to convert Markdown to HTML.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MarkdownToHtml {
|
|
9
|
+
private _parser;
|
|
10
|
+
private _options;
|
|
11
|
+
constructor();
|
|
12
|
+
parse(markdown: string): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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
|
+
* This is a helper class used by the {@link module:markdown-gfm/markdown Markdown feature} to convert Markdown to HTML.
|
|
11
|
+
*/
|
|
12
|
+
export class MarkdownToHtml {
|
|
13
|
+
constructor() {
|
|
14
|
+
this._options = {
|
|
15
|
+
gfm: true,
|
|
16
|
+
breaks: true,
|
|
17
|
+
tables: true,
|
|
18
|
+
xhtml: true,
|
|
19
|
+
headerIds: false
|
|
20
|
+
};
|
|
21
|
+
// Overrides.
|
|
22
|
+
marked.use({
|
|
23
|
+
tokenizer: {
|
|
24
|
+
// Disable the autolink rule in the lexer.
|
|
25
|
+
autolink: () => null,
|
|
26
|
+
url: () => null
|
|
27
|
+
},
|
|
28
|
+
renderer: {
|
|
29
|
+
checkbox(...args) {
|
|
30
|
+
// Remove bogus space after <input type="checkbox"> because it would be preserved
|
|
31
|
+
// by DomConverter as it's next to an inline object.
|
|
32
|
+
return Object.getPrototypeOf(this).checkbox.call(this, ...args).trimRight();
|
|
33
|
+
},
|
|
34
|
+
code(...args) {
|
|
35
|
+
// Since marked v1.2.8, every <code> gets a trailing "\n" whether it originally
|
|
36
|
+
// ended with one or not (see https://github.com/markedjs/marked/issues/1884 to learn why).
|
|
37
|
+
// This results in a redundant soft break in the model when loaded into the editor, which
|
|
38
|
+
// is best prevented at this stage. See https://github.com/ckeditor/ckeditor5/issues/11124.
|
|
39
|
+
return Object.getPrototypeOf(this).code.call(this, ...args).replace('\n</code>', '</code>');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
this._parser = marked;
|
|
44
|
+
}
|
|
45
|
+
parse(markdown) {
|
|
46
|
+
return this._parser.parse(markdown, this._options);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2024, 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.js';
|
|
9
|
+
import { ClipboardPipeline } from 'ckeditor5/src/clipboard.js';
|
|
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 isOfficialPlugin(): true;
|
|
32
|
+
/**
|
|
33
|
+
* @inheritDoc
|
|
34
|
+
*/
|
|
35
|
+
static get requires(): readonly [typeof ClipboardPipeline];
|
|
36
|
+
/**
|
|
37
|
+
* @inheritDoc
|
|
38
|
+
*/
|
|
39
|
+
init(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Determines if the code copied from a website in the `text/html` type can be parsed as Markdown.
|
|
42
|
+
* It removes any OS-specific HTML tags, for example, <meta> on macOS and <!--StartFragment--> on Windows.
|
|
43
|
+
* Then removes a single wrapper HTML tag or wrappers for sibling tags, and if there are no more tags left,
|
|
44
|
+
* returns the remaining text. Returns null if there are any remaining HTML tags detected.
|
|
45
|
+
*
|
|
46
|
+
* @param htmlString Clipboard content in the `text/html` type format.
|
|
47
|
+
*/
|
|
48
|
+
private _parseMarkdownFromHtml;
|
|
49
|
+
/**
|
|
50
|
+
* Removes OS-specific tags.
|
|
51
|
+
*
|
|
52
|
+
* @param htmlString Clipboard content in the `text/html` type format.
|
|
53
|
+
*/
|
|
54
|
+
private _removeOsSpecificTags;
|
|
55
|
+
/**
|
|
56
|
+
* If the input HTML string contains any first-level formatting tags
|
|
57
|
+
* like <b>, <strong>, or <i>, we should not treat it as Markdown.
|
|
58
|
+
*
|
|
59
|
+
* @param htmlString Clipboard content.
|
|
60
|
+
*/
|
|
61
|
+
private _containsOnlyAllowedFirstLevelTags;
|
|
62
|
+
/**
|
|
63
|
+
* Removes multiple HTML wrapper tags from a list of sibling HTML tags.
|
|
64
|
+
*
|
|
65
|
+
* @param htmlString Clipboard content without any OS-specific tags.
|
|
66
|
+
*/
|
|
67
|
+
private _removeFirstLevelWrapperTagsAndBrs;
|
|
68
|
+
/**
|
|
69
|
+
* Determines if a string contains any HTML tags.
|
|
70
|
+
*/
|
|
71
|
+
private _containsAnyRemainingHtmlTags;
|
|
72
|
+
/**
|
|
73
|
+
* Replaces the reserved HTML entities with the actual characters.
|
|
74
|
+
*
|
|
75
|
+
* @param htmlString Clipboard content without any tags.
|
|
76
|
+
*/
|
|
77
|
+
private _replaceHtmlReservedEntitiesWithCharacters;
|
|
78
|
+
}
|