onchain-lexical-markdown 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import {ElementNode} from 'lexical';
10
+ import {Instance} from 'onchain-lexical-instance';
11
+
12
+ import {createMarkdownImport} from './MarkdownImport';
13
+ import {normalizeMarkdown, Transformer} from './MarkdownTransformers';
14
+ import {TransFormerGather} from './transformer';
15
+
16
+ /**
17
+ * Renders markdown from a string. The selection is moved to the start after the operation.
18
+ *
19
+ * @param {boolean} [shouldPreserveNewLines] By setting this to true, new lines will be preserved between conversions
20
+ * @param {boolean} [shouldMergeAdjacentLines] By setting this to true, adjacent non empty lines will be merged according to commonmark spec: https://spec.commonmark.org/0.24/#example-177. Not applicable if shouldPreserveNewLines = true.
21
+ */
22
+ export function $convertFromMarkdownString(
23
+ markdown: string,
24
+ transformers: Array<Transformer> = TransFormerGather.value,
25
+ node?: ElementNode,
26
+ shouldPreserveNewLines = false,
27
+ shouldMergeAdjacentLines = false,
28
+ instanceMap?: Map<string, Instance>,
29
+ ): void {
30
+ const sanitizedMarkdown = shouldPreserveNewLines
31
+ ? markdown
32
+ : normalizeMarkdown(markdown, shouldMergeAdjacentLines);
33
+ const importMarkdown = createMarkdownImport(
34
+ transformers,
35
+ shouldPreserveNewLines,
36
+ instanceMap,
37
+ );
38
+ return importMarkdown(sanitizedMarkdown, node);
39
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type {TextFormatTransformersIndex} from './MarkdownImport';
10
+ import type {TextFormatTransformer} from './MarkdownTransformers';
11
+ import type {TextNode} from 'lexical';
12
+
13
+ import {PUNCTUATION_OR_SPACE} from './utils';
14
+
15
+ export function findOutermostTextFormatTransformer(
16
+ textNode: TextNode,
17
+ textFormatTransformersIndex: TextFormatTransformersIndex,
18
+ ): {
19
+ startIndex: number;
20
+ endIndex: number;
21
+ transformer: TextFormatTransformer;
22
+ match: RegExpMatchArray;
23
+ } | null {
24
+ const textContent = textNode.getTextContent();
25
+ const match = findOutermostMatch(textContent, textFormatTransformersIndex);
26
+
27
+ if (!match) {
28
+ return null;
29
+ }
30
+
31
+ const textFormatMatchStart: number = match.index || 0;
32
+ const textFormatMatchEnd = textFormatMatchStart + match[0].length;
33
+
34
+ const transformer: TextFormatTransformer =
35
+ textFormatTransformersIndex.transformersByTag[match[1]];
36
+
37
+ return {
38
+ endIndex: textFormatMatchEnd,
39
+ match,
40
+ startIndex: textFormatMatchStart,
41
+ transformer,
42
+ };
43
+ }
44
+
45
+ // Finds first "<tag>content<tag>" match that is not nested into another tag
46
+ function findOutermostMatch(
47
+ textContent: string,
48
+ textTransformersIndex: TextFormatTransformersIndex,
49
+ ): RegExpMatchArray | null {
50
+ const openTagsMatch = textContent.match(textTransformersIndex.openTagsRegExp);
51
+
52
+ if (openTagsMatch == null) {
53
+ return null;
54
+ }
55
+
56
+ for (const match of openTagsMatch) {
57
+ // Open tags reg exp might capture leading space so removing it
58
+ // before using match to find transformer
59
+ const tag = match.replace(/^\s/, '');
60
+ const fullMatchRegExp = textTransformersIndex.fullMatchRegExpByTag[tag];
61
+ if (fullMatchRegExp == null) {
62
+ continue;
63
+ }
64
+
65
+ const fullMatch = textContent.match(fullMatchRegExp);
66
+ const transformer = textTransformersIndex.transformersByTag[tag];
67
+ if (fullMatch != null && transformer != null) {
68
+ if (transformer.intraword !== false) {
69
+ return fullMatch;
70
+ }
71
+
72
+ // For non-intraword transformers checking if it's within a word
73
+ // or surrounded with space/punctuation/newline
74
+ const {index = 0} = fullMatch;
75
+ const beforeChar = textContent[index - 1];
76
+ const afterChar = textContent[index + fullMatch[0].length];
77
+
78
+ if (
79
+ (!beforeChar || PUNCTUATION_OR_SPACE.test(beforeChar)) &&
80
+ (!afterChar || PUNCTUATION_OR_SPACE.test(afterChar))
81
+ ) {
82
+ return fullMatch;
83
+ }
84
+ }
85
+ }
86
+
87
+ return null;
88
+ }
89
+
90
+ export function importTextFormatTransformer(
91
+ textNode: TextNode,
92
+ startIndex: number,
93
+ endIndex: number,
94
+ transformer: TextFormatTransformer,
95
+ match: RegExpMatchArray,
96
+ ): {
97
+ transformedNode: TextNode;
98
+ nodeBefore: TextNode | undefined; // If split
99
+ nodeAfter: TextNode | undefined; // If split
100
+ } {
101
+ const textContent = textNode.getTextContent();
102
+
103
+ // No text matches - we can safely process the text format match
104
+ let transformedNode, nodeAfter, nodeBefore;
105
+
106
+ // If matching full content there's no need to run splitText and can reuse existing textNode
107
+ // to update its content and apply format. E.g. for **_Hello_** string after applying bold
108
+ // format (**) it will reuse the same text node to apply italic (_)
109
+ if (match[0] === textContent) {
110
+ transformedNode = textNode;
111
+ } else {
112
+ if (startIndex === 0) {
113
+ [transformedNode, nodeAfter] = textNode.splitText(endIndex);
114
+ } else {
115
+ [nodeBefore, transformedNode, nodeAfter] = textNode.splitText(
116
+ startIndex,
117
+ endIndex,
118
+ );
119
+ }
120
+ }
121
+
122
+ transformedNode.setTextContent(match[2]);
123
+
124
+ if (transformer) {
125
+ for (const format of transformer.format) {
126
+ if (!transformedNode.hasFormat(format)) {
127
+ transformedNode.toggleFormat(format);
128
+ }
129
+ }
130
+ }
131
+
132
+ return {
133
+ nodeAfter: nodeAfter,
134
+ nodeBefore: nodeBefore,
135
+ transformedNode: transformedNode,
136
+ };
137
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type {TextMatchTransformer} from './MarkdownTransformers';
9
+
10
+ import {type TextNode} from 'lexical';
11
+
12
+ export function findOutermostTextMatchTransformer(
13
+ textNode_: TextNode,
14
+ textMatchTransformers: Array<TextMatchTransformer>,
15
+ ): {
16
+ startIndex: number;
17
+ endIndex: number;
18
+ transformer: TextMatchTransformer;
19
+ match: RegExpMatchArray;
20
+ } | null {
21
+ const textNode = textNode_;
22
+
23
+ let foundMatchStartIndex: number | undefined = undefined;
24
+ let foundMatchEndIndex: number | undefined = undefined;
25
+ let foundMatchTransformer: TextMatchTransformer | undefined = undefined;
26
+ let foundMatch: RegExpMatchArray | undefined = undefined;
27
+
28
+ for (const transformer of textMatchTransformers) {
29
+ if (!transformer.replace || !transformer.importRegExp) {
30
+ continue;
31
+ }
32
+ const match = textNode.getTextContent().match(transformer.importRegExp);
33
+
34
+ if (!match) {
35
+ continue;
36
+ }
37
+
38
+ const startIndex = match.index || 0;
39
+ const endIndex = transformer.getEndIndex
40
+ ? transformer.getEndIndex(textNode, match)
41
+ : startIndex + match[0].length;
42
+
43
+ if (endIndex === false) {
44
+ continue;
45
+ }
46
+
47
+ if (
48
+ foundMatchStartIndex === undefined ||
49
+ foundMatchEndIndex === undefined ||
50
+ (startIndex < foundMatchStartIndex && endIndex > foundMatchEndIndex)
51
+ ) {
52
+ foundMatchStartIndex = startIndex;
53
+ foundMatchEndIndex = endIndex;
54
+ foundMatchTransformer = transformer;
55
+ foundMatch = match;
56
+ }
57
+ }
58
+
59
+ if (
60
+ foundMatchStartIndex === undefined ||
61
+ foundMatchEndIndex === undefined ||
62
+ foundMatchTransformer === undefined ||
63
+ foundMatch === undefined
64
+ ) {
65
+ return null;
66
+ }
67
+
68
+ return {
69
+ endIndex: foundMatchEndIndex,
70
+ match: foundMatch,
71
+ startIndex: foundMatchStartIndex,
72
+ transformer: foundMatchTransformer,
73
+ };
74
+ }
75
+
76
+ export function importFoundTextMatchTransformer(
77
+ textNode: TextNode,
78
+ startIndex: number,
79
+ endIndex: number,
80
+ transformer: TextMatchTransformer,
81
+ match: RegExpMatchArray,
82
+ ): {
83
+ transformedNode?: TextNode;
84
+ nodeBefore: TextNode | undefined; // If split
85
+ nodeAfter: TextNode | undefined; // If split
86
+ } | null {
87
+ let transformedNode, nodeAfter, nodeBefore;
88
+
89
+ if (startIndex === 0) {
90
+ [transformedNode, nodeAfter] = textNode.splitText(endIndex);
91
+ } else {
92
+ [nodeBefore, transformedNode, nodeAfter] = textNode.splitText(
93
+ startIndex,
94
+ endIndex,
95
+ );
96
+ }
97
+
98
+ if (!transformer.replace) {
99
+ return null;
100
+ }
101
+ const potentialTransformedNode = transformer.replace(transformedNode, match);
102
+
103
+ return {
104
+ nodeAfter,
105
+ nodeBefore,
106
+ transformedNode: potentialTransformedNode || undefined,
107
+ };
108
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ import type {TextFormatTransformersIndex} from './MarkdownImport';
9
+ import type {TextMatchTransformer} from './MarkdownTransformers';
10
+
11
+ import {$isTextNode, type LexicalNode, type TextNode} from 'lexical';
12
+
13
+ import {
14
+ findOutermostTextFormatTransformer,
15
+ importTextFormatTransformer,
16
+ } from './importTextFormatTransformer';
17
+ import {
18
+ findOutermostTextMatchTransformer,
19
+ importFoundTextMatchTransformer,
20
+ } from './importTextMatchTransformer';
21
+
22
+ /**
23
+ * Returns true if the node can contain transformable markdown.
24
+ * Code nodes cannot contain transformable markdown.
25
+ * For example, `code **bold**` should not be transformed to
26
+ * <code>code <strong>bold</strong></code>.
27
+ */
28
+ export function canContainTransformableMarkdown(
29
+ node: LexicalNode | undefined,
30
+ ): node is TextNode {
31
+ return $isTextNode(node) && !node.hasFormat('code');
32
+ }
33
+
34
+ /**
35
+ * Handles applying both text format and text match transformers.
36
+ * It finds the outermost text format or text match and applies it,
37
+ * then recursively calls itself to apply the next outermost transformer,
38
+ * until there are no more transformers to apply.
39
+ */
40
+ export function importTextTransformers(
41
+ textNode: TextNode,
42
+ textFormatTransformersIndex: TextFormatTransformersIndex,
43
+ textMatchTransformers: Array<TextMatchTransformer>,
44
+ ) {
45
+ let foundTextFormat = findOutermostTextFormatTransformer(
46
+ textNode,
47
+ textFormatTransformersIndex,
48
+ );
49
+
50
+ let foundTextMatch = findOutermostTextMatchTransformer(
51
+ textNode,
52
+ textMatchTransformers,
53
+ );
54
+
55
+ if (foundTextFormat && foundTextMatch) {
56
+ // Find the outermost transformer
57
+ if (
58
+ foundTextFormat.startIndex <= foundTextMatch.startIndex &&
59
+ foundTextFormat.endIndex >= foundTextMatch.endIndex
60
+ ) {
61
+ // foundTextFormat wraps foundTextMatch - apply foundTextFormat by setting foundTextMatch to null
62
+ foundTextMatch = null;
63
+ } else {
64
+ // foundTextMatch wraps foundTextFormat - apply foundTextMatch by setting foundTextFormat to null
65
+ foundTextFormat = null;
66
+ }
67
+ }
68
+
69
+ if (foundTextFormat) {
70
+ const result = importTextFormatTransformer(
71
+ textNode,
72
+ foundTextFormat.startIndex,
73
+ foundTextFormat.endIndex,
74
+ foundTextFormat.transformer,
75
+ foundTextFormat.match,
76
+ );
77
+
78
+ if (canContainTransformableMarkdown(result.nodeAfter)) {
79
+ importTextTransformers(
80
+ result.nodeAfter,
81
+ textFormatTransformersIndex,
82
+ textMatchTransformers,
83
+ );
84
+ }
85
+ if (canContainTransformableMarkdown(result.nodeBefore)) {
86
+ importTextTransformers(
87
+ result.nodeBefore,
88
+ textFormatTransformersIndex,
89
+ textMatchTransformers,
90
+ );
91
+ }
92
+ if (canContainTransformableMarkdown(result.transformedNode)) {
93
+ importTextTransformers(
94
+ result.transformedNode,
95
+ textFormatTransformersIndex,
96
+ textMatchTransformers,
97
+ );
98
+ }
99
+ } else if (foundTextMatch) {
100
+ const result = importFoundTextMatchTransformer(
101
+ textNode,
102
+ foundTextMatch.startIndex,
103
+ foundTextMatch.endIndex,
104
+ foundTextMatch.transformer,
105
+ foundTextMatch.match,
106
+ );
107
+ if (!result) {
108
+ return;
109
+ }
110
+
111
+ if (canContainTransformableMarkdown(result.nodeAfter)) {
112
+ importTextTransformers(
113
+ result.nodeAfter,
114
+ textFormatTransformersIndex,
115
+ textMatchTransformers,
116
+ );
117
+ }
118
+ if (canContainTransformableMarkdown(result.nodeBefore)) {
119
+ importTextTransformers(
120
+ result.nodeBefore,
121
+ textFormatTransformersIndex,
122
+ textMatchTransformers,
123
+ );
124
+ }
125
+ if (canContainTransformableMarkdown(result.transformedNode)) {
126
+ importTextTransformers(
127
+ result.transformedNode,
128
+ textFormatTransformersIndex,
129
+ textMatchTransformers,
130
+ );
131
+ }
132
+ }
133
+
134
+ // Handle escape characters
135
+ const textContent = textNode.getTextContent();
136
+ const escapedText = textContent
137
+ .replace(/\\([*_`~\\])/g, '$1')
138
+ .replace(/&#(\d+);/g, (_, codePoint) => {
139
+ return String.fromCodePoint(codePoint);
140
+ });
141
+ textNode.setTextContent(escapedText);
142
+ }
package/src/index.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type {
10
+ ElementTransformer,
11
+ MultilineElementTransformer,
12
+ TextFormatTransformer,
13
+ TextMatchTransformer,
14
+ Transformer,
15
+ } from './MarkdownTransformers';
16
+
17
+ import {$convertFromMarkdownString} from './fromMarkdownString';
18
+ // import {createMarkdownExport} from './MarkdownExport';
19
+ import {registerMarkdownShortcuts} from './MarkdownShortcuts';
20
+ import {
21
+ BOLD_ITALIC_STAR,
22
+ BOLD_ITALIC_UNDERSCORE,
23
+ BOLD_STAR,
24
+ BOLD_UNDERSCORE,
25
+ CHECK_LIST,
26
+ CODE,
27
+ HEADING,
28
+ HIGHLIGHT,
29
+ INLINE_CODE,
30
+ ITALIC_STAR,
31
+ ITALIC_UNDERSCORE,
32
+ LINK,
33
+ ORDERED_LIST,
34
+ QUOTE,
35
+ STRIKETHROUGH,
36
+ UNORDERED_LIST,
37
+ } from './MarkdownTransformers';
38
+ import {$convertToMarkdownString} from './toMarkdownString';
39
+ import {
40
+ ELEMENT_TRANSFORMERS,
41
+ getInstanceTransformers,
42
+ MULTILINE_ELEMENT_TRANSFORMERS,
43
+ TEXT_FORMAT_TRANSFORMERS,
44
+ TEXT_MATCH_TRANSFORMERS,
45
+ TransFormerGather,
46
+ TRANSFORMERS,
47
+ } from './transformer';
48
+
49
+ export {
50
+ $convertFromMarkdownString,
51
+ $convertToMarkdownString,
52
+ BOLD_ITALIC_STAR,
53
+ BOLD_ITALIC_UNDERSCORE,
54
+ BOLD_STAR,
55
+ BOLD_UNDERSCORE,
56
+ CHECK_LIST,
57
+ CODE,
58
+ ELEMENT_TRANSFORMERS,
59
+ type ElementTransformer,
60
+ getInstanceTransformers,
61
+ HEADING,
62
+ HIGHLIGHT,
63
+ INLINE_CODE,
64
+ ITALIC_STAR,
65
+ ITALIC_UNDERSCORE,
66
+ LINK,
67
+ MULTILINE_ELEMENT_TRANSFORMERS,
68
+ type MultilineElementTransformer,
69
+ ORDERED_LIST,
70
+ QUOTE,
71
+ registerMarkdownShortcuts,
72
+ STRIKETHROUGH,
73
+ TEXT_FORMAT_TRANSFORMERS,
74
+ TEXT_MATCH_TRANSFORMERS,
75
+ type TextFormatTransformer,
76
+ type TextMatchTransformer,
77
+ type Transformer,
78
+ TransFormerGather,
79
+ TRANSFORMERS,
80
+ UNORDERED_LIST,
81
+ };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import {ElementNode} from 'lexical';
10
+
11
+ import {createMarkdownExport} from './MarkdownExport';
12
+ import {Transformer} from './MarkdownTransformers';
13
+ import {TransFormerGather} from './transformer';
14
+
15
+ export function $convertToMarkdownString(
16
+ transformers: Array<Transformer> = TransFormerGather.value,
17
+ node?: ElementNode,
18
+ shouldPreserveNewLines: boolean = false,
19
+ ): string {
20
+ const exportMarkdown = createMarkdownExport(
21
+ transformers,
22
+ shouldPreserveNewLines,
23
+ );
24
+ return exportMarkdown(node);
25
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ export const INS_SYMBOL = '\u200B';
10
+ export const INSTANCE_START_REGEX = /^(<!--)(\u200B+)(-->)\s*/;
11
+ export const INSTANCE_END_REGEX = /^(<!---->)\s*/;
12
+ export const HEADING_REGEX = /^(#{1,6})\s/;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import {
10
+ $createHorizontalRuleNode,
11
+ $isHorizontalRuleNode,
12
+ HorizontalRuleNode,
13
+ } from '@lexical/react/LexicalHorizontalRuleNode';
14
+ import {LexicalNode} from 'lexical';
15
+
16
+ import {ElementTransformer} from '../MarkdownTransformers';
17
+
18
+ export const HR: ElementTransformer = {
19
+ dependencies: [HorizontalRuleNode],
20
+ export: (node: LexicalNode) => {
21
+ return $isHorizontalRuleNode(node) ? '***' : null;
22
+ },
23
+ regExp: /^(---|\*\*\*|___)\s?$/,
24
+ replace: (parentNode, _1, _2, isImport) => {
25
+ const line = $createHorizontalRuleNode();
26
+
27
+ // TODO: Get rid of isImport flag
28
+ if (isImport || parentNode.getNextSibling() != null) {
29
+ parentNode.replace(line);
30
+ } else {
31
+ parentNode.insertBefore(line);
32
+ }
33
+
34
+ line.selectNext();
35
+ },
36
+ type: 'element',
37
+ };
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type {
10
+ ElementTransformer,
11
+ MultilineElementTransformer,
12
+ TextFormatTransformer,
13
+ TextMatchTransformer,
14
+ Transformer,
15
+ } from '../MarkdownTransformers';
16
+
17
+ import {
18
+ BOLD_ITALIC_STAR,
19
+ BOLD_ITALIC_UNDERSCORE,
20
+ BOLD_STAR,
21
+ BOLD_UNDERSCORE,
22
+ CHECK_LIST,
23
+ CODE,
24
+ // HEADING,
25
+ HIGHLIGHT,
26
+ INLINE_CODE,
27
+ ITALIC_STAR,
28
+ ITALIC_UNDERSCORE,
29
+ LINK,
30
+ ORDERED_LIST,
31
+ QUOTE,
32
+ STRIKETHROUGH,
33
+ UNORDERED_LIST,
34
+ } from '../MarkdownTransformers';
35
+ import {HR} from './hr';
36
+ import {InstanceHeadingTransformer, InstanceTransformer} from './instance';
37
+ import {TABLE} from './table';
38
+
39
+ export const ELEMENT_TRANSFORMERS: Array<ElementTransformer> = [
40
+ // HEADING,
41
+ QUOTE,
42
+ UNORDERED_LIST,
43
+ ORDERED_LIST,
44
+ ];
45
+
46
+ export const MULTILINE_ELEMENT_TRANSFORMERS: Array<MultilineElementTransformer> =
47
+ [CODE];
48
+
49
+ // Order of text format transformers matters:
50
+ //
51
+ // - code should go first as it prevents any transformations inside
52
+ // - then longer tags match (e.g. ** or __ should go before * or _)
53
+ export const TEXT_FORMAT_TRANSFORMERS: Array<TextFormatTransformer> = [
54
+ INLINE_CODE,
55
+ BOLD_ITALIC_STAR,
56
+ BOLD_ITALIC_UNDERSCORE,
57
+ BOLD_STAR,
58
+ BOLD_UNDERSCORE,
59
+ HIGHLIGHT,
60
+ ITALIC_STAR,
61
+ ITALIC_UNDERSCORE,
62
+ STRIKETHROUGH,
63
+ ];
64
+
65
+ export const TEXT_MATCH_TRANSFORMERS: Array<TextMatchTransformer> = [LINK];
66
+
67
+ export const TRANSFORMERS: Array<Transformer> = [
68
+ CHECK_LIST,
69
+ ...ELEMENT_TRANSFORMERS,
70
+ ...MULTILINE_ELEMENT_TRANSFORMERS,
71
+ ...TEXT_FORMAT_TRANSFORMERS,
72
+ ...TEXT_MATCH_TRANSFORMERS,
73
+ ];
74
+
75
+ class TFR {
76
+ private _value = new Set([...TRANSFORMERS]);
77
+
78
+ get value() {
79
+ return Array.from(this._value);
80
+ }
81
+
82
+ register(tfr: Transformer) {
83
+ this._value.add(tfr);
84
+ }
85
+ }
86
+ const TransFormerGather = new TFR();
87
+
88
+ TransFormerGather.register(InstanceTransformer);
89
+ TransFormerGather.register(InstanceHeadingTransformer);
90
+ TransFormerGather.register(HR);
91
+ TransFormerGather.register(TABLE);
92
+
93
+ function getInstanceTransformers() {
94
+ return TransFormerGather.value;
95
+ }
96
+
97
+ export {getInstanceTransformers, TransFormerGather};