mdsquare 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +218 -2
- package/dist/callout.d.ts +17 -0
- package/dist/callout.js +541 -0
- package/dist/calloutHeader.d.ts +47 -0
- package/dist/calloutHeader.js +75 -0
- package/dist/codeBlock.d.ts +78 -0
- package/dist/codeBlock.js +686 -0
- package/dist/codeTheme.d.ts +47 -0
- package/dist/codeTheme.js +394 -0
- package/dist/delimiter.d.ts +20 -0
- package/dist/delimiter.js +73 -0
- package/dist/editor.d.ts +132 -0
- package/dist/editor.js +225 -0
- package/dist/emphasis.d.ts +6 -0
- package/dist/emphasis.js +101 -0
- package/dist/escape.d.ts +4 -0
- package/dist/escape.js +39 -0
- package/dist/extensions.d.ts +74 -0
- package/dist/extensions.js +81 -0
- package/dist/footnote.d.ts +24 -0
- package/dist/footnote.js +456 -0
- package/dist/footnoteSyntax.d.ts +23 -0
- package/dist/footnoteSyntax.js +107 -0
- package/dist/hashtag.d.ts +4 -0
- package/dist/hashtag.js +64 -0
- package/dist/hashtagSyntax.d.ts +36 -0
- package/dist/hashtagSyntax.js +99 -0
- package/dist/heading.d.ts +7 -0
- package/dist/heading.js +159 -0
- package/dist/highlight.d.ts +5 -0
- package/dist/highlight.js +6 -0
- package/dist/horizontalRule.d.ts +21 -0
- package/dist/horizontalRule.js +142 -0
- package/dist/image.d.ts +58 -0
- package/dist/image.js +344 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/inlineCode.d.ts +4 -0
- package/dist/inlineCode.js +68 -0
- package/dist/link.d.ts +47 -0
- package/dist/link.js +217 -0
- package/dist/list.d.ts +14 -0
- package/dist/list.js +136 -0
- package/dist/listEnter.d.ts +20 -0
- package/dist/listEnter.js +72 -0
- package/dist/listIndent.d.ts +23 -0
- package/dist/listIndent.js +335 -0
- package/dist/markVision.d.ts +17 -0
- package/dist/markVision.js +56 -0
- package/dist/math.d.ts +45 -0
- package/dist/math.js +233 -0
- package/dist/mathSyntax.d.ts +24 -0
- package/dist/mathSyntax.js +179 -0
- package/dist/mention.d.ts +4 -0
- package/dist/mention.js +58 -0
- package/dist/mentionSyntax.d.ts +14 -0
- package/dist/mentionSyntax.js +71 -0
- package/dist/quote.d.ts +9 -0
- package/dist/quote.js +122 -0
- package/dist/setup.d.ts +13 -0
- package/dist/setup.js +40 -0
- package/dist/style.css +6 -0
- package/dist/style.css.d.ts +2 -0
- package/dist/table.d.ts +38 -0
- package/dist/table.js +960 -0
- package/dist/tableEdit.d.ts +30 -0
- package/dist/tableEdit.js +305 -0
- package/dist/tableMenu.d.ts +65 -0
- package/dist/tableMenu.js +1125 -0
- package/dist/tableModel.d.ts +168 -0
- package/dist/tableModel.js +433 -0
- package/dist/tableState.d.ts +36 -0
- package/dist/tableState.js +96 -0
- package/dist/task.d.ts +13 -0
- package/dist/task.js +179 -0
- package/dist/textMate.d.ts +49 -0
- package/dist/textMate.js +284 -0
- package/dist/tikz.d.ts +56 -0
- package/dist/tikz.js +343 -0
- package/dist/underline.d.ts +5 -0
- package/dist/underline.js +6 -0
- package/dist/utils/blockMargin.d.ts +6 -0
- package/dist/utils/blockMargin.js +6 -0
- package/dist/utils/codePoint.d.ts +13 -0
- package/dist/utils/codePoint.js +43 -0
- package/dist/utils/container.d.ts +10 -0
- package/dist/utils/container.js +10 -0
- package/dist/utils/reveal.d.ts +99 -0
- package/dist/utils/reveal.js +161 -0
- package/dist/utils/selection.d.ts +33 -0
- package/dist/utils/selection.js +45 -0
- package/dist/utils/syntaxTree.d.ts +18 -0
- package/dist/utils/syntaxTree.js +23 -0
- package/package.json +79 -4
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Extension } from "@codemirror/state";
|
|
2
|
+
import { type Highlighter, type Tag } from "@lezer/highlight";
|
|
3
|
+
import { type TokenColorRule } from "./textMate.js";
|
|
4
|
+
/**
|
|
5
|
+
* 코드 블록 토큰 색 테마.
|
|
6
|
+
* - `highlighter(lang)`: 정보 문자열의 언어(소문자)별 Lezer 하이라이터. 토큰에 붙일 클래스를 정합니다.
|
|
7
|
+
* - `extension`: 그 클래스들의 CSS, 코드 블록 배경 등
|
|
8
|
+
*/
|
|
9
|
+
export interface CodeTheme {
|
|
10
|
+
/** 토큰 캐시를 나누는 고유 이름 */
|
|
11
|
+
readonly id: string;
|
|
12
|
+
highlighter(lang: string): Highlighter;
|
|
13
|
+
/**
|
|
14
|
+
* 문자열 따옴표에 따로 붙일 클래스 (VS Code처럼 따옴표와 내용을 다른 색으로 칠할 때).
|
|
15
|
+
* 없으면 따옴표도 문자열과 같은 클래스를 씁니다.
|
|
16
|
+
*/
|
|
17
|
+
quoteClass?(lang: string): string | null;
|
|
18
|
+
readonly extension: Extension;
|
|
19
|
+
}
|
|
20
|
+
/** 기본 토큰 색 (GitHub 계열) */
|
|
21
|
+
export declare const defaultCodeTheme: CodeTheme;
|
|
22
|
+
/** 언어의 TextMate 접미사와 최상위 스코프 */
|
|
23
|
+
export declare function textMateLanguage(lang: string): {
|
|
24
|
+
suffix: string;
|
|
25
|
+
root: string;
|
|
26
|
+
};
|
|
27
|
+
/** 태그의 스코프 경로 (가장 구체적인 태그부터 찾음). 없으면 null */
|
|
28
|
+
export declare function scopesForTag(tag: Tag, lang: string): readonly string[] | null;
|
|
29
|
+
/** VS Code 색 테마 JSON */
|
|
30
|
+
export interface VSCodeThemeJson {
|
|
31
|
+
readonly name?: string;
|
|
32
|
+
readonly type?: string;
|
|
33
|
+
readonly colors?: Readonly<Record<string, string>>;
|
|
34
|
+
readonly tokenColors?: readonly TokenColorRule[] | string;
|
|
35
|
+
/** 예전 .tmTheme 형식 */
|
|
36
|
+
readonly settings?: readonly TokenColorRule[];
|
|
37
|
+
}
|
|
38
|
+
export interface VSCodeThemeOptions {
|
|
39
|
+
/** 테마의 배경색(editor.background)을 코드 블록에 칠할지 (기본 true) */
|
|
40
|
+
background?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* VS Code 색 테마(JSON/JSONC 문자열 또는 객체)를 코드 블록 테마로 바꿉니다.
|
|
44
|
+
* 토큰 색은 VS Code와 같은 방식(TextMate 스코프 매칭)으로 정합니다. 다만 Lezer 문법이 구분하지 않는
|
|
45
|
+
* 차이(예: 매개변수와 지역 변수)는 재현되지 않습니다.
|
|
46
|
+
*/
|
|
47
|
+
export declare function vscodeTheme(source: string | VSCodeThemeJson, options?: VSCodeThemeOptions): CodeTheme;
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { EditorView } from "@codemirror/view";
|
|
2
|
+
import { tags as t, tagHighlighter } from "@lezer/highlight";
|
|
3
|
+
import { FontStyle, parseJsonc, textMateTheme } from "./textMate.js";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// 기본 테마 (GitHub 계열, 밝은/어두운 에디터 모두)
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
const defaultHighlighter = tagHighlighter([
|
|
8
|
+
{ tag: [t.comment, t.meta], class: "cm-code-comment" },
|
|
9
|
+
{ tag: [t.keyword, t.operator, t.processingInstruction], class: "cm-code-keyword" },
|
|
10
|
+
{
|
|
11
|
+
tag: [t.string, t.special(t.string), t.regexp, t.character, t.attributeValue, t.url, t.escape],
|
|
12
|
+
class: "cm-code-string",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
tag: [t.number, t.bool, t.null, t.atom, t.self, t.unit, t.color, t.constant(t.variableName), t.propertyName],
|
|
16
|
+
class: "cm-code-constant",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
tag: [
|
|
20
|
+
t.function(t.variableName),
|
|
21
|
+
t.function(t.propertyName),
|
|
22
|
+
t.function(t.definition(t.variableName)),
|
|
23
|
+
t.className,
|
|
24
|
+
t.definition(t.className),
|
|
25
|
+
t.typeName,
|
|
26
|
+
t.attributeName,
|
|
27
|
+
],
|
|
28
|
+
class: "cm-code-function",
|
|
29
|
+
},
|
|
30
|
+
{ tag: [t.tagName, t.inserted], class: "cm-code-tag" },
|
|
31
|
+
{ tag: [t.standard(t.variableName), t.standard(t.typeName), t.namespace, t.labelName], class: "cm-code-builtin" },
|
|
32
|
+
{ tag: [t.deleted, t.invalid], class: "cm-code-deleted" },
|
|
33
|
+
{ tag: t.punctuation, class: "cm-code-punctuation" },
|
|
34
|
+
{ tag: t.heading, class: "cm-code-bold cm-code-keyword" },
|
|
35
|
+
{ tag: t.strong, class: "cm-code-bold" },
|
|
36
|
+
{ tag: t.emphasis, class: "cm-code-italic" },
|
|
37
|
+
]);
|
|
38
|
+
/** 기본 토큰 색 (GitHub 계열) */
|
|
39
|
+
export const defaultCodeTheme = {
|
|
40
|
+
id: "default",
|
|
41
|
+
highlighter: () => defaultHighlighter,
|
|
42
|
+
extension: EditorView.baseTheme({
|
|
43
|
+
// 코드 블록 상자 색 (상자는 codeBlock이 그립니다)
|
|
44
|
+
"&light .cm-codeblock-line": { "--cm-codeblock-bg": "rgba(135, 131, 120, 0.1)" },
|
|
45
|
+
"&dark .cm-codeblock-line": { "--cm-codeblock-bg": "rgba(255, 255, 255, 0.06)" },
|
|
46
|
+
".cm-code-comment": { fontStyle: "italic" },
|
|
47
|
+
".cm-code-bold": { fontWeight: "bold" },
|
|
48
|
+
".cm-code-italic": { fontStyle: "italic" },
|
|
49
|
+
"&light .cm-code-comment": { color: "#6a737d" },
|
|
50
|
+
"&light .cm-code-keyword": { color: "#d73a49" },
|
|
51
|
+
"&light .cm-code-string": { color: "#032f62" },
|
|
52
|
+
"&light .cm-code-constant": { color: "#005cc5" },
|
|
53
|
+
"&light .cm-code-function": { color: "#6f42c1" },
|
|
54
|
+
"&light .cm-code-tag": { color: "#22863a" },
|
|
55
|
+
"&light .cm-code-builtin": { color: "#e36209" },
|
|
56
|
+
"&light .cm-code-deleted": { color: "#b31d28" },
|
|
57
|
+
"&light .cm-code-punctuation": { color: "#24292e" },
|
|
58
|
+
"&dark .cm-code-comment": { color: "#8b949e" },
|
|
59
|
+
"&dark .cm-code-keyword": { color: "#ff7b72" },
|
|
60
|
+
"&dark .cm-code-string": { color: "#a5d6ff" },
|
|
61
|
+
"&dark .cm-code-constant": { color: "#79c0ff" },
|
|
62
|
+
"&dark .cm-code-function": { color: "#d2a8ff" },
|
|
63
|
+
"&dark .cm-code-tag": { color: "#7ee787" },
|
|
64
|
+
"&dark .cm-code-builtin": { color: "#ffa657" },
|
|
65
|
+
"&dark .cm-code-deleted": { color: "#ffa198" },
|
|
66
|
+
"&dark .cm-code-punctuation": { color: "#c9d1d9" },
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
const scopeTable = (entries) => {
|
|
70
|
+
const map = new Map();
|
|
71
|
+
for (const [tags, scopes] of entries)
|
|
72
|
+
for (const tag of Array.isArray(tags) ? tags : [tags])
|
|
73
|
+
map.set(tag, scopes);
|
|
74
|
+
return map;
|
|
75
|
+
};
|
|
76
|
+
const GENERIC_SCOPES = scopeTable([
|
|
77
|
+
// 주석
|
|
78
|
+
[t.comment, ["comment.line"]],
|
|
79
|
+
[t.lineComment, ["comment.line.double-slash"]],
|
|
80
|
+
[t.blockComment, ["comment.block"]],
|
|
81
|
+
[t.docComment, ["comment.block.documentation"]],
|
|
82
|
+
// 문자열/리터럴
|
|
83
|
+
[t.string, ["string.quoted.double"]],
|
|
84
|
+
[t.docString, ["string.quoted.docstring"]],
|
|
85
|
+
[t.character, ["string.quoted.single"]],
|
|
86
|
+
[t.special(t.string), ["string.template"]],
|
|
87
|
+
[t.regexp, ["string.regexp"]],
|
|
88
|
+
[t.escape, ["constant.character.escape"]],
|
|
89
|
+
[t.attributeValue, ["string.quoted.double"]],
|
|
90
|
+
[t.url, ["markup.underline.link"]],
|
|
91
|
+
[[t.number, t.integer, t.float], ["constant.numeric"]],
|
|
92
|
+
[t.bool, ["constant.language.boolean"]],
|
|
93
|
+
[t.null, ["constant.language.null"]],
|
|
94
|
+
[t.atom, ["constant.language"]],
|
|
95
|
+
[t.unit, ["keyword.other.unit"]],
|
|
96
|
+
[t.color, ["constant.other.color"]],
|
|
97
|
+
// 키워드
|
|
98
|
+
[t.keyword, ["keyword"]],
|
|
99
|
+
[t.controlKeyword, ["keyword.control"]],
|
|
100
|
+
[t.moduleKeyword, ["keyword.control.import"]],
|
|
101
|
+
[t.operatorKeyword, ["keyword.operator.expression"]],
|
|
102
|
+
[t.definitionKeyword, ["storage.type"]],
|
|
103
|
+
[t.modifier, ["storage.modifier"]],
|
|
104
|
+
[t.self, ["variable.language.this"]],
|
|
105
|
+
// 연산자/구두점
|
|
106
|
+
[t.operator, ["keyword.operator"]],
|
|
107
|
+
[t.arithmeticOperator, ["keyword.operator.arithmetic"]],
|
|
108
|
+
[t.logicOperator, ["keyword.operator.logical"]],
|
|
109
|
+
[t.bitwiseOperator, ["keyword.operator.bitwise"]],
|
|
110
|
+
[t.compareOperator, ["keyword.operator.comparison"]],
|
|
111
|
+
[[t.updateOperator, t.definitionOperator], ["keyword.operator.assignment"]],
|
|
112
|
+
[t.typeOperator, ["keyword.operator.type"]],
|
|
113
|
+
[t.controlOperator, ["keyword.operator.logical"]],
|
|
114
|
+
[t.derefOperator, ["punctuation.accessor"]],
|
|
115
|
+
[t.punctuation, ["punctuation"]],
|
|
116
|
+
[t.separator, ["punctuation.separator"]],
|
|
117
|
+
[t.bracket, ["punctuation.bracket"]],
|
|
118
|
+
[t.paren, ["punctuation.parenthesis"]],
|
|
119
|
+
[t.squareBracket, ["punctuation.section.brackets"]],
|
|
120
|
+
[t.function(t.punctuation), ["storage.type.function.arrow"]],
|
|
121
|
+
[t.brace, ["punctuation.definition.block"]],
|
|
122
|
+
[t.angleBracket, ["punctuation.definition.typeparameters"]],
|
|
123
|
+
// 이름
|
|
124
|
+
[t.name, ["variable"]],
|
|
125
|
+
[t.variableName, ["variable.other.readwrite"]],
|
|
126
|
+
[t.definition(t.variableName), ["meta.definition.variable", "variable.other.readwrite"]],
|
|
127
|
+
[t.local(t.variableName), ["variable.other.readwrite"]],
|
|
128
|
+
[t.constant(t.variableName), ["variable.other.constant"]],
|
|
129
|
+
[t.special(t.variableName), ["variable.language"]],
|
|
130
|
+
[t.standard(t.variableName), ["support.variable"]],
|
|
131
|
+
[t.function(t.variableName), ["meta.function-call", "entity.name.function"]],
|
|
132
|
+
[t.function(t.definition(t.variableName)), ["meta.definition.function", "entity.name.function"]],
|
|
133
|
+
[t.function(t.standard(t.variableName)), ["meta.function-call", "support.function"]],
|
|
134
|
+
[t.propertyName, ["variable.other.property"]],
|
|
135
|
+
[t.definition(t.propertyName), ["meta.definition.property", "variable.object.property"]],
|
|
136
|
+
[t.function(t.propertyName), ["meta.function-call", "entity.name.function"]],
|
|
137
|
+
[t.function(t.definition(t.propertyName)), ["meta.definition.method", "entity.name.function"]],
|
|
138
|
+
[t.special(t.propertyName), ["variable.other.property"]],
|
|
139
|
+
[[t.className, t.definition(t.className)], ["meta.class", "entity.name.type.class"]],
|
|
140
|
+
[[t.typeName, t.definition(t.typeName)], ["entity.name.type"]],
|
|
141
|
+
[t.standard(t.typeName), ["support.type.primitive"]],
|
|
142
|
+
[t.namespace, ["entity.name.type.module"]],
|
|
143
|
+
[t.labelName, ["entity.name.label"]],
|
|
144
|
+
[t.macroName, ["entity.name.function.preprocessor"]],
|
|
145
|
+
[t.tagName, ["meta.tag", "entity.name.tag"]],
|
|
146
|
+
[t.attributeName, ["meta.tag", "entity.other.attribute-name"]],
|
|
147
|
+
// 메타
|
|
148
|
+
[t.meta, ["meta"]],
|
|
149
|
+
[t.annotation, ["meta.decorator"]],
|
|
150
|
+
[t.processingInstruction, ["meta.preprocessor"]],
|
|
151
|
+
[t.documentMeta, ["comment.block.documentation"]],
|
|
152
|
+
[t.invalid, ["invalid.illegal"]],
|
|
153
|
+
// 문서 (마크다운 등)
|
|
154
|
+
[t.heading, ["markup.heading"]],
|
|
155
|
+
[t.emphasis, ["markup.italic"]],
|
|
156
|
+
[t.strong, ["markup.bold"]],
|
|
157
|
+
[t.strikethrough, ["markup.strikethrough"]],
|
|
158
|
+
[t.link, ["markup.underline.link"]],
|
|
159
|
+
[t.quote, ["markup.quote"]],
|
|
160
|
+
[t.list, ["punctuation.definition.list"]],
|
|
161
|
+
[t.monospace, ["markup.inline.raw"]],
|
|
162
|
+
[t.inserted, ["markup.inserted"]],
|
|
163
|
+
[t.deleted, ["markup.deleted"]],
|
|
164
|
+
[t.changed, ["markup.changed"]],
|
|
165
|
+
[t.contentSeparator, ["meta.separator"]],
|
|
166
|
+
]);
|
|
167
|
+
/** 언어별로 스코프가 다른 태그 */
|
|
168
|
+
const LANGUAGE_SCOPES = {
|
|
169
|
+
ts: scopeTable([
|
|
170
|
+
// TypeScript/JavaScript 문법은 식의 괄호를 punctuation이 아닌 meta.brace로 둡니다.
|
|
171
|
+
[t.paren, ["meta.brace.round"]],
|
|
172
|
+
[t.squareBracket, ["meta.brace.square"]],
|
|
173
|
+
]),
|
|
174
|
+
css: scopeTable([
|
|
175
|
+
[t.constant(t.className), ["meta.selector", "entity.other.attribute-name.pseudo-class"]],
|
|
176
|
+
[t.modifier, ["keyword.other.important"]],
|
|
177
|
+
[t.definitionKeyword, ["keyword.control.at-rule"]],
|
|
178
|
+
[[t.propertyName, t.definition(t.propertyName)], ["meta.property-name", "support.type.property-name"]],
|
|
179
|
+
[t.tagName, ["meta.selector", "entity.name.tag"]],
|
|
180
|
+
[t.className, ["meta.selector", "entity.other.attribute-name.class"]],
|
|
181
|
+
[t.labelName, ["meta.selector", "entity.other.attribute-name.id"]],
|
|
182
|
+
[t.keyword, ["keyword.control.at-rule"]],
|
|
183
|
+
[t.atom, ["meta.property-value", "support.constant.property-value"]],
|
|
184
|
+
[t.variableName, ["variable.argument"]],
|
|
185
|
+
[t.function(t.variableName), ["meta.function", "support.function"]],
|
|
186
|
+
]),
|
|
187
|
+
json: scopeTable([
|
|
188
|
+
[[t.propertyName, t.definition(t.propertyName)], ["meta.structure.dictionary", "support.type.property-name"]],
|
|
189
|
+
[t.string, ["meta.structure.dictionary.value", "string.quoted.double"]],
|
|
190
|
+
[[t.bool, t.null], ["constant.language"]],
|
|
191
|
+
]),
|
|
192
|
+
yaml: scopeTable([
|
|
193
|
+
[[t.propertyName, t.definition(t.propertyName)], ["entity.name.tag"]],
|
|
194
|
+
[t.content, ["string.unquoted.plain.out"]],
|
|
195
|
+
]),
|
|
196
|
+
html: scopeTable([[t.angleBracket, ["meta.tag", "punctuation.definition.tag"]]]),
|
|
197
|
+
python: scopeTable([
|
|
198
|
+
[t.bool, ["constant.language"]],
|
|
199
|
+
[t.self, ["variable.parameter.function.language.special.self"]],
|
|
200
|
+
[t.function(t.propertyName), ["meta.function-call", "meta.member.access", "entity.name.function"]],
|
|
201
|
+
[t.propertyName, ["meta.member.access"]],
|
|
202
|
+
]),
|
|
203
|
+
};
|
|
204
|
+
LANGUAGE_SCOPES["xml"] = LANGUAGE_SCOPES["html"];
|
|
205
|
+
for (const key of ["js", "js.jsx", "tsx"])
|
|
206
|
+
LANGUAGE_SCOPES[key] = LANGUAGE_SCOPES["ts"];
|
|
207
|
+
LANGUAGE_SCOPES["css.scss"] = LANGUAGE_SCOPES["css"];
|
|
208
|
+
LANGUAGE_SCOPES["css.less"] = LANGUAGE_SCOPES["css"];
|
|
209
|
+
/** 정보 문자열 언어 → TextMate 접미사 */
|
|
210
|
+
const TEXTMATE_SUFFIX = {
|
|
211
|
+
js: "js",
|
|
212
|
+
javascript: "js",
|
|
213
|
+
mjs: "js",
|
|
214
|
+
cjs: "js",
|
|
215
|
+
jsx: "js.jsx",
|
|
216
|
+
ts: "ts",
|
|
217
|
+
typescript: "ts",
|
|
218
|
+
mts: "ts",
|
|
219
|
+
tsx: "tsx",
|
|
220
|
+
py: "python",
|
|
221
|
+
python: "python",
|
|
222
|
+
css: "css",
|
|
223
|
+
scss: "css.scss",
|
|
224
|
+
less: "css.less",
|
|
225
|
+
json: "json",
|
|
226
|
+
jsonc: "json",
|
|
227
|
+
yaml: "yaml",
|
|
228
|
+
yml: "yaml",
|
|
229
|
+
html: "html",
|
|
230
|
+
htm: "html",
|
|
231
|
+
xml: "xml",
|
|
232
|
+
svg: "xml",
|
|
233
|
+
md: "markdown",
|
|
234
|
+
markdown: "markdown",
|
|
235
|
+
rs: "rust",
|
|
236
|
+
rust: "rust",
|
|
237
|
+
go: "go",
|
|
238
|
+
java: "java",
|
|
239
|
+
c: "c",
|
|
240
|
+
h: "c",
|
|
241
|
+
cpp: "cpp",
|
|
242
|
+
"c++": "cpp",
|
|
243
|
+
cc: "cpp",
|
|
244
|
+
cs: "cs",
|
|
245
|
+
csharp: "cs",
|
|
246
|
+
php: "php",
|
|
247
|
+
sql: "sql",
|
|
248
|
+
sh: "shell",
|
|
249
|
+
bash: "shell",
|
|
250
|
+
zsh: "shell",
|
|
251
|
+
shell: "shell",
|
|
252
|
+
rb: "ruby",
|
|
253
|
+
ruby: "ruby",
|
|
254
|
+
kt: "kotlin",
|
|
255
|
+
kotlin: "kotlin",
|
|
256
|
+
swift: "swift",
|
|
257
|
+
ini: "ini",
|
|
258
|
+
toml: "toml",
|
|
259
|
+
};
|
|
260
|
+
const ROOT_SCOPE = {
|
|
261
|
+
html: "text.html.basic",
|
|
262
|
+
xml: "text.xml",
|
|
263
|
+
markdown: "text.html.markdown",
|
|
264
|
+
};
|
|
265
|
+
/** 언어의 TextMate 접미사와 최상위 스코프 */
|
|
266
|
+
export function textMateLanguage(lang) {
|
|
267
|
+
const suffix = TEXTMATE_SUFFIX[lang] ?? (/^[a-z][a-z0-9+#-]*$/.test(lang) ? lang : "");
|
|
268
|
+
return { suffix, root: ROOT_SCOPE[suffix] ?? (suffix ? `source.${suffix}` : "source") };
|
|
269
|
+
}
|
|
270
|
+
/** 태그의 스코프 경로 (가장 구체적인 태그부터 찾음). 없으면 null */
|
|
271
|
+
export function scopesForTag(tag, lang) {
|
|
272
|
+
const { suffix, root } = textMateLanguage(lang);
|
|
273
|
+
const own = LANGUAGE_SCOPES[suffix];
|
|
274
|
+
for (const candidate of tag.set) {
|
|
275
|
+
const scopes = own?.get(candidate) ?? GENERIC_SCOPES.get(candidate);
|
|
276
|
+
if (scopes)
|
|
277
|
+
return [root, ...scopes.map((s) => (suffix ? `${s}.${suffix}` : s))];
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
let themeCount = 0;
|
|
282
|
+
/**
|
|
283
|
+
* VS Code 색 테마(JSON/JSONC 문자열 또는 객체)를 코드 블록 테마로 바꿉니다.
|
|
284
|
+
* 토큰 색은 VS Code와 같은 방식(TextMate 스코프 매칭)으로 정합니다. 다만 Lezer 문법이 구분하지 않는
|
|
285
|
+
* 차이(예: 매개변수와 지역 변수)는 재현되지 않습니다.
|
|
286
|
+
*/
|
|
287
|
+
export function vscodeTheme(source, options = {}) {
|
|
288
|
+
const json = (typeof source === "string" ? parseJsonc(source) : source);
|
|
289
|
+
if (!json || typeof json !== "object")
|
|
290
|
+
throw new TypeError("vscodeTheme: 테마 JSON 객체가 아닙니다.");
|
|
291
|
+
const colors = json.colors ?? {};
|
|
292
|
+
const rules = Array.isArray(json.tokenColors) ? json.tokenColors : Array.isArray(json.settings) ? json.settings : [];
|
|
293
|
+
const tm = textMateTheme(rules, colors["editor.foreground"]);
|
|
294
|
+
const id = `vsc${++themeCount}`;
|
|
295
|
+
// 글자 색과 글꼴 모양은 따로 클래스를 만들어 조합합니다. (규칙에 쓰인 색 × 모양 조합을 미리 만들 필요가 없음)
|
|
296
|
+
const colorClass = new Map(tm.colors.map((color, i) => [color, `cm-${id}-c${i}`]));
|
|
297
|
+
const classFor = (style) => {
|
|
298
|
+
const cls = [];
|
|
299
|
+
if (style.foreground && style.foreground !== tm.foreground)
|
|
300
|
+
cls.push(colorClass.get(style.foreground));
|
|
301
|
+
if (style.fontStyle > 0)
|
|
302
|
+
cls.push(`cm-${id}-f${style.fontStyle}`);
|
|
303
|
+
return cls.length ? cls.join(" ") : null;
|
|
304
|
+
};
|
|
305
|
+
const highlighters = new Map();
|
|
306
|
+
const highlighter = (lang) => {
|
|
307
|
+
const key = textMateLanguage(lang).suffix;
|
|
308
|
+
let hl = highlighters.get(key);
|
|
309
|
+
if (!hl) {
|
|
310
|
+
const memo = new Map();
|
|
311
|
+
hl = {
|
|
312
|
+
style(tags) {
|
|
313
|
+
let cls = memo.get(tags);
|
|
314
|
+
if (cls === undefined) {
|
|
315
|
+
const parts = [];
|
|
316
|
+
for (const tag of tags) {
|
|
317
|
+
const scopes = scopesForTag(tag, lang);
|
|
318
|
+
const c = scopes && classFor(tm.resolve(scopes));
|
|
319
|
+
if (c)
|
|
320
|
+
parts.push(c);
|
|
321
|
+
}
|
|
322
|
+
cls = parts.length ? parts.join(" ") : null;
|
|
323
|
+
memo.set(tags, cls);
|
|
324
|
+
}
|
|
325
|
+
return cls;
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
highlighters.set(key, hl);
|
|
329
|
+
}
|
|
330
|
+
return hl;
|
|
331
|
+
};
|
|
332
|
+
// 따옴표: VS Code 문법은 따옴표를 punctuation.definition.string으로 따로 둡니다.
|
|
333
|
+
const quoteClasses = new Map();
|
|
334
|
+
const quoteClass = (lang) => {
|
|
335
|
+
const { suffix, root } = textMateLanguage(lang);
|
|
336
|
+
let cls = quoteClasses.get(suffix);
|
|
337
|
+
if (cls === undefined) {
|
|
338
|
+
const sfx = suffix ? `.${suffix}` : "";
|
|
339
|
+
const quote = classFor(tm.resolve([root, `string.quoted.double${sfx}`, `punctuation.definition.string.begin${sfx}`]));
|
|
340
|
+
const body = classFor(tm.resolve([root, `string.quoted.double${sfx}`]));
|
|
341
|
+
// 내용과 색이 같으면 나눌 필요가 없습니다.
|
|
342
|
+
cls = quote !== body ? (quote ?? `cm-${id}-plain`) : null;
|
|
343
|
+
quoteClasses.set(suffix, cls);
|
|
344
|
+
}
|
|
345
|
+
return cls;
|
|
346
|
+
};
|
|
347
|
+
const spec = {};
|
|
348
|
+
for (const [color, cls] of colorClass)
|
|
349
|
+
spec[`.${cls}`] = { color };
|
|
350
|
+
for (let f = 1; f < 16; f++) {
|
|
351
|
+
spec[`.cm-${id}-f${f}`] = {
|
|
352
|
+
fontStyle: f & FontStyle.Italic ? "italic" : "normal",
|
|
353
|
+
fontWeight: f & FontStyle.Bold ? "bold" : "normal",
|
|
354
|
+
textDecoration: [f & FontStyle.Underline ? "underline" : "", f & FontStyle.Strikethrough ? "line-through" : ""]
|
|
355
|
+
.filter(Boolean)
|
|
356
|
+
.join(" ") || "none",
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
// 코드 블록 바탕. 기본 테마(baseTheme의 &light/&dark 규칙)보다 구체적인 선택자를 씁니다.
|
|
360
|
+
const block = "&.cm-editor .cm-content .cm-codeblock-line";
|
|
361
|
+
const background = options.background !== false ? colors["editor.background"] : undefined;
|
|
362
|
+
const lineStyle = {};
|
|
363
|
+
if (tm.foreground)
|
|
364
|
+
lineStyle["color"] = tm.foreground;
|
|
365
|
+
if (background)
|
|
366
|
+
lineStyle["--cm-codeblock-bg"] = background;
|
|
367
|
+
if (colors["editorCursor.foreground"])
|
|
368
|
+
lineStyle["caretColor"] = colors["editorCursor.foreground"];
|
|
369
|
+
spec[block] = lineStyle;
|
|
370
|
+
const selection = colors["editor.selectionBackground"];
|
|
371
|
+
if (selection)
|
|
372
|
+
spec[`${block} .cm-codeblock-selected`] = { backgroundColor: selection };
|
|
373
|
+
if (colors["editorCursor.foreground"]) {
|
|
374
|
+
spec["&.cm-codeblock-cursor .cm-cursor"] = { borderLeftColor: colors["editorCursor.foreground"] };
|
|
375
|
+
}
|
|
376
|
+
// 도구 모음도 테마 색으로
|
|
377
|
+
const widgetBg = colors["editorHoverWidget.background"] ?? colors["editorWidget.background"] ?? background;
|
|
378
|
+
if (widgetBg) {
|
|
379
|
+
spec[`${block} .cm-codeblock-toolbar`] = {
|
|
380
|
+
backgroundColor: widgetBg,
|
|
381
|
+
borderColor: colors["editorHoverWidget.border"] ?? colors["editorWidget.border"] ?? "transparent",
|
|
382
|
+
color: colors["descriptionForeground"] ?? colors["editorLineNumber.activeForeground"] ?? tm.foreground ?? "inherit",
|
|
383
|
+
};
|
|
384
|
+
if (tm.foreground)
|
|
385
|
+
spec[`${block} .cm-codeblock-copy:hover`] = { color: tm.foreground };
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
id,
|
|
389
|
+
highlighter,
|
|
390
|
+
quoteClass,
|
|
391
|
+
// dark 옵션은 주지 않습니다: 에디터 전체가 아니라 코드 블록에만 적용되는 테마입니다.
|
|
392
|
+
extension: EditorView.theme(spec),
|
|
393
|
+
};
|
|
394
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MarkdownConfig } from "@lezer/markdown";
|
|
2
|
+
import { type Tag } from "@lezer/highlight";
|
|
3
|
+
export interface DoubleDelimiterSpec {
|
|
4
|
+
/** 노드 이름 (예: "Highlight"). 기호 노드 이름은 `${name}Mark`가 됩니다. */
|
|
5
|
+
readonly name: string;
|
|
6
|
+
/** 구분자 문자 한 글자 (예: "=" → `==text==`) */
|
|
7
|
+
readonly char: string;
|
|
8
|
+
/** 노드와 그 자식 전체에 적용할 하이라이트 태그 */
|
|
9
|
+
readonly tag: Tag;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `XXtextXX` 형태(같은 문자 2개로 감싸는) 인라인 문법을 만드는 Lezer Markdown 확장 팩토리입니다.
|
|
13
|
+
*
|
|
14
|
+
* 열고 닫는 규칙은 GFM 취소선(`~~`)과 같은 CommonMark flanking 규칙을 따르며,
|
|
15
|
+
* 같은 문자가 3개 이상 연속되면 시작 위치에서는 구분자로 보지 않습니다. (`~~`와 동일)
|
|
16
|
+
*
|
|
17
|
+
* 참고: GFM `~~`와 마찬가지로 단어 중간의 구분자도 열고 닫을 수 있습니다.
|
|
18
|
+
* 예: `1--2, 3--4` → `--2, 3--`가 Underline. (`_`처럼 제한하지 않기로 결정한 동작)
|
|
19
|
+
*/
|
|
20
|
+
export declare function doubleDelimiterSyntax({ name, char, tag }: DoubleDelimiterSpec): MarkdownConfig;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { tags } from "@lezer/highlight";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// 문자 분류 (CommonMark flanking 규칙용)
|
|
4
|
+
//
|
|
5
|
+
// @lezer/markdown 내장 Emphasis/Strikethrough와 동일한 판정을 하되,
|
|
6
|
+
// 문자열 slice + 정규식 대신 문자 코드로 판정합니다.
|
|
7
|
+
// - ASCII는 모듈 로드 시 1회 만든 테이블로 O(1) 조회
|
|
8
|
+
// - 비ASCII만 정규식으로 판정 (Lezer와 같은 Unicode \p{P}/\p{S} 기준)
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
const OTHER = 0;
|
|
11
|
+
const SPACE = 1; // 공백 또는 구간 경계(줄 시작/끝)
|
|
12
|
+
const PUNCT = 2;
|
|
13
|
+
const SpaceRe = /\s/;
|
|
14
|
+
const PunctuationRe = /[\p{S}\p{P}]/u;
|
|
15
|
+
function classifySlow(code) {
|
|
16
|
+
const ch = String.fromCharCode(code);
|
|
17
|
+
return SpaceRe.test(ch) ? SPACE : PunctuationRe.test(ch) ? PUNCT : OTHER;
|
|
18
|
+
}
|
|
19
|
+
const asciiKind = new Uint8Array(128);
|
|
20
|
+
for (let code = 0; code < 128; code++)
|
|
21
|
+
asciiKind[code] = classifySlow(code);
|
|
22
|
+
/** code가 -1(구간 끝)이면 공백으로 취급합니다. (Lezer의 /\s|^$/ 와 동일) */
|
|
23
|
+
function charKind(code) {
|
|
24
|
+
if (code < 0)
|
|
25
|
+
return SPACE;
|
|
26
|
+
return code < 128 ? asciiKind[code] : classifySlow(code);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `XXtextXX` 형태(같은 문자 2개로 감싸는) 인라인 문법을 만드는 Lezer Markdown 확장 팩토리입니다.
|
|
30
|
+
*
|
|
31
|
+
* 열고 닫는 규칙은 GFM 취소선(`~~`)과 같은 CommonMark flanking 규칙을 따르며,
|
|
32
|
+
* 같은 문자가 3개 이상 연속되면 시작 위치에서는 구분자로 보지 않습니다. (`~~`와 동일)
|
|
33
|
+
*
|
|
34
|
+
* 참고: GFM `~~`와 마찬가지로 단어 중간의 구분자도 열고 닫을 수 있습니다.
|
|
35
|
+
* 예: `1--2, 3--4` → `--2, 3--`가 Underline. (`_`처럼 제한하지 않기로 결정한 동작)
|
|
36
|
+
*/
|
|
37
|
+
export function doubleDelimiterSyntax({ name, char, tag }) {
|
|
38
|
+
if (char.length !== 1)
|
|
39
|
+
throw new RangeError(`char must be a single character: ${char}`);
|
|
40
|
+
const code = char.charCodeAt(0);
|
|
41
|
+
const mark = `${name}Mark`;
|
|
42
|
+
const delimiter = { resolve: name, mark };
|
|
43
|
+
return {
|
|
44
|
+
defineNodes: [
|
|
45
|
+
// "/..." : 내부의 강조/코드 등 자식 노드에도 스타일이 상속되도록 합니다.
|
|
46
|
+
{ name, style: { [`${name}/...`]: tag } },
|
|
47
|
+
{ name: mark, style: tags.processingInstruction },
|
|
48
|
+
],
|
|
49
|
+
parseInline: [
|
|
50
|
+
{
|
|
51
|
+
name,
|
|
52
|
+
parse(cx, next, pos) {
|
|
53
|
+
// 핫 패스: 모든 문자 위치마다 호출되므로 첫 비교로 즉시 빠져나갑니다.
|
|
54
|
+
if (next !== code || cx.char(pos + 1) !== code || cx.char(pos + 2) === code) {
|
|
55
|
+
return -1;
|
|
56
|
+
}
|
|
57
|
+
// cx.char()는 구간 시작 이전 위치에서 NaN을 반환하므로 직접 경계를 처리합니다.
|
|
58
|
+
const before = pos > cx.offset ? charKind(cx.char(pos - 1)) : SPACE;
|
|
59
|
+
const after = charKind(cx.char(pos + 2));
|
|
60
|
+
const canOpen = after !== SPACE && (after !== PUNCT || before !== OTHER);
|
|
61
|
+
const canClose = before !== SPACE && (before !== PUNCT || after !== OTHER);
|
|
62
|
+
// 열지도 닫지도 못하는 구분자는 매칭될 일이 없습니다.
|
|
63
|
+
// Lezer는 이런 구분자도 parts 배열에 쌓고, 닫는 구분자마다 문단 시작까지
|
|
64
|
+
// 역방향으로 훑으므로(O(n²)), 아예 추가하지 않고 일반 텍스트로 둡니다.
|
|
65
|
+
if (!canOpen && !canClose)
|
|
66
|
+
return -1;
|
|
67
|
+
return cx.addDelimiter(delimiter, pos, pos + 2, canOpen, canClose);
|
|
68
|
+
},
|
|
69
|
+
after: "Emphasis",
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
}
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type Extension } from "@codemirror/state";
|
|
2
|
+
import { EditorView } from "@codemirror/view";
|
|
3
|
+
import { type CodeBlockOptions } from "./codeBlock.js";
|
|
4
|
+
import { type ExtendedMarkdownOptions } from "./extensions.js";
|
|
5
|
+
import { type ImageOptions } from "./image.js";
|
|
6
|
+
import { type LinkOptions } from "./link.js";
|
|
7
|
+
import { type MathOptions } from "./math.js";
|
|
8
|
+
import { type TikzJaxOptions, type TikzOptions } from "./tikz.js";
|
|
9
|
+
/** 켜고 끌 수 있는 기능. 모두 기본으로 켜져 있습니다. (TikZ는 tikz 옵션을 줄 때만) */
|
|
10
|
+
export interface MDSquareFeatures {
|
|
11
|
+
/** 굵게, 기울임, 취소선, 밑줄(`--`), 하이라이트(`==`) */
|
|
12
|
+
emphasis?: boolean;
|
|
13
|
+
heading?: boolean;
|
|
14
|
+
hashtag?: boolean;
|
|
15
|
+
mention?: boolean;
|
|
16
|
+
/** `\*` 같은 이스케이프 */
|
|
17
|
+
escape?: boolean;
|
|
18
|
+
inlineCode?: boolean;
|
|
19
|
+
/** 불릿/번호 목록 (+ Tab/Shift-Tab 들여쓰기) */
|
|
20
|
+
list?: boolean;
|
|
21
|
+
/** 작업 목록 `- [ ]` */
|
|
22
|
+
task?: boolean;
|
|
23
|
+
link?: boolean;
|
|
24
|
+
image?: boolean;
|
|
25
|
+
horizontalRule?: boolean;
|
|
26
|
+
footnote?: boolean;
|
|
27
|
+
quote?: boolean;
|
|
28
|
+
/** Obsidian 콜아웃 / GFM 알림 `> [!note]` (quote 포함) */
|
|
29
|
+
callout?: boolean;
|
|
30
|
+
/** 코드 블록 (구문 강조, 복사 버튼) */
|
|
31
|
+
codeBlock?: boolean;
|
|
32
|
+
/** LaTeX 수식 `$…$`, `$$…$$` (KaTeX) */
|
|
33
|
+
math?: boolean;
|
|
34
|
+
/** GFM 표 */
|
|
35
|
+
table?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export type MDSquareTheme = "light" | "dark" | "auto";
|
|
38
|
+
export interface MDSquareEditorOptions {
|
|
39
|
+
/** 에디터를 넣을 요소. 없으면 나중에 `editor.dom`을 직접 붙입니다. */
|
|
40
|
+
parent?: Element | DocumentFragment;
|
|
41
|
+
/** 처음 문서 (마크다운) */
|
|
42
|
+
value?: string;
|
|
43
|
+
/** 문서가 바뀔 때마다 호출됩니다. (setValue로 바꿀 때도) */
|
|
44
|
+
onChange?: (value: string, editor: MDSquareEditor) => void;
|
|
45
|
+
/** 밝은/어두운 테마. "auto"는 시스템 설정을 따릅니다. (기본 "auto") */
|
|
46
|
+
theme?: MDSquareTheme;
|
|
47
|
+
/** 읽기 전용 (기본 false) */
|
|
48
|
+
readOnly?: boolean;
|
|
49
|
+
/** 문서가 비었을 때 보여줄 글 */
|
|
50
|
+
placeholder?: string;
|
|
51
|
+
/** 줄 번호 (기본 false) */
|
|
52
|
+
lineNumbers?: boolean;
|
|
53
|
+
/** 기능 켜고 끄기 (기본 모두 켬) */
|
|
54
|
+
features?: MDSquareFeatures;
|
|
55
|
+
/**
|
|
56
|
+
* 코드 블록 옵션. languages를 주지 않으면 `@codemirror/language-data`의 언어를 씁니다(쓸 때 불러옴).
|
|
57
|
+
* `tikz` 블록은 LaTeX로 강조합니다.
|
|
58
|
+
*/
|
|
59
|
+
codeBlock?: CodeBlockOptions;
|
|
60
|
+
image?: ImageOptions;
|
|
61
|
+
link?: LinkOptions;
|
|
62
|
+
math?: MathOptions;
|
|
63
|
+
/**
|
|
64
|
+
* TikZ 그림(```` ```tikz ````). 주면 켜집니다.
|
|
65
|
+
* - `{ tikzjax: { src } }`: TikZJax(`@drgrice1/tikzjax`, GPL-3.0)의 dist 폴더를 앱이 제공하는 주소
|
|
66
|
+
* - `{ render }`: 직접 만든 렌더러 (서버 렌더링 등)
|
|
67
|
+
*/
|
|
68
|
+
tikz?: (TikzOptions & {
|
|
69
|
+
tikzjax?: TikzJaxOptions;
|
|
70
|
+
}) | false;
|
|
71
|
+
/** 마크다운 문법 옵션 (목록 Enter 동작 등) */
|
|
72
|
+
markdown?: ExtendedMarkdownOptions;
|
|
73
|
+
/** 덧붙일 CodeMirror 확장 */
|
|
74
|
+
extensions?: Extension;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 하이브리드 마크다운 에디터 (CodeMirror 6 기반).
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* import MDSquareEditor from "mdsquare";
|
|
81
|
+
* import "mdsquare/style.css";
|
|
82
|
+
*
|
|
83
|
+
* const editor = new MDSquareEditor({ parent: document.getElementById("editor")!, value: "# 안녕하세요" });
|
|
84
|
+
* editor.getValue();
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare class MDSquareEditor {
|
|
88
|
+
/** CodeMirror 뷰 (확장을 직접 다룰 때) */
|
|
89
|
+
readonly view: EditorView;
|
|
90
|
+
private readonly themeSlot;
|
|
91
|
+
private readonly readOnlySlot;
|
|
92
|
+
private theme;
|
|
93
|
+
private media;
|
|
94
|
+
private readonly onMediaChange;
|
|
95
|
+
/** 옵션으로 정해지는 확장들. 파일을 새로 열 때도 같은 것을 써서 렌더링 캐시(수식, TikZ 등)를 이어 씁니다. */
|
|
96
|
+
private readonly extensions;
|
|
97
|
+
private readOnly;
|
|
98
|
+
constructor(options?: MDSquareEditorOptions);
|
|
99
|
+
/** 지금 설정(테마, 읽기 전용)으로 새 상태를 만듭니다. */
|
|
100
|
+
private createState;
|
|
101
|
+
/** 에디터 바깥 요소 (`.cm-editor`) */
|
|
102
|
+
get dom(): HTMLElement;
|
|
103
|
+
/** 지금 문서 (마크다운) */
|
|
104
|
+
getValue(): string;
|
|
105
|
+
/**
|
|
106
|
+
* 다른 파일(문서)을 엽니다. 처음 연 것처럼 새로 시작합니다.
|
|
107
|
+
* - 실행 취소 기록을 새로 시작합니다. (Ctrl+Z로 이전 파일 내용으로 돌아가지 않음)
|
|
108
|
+
* - onChange를 부르지 않습니다. (방금 연 파일을 바로 저장하지 않음)
|
|
109
|
+
* - 커서는 문서 처음, 스크롤은 맨 위. 접기·열린 메뉴 등 화면 상태도 초기화합니다.
|
|
110
|
+
* - 테마, 읽기 전용 등 설정은 그대로입니다.
|
|
111
|
+
*
|
|
112
|
+
* 같은 문서 안에서 내용을 바꾸는 것(실행 취소할 수 있어야 하는 편집)은 setValue를 쓰세요.
|
|
113
|
+
*/
|
|
114
|
+
open(value: string): void;
|
|
115
|
+
/**
|
|
116
|
+
* 지금 문서의 내용을 바꿉니다. 편집처럼 다뤄 실행 취소할 수 있고 onChange도 호출됩니다. 커서는 문서 처음으로.
|
|
117
|
+
* 다른 파일을 여는 것이라면 open을 쓰세요.
|
|
118
|
+
*/
|
|
119
|
+
setValue(value: string): void;
|
|
120
|
+
focus(): void;
|
|
121
|
+
/** 테마 바꾸기 ("auto": 시스템 설정을 따르고, 설정이 바뀌면 함께 바뀜) */
|
|
122
|
+
setTheme(theme: MDSquareTheme): void;
|
|
123
|
+
setReadOnly(readOnly: boolean): void;
|
|
124
|
+
/** 에디터를 없애고 이벤트를 정리합니다. */
|
|
125
|
+
destroy(): void;
|
|
126
|
+
private themeExtension;
|
|
127
|
+
private applyTheme;
|
|
128
|
+
private watchSystemTheme;
|
|
129
|
+
}
|
|
130
|
+
/** 옵션에 따라 마크다운 확장들을 고릅니다. */
|
|
131
|
+
export declare function markdownExtensions(options?: MDSquareEditorOptions): Extension;
|
|
132
|
+
export default MDSquareEditor;
|