@lvce-editor/shared-process 0.12.0 → 0.13.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.
Files changed (102) hide show
  1. package/config/defaultKeyBindings.json +5 -0
  2. package/config/defaultSettings.json +4 -0
  3. package/extensions/builtin.language-basics-graphql/extension.json +1 -1
  4. package/extensions/builtin.language-basics-graphql/src/tokenizeGraphql.js +408 -4
  5. package/extensions/builtin.language-basics-html/src/tokenizeHtml.js +91 -3
  6. package/extensions/builtin.language-basics-javascript/src/tokenizeJavaScript.js +7 -0
  7. package/extensions/builtin.language-basics-json/extension.json +3 -1
  8. package/extensions/builtin.language-basics-jsx/README.md +14 -0
  9. package/extensions/builtin.language-basics-jsx/extension.json +13 -0
  10. package/extensions/builtin.language-basics-jsx/src/tokenizeJsx.js +648 -0
  11. package/extensions/builtin.language-basics-julia/src/tokenizeJulia.js +52 -1
  12. package/extensions/builtin.language-basics-markdown/src/tokenizeMarkdown.js +82 -2
  13. package/extensions/builtin.language-basics-mdx/README.md +14 -0
  14. package/extensions/builtin.language-basics-mdx/extension.json +12 -0
  15. package/extensions/builtin.language-basics-mdx/src/tokenizeMdx.js +395 -0
  16. package/extensions/builtin.language-basics-shellscript/src/tokenizeShellScript.js +22 -1
  17. package/extensions/builtin.language-basics-toml/src/tokenizeToml.js +29 -1
  18. package/extensions/builtin.language-basics-typescript/extension.json +1 -1
  19. package/extensions/builtin.language-basics-typescript/src/tokenizeTypeScript.js +128 -12
  20. package/extensions/builtin.language-basics-xml/extension.json +3 -2
  21. package/extensions/builtin.language-basics-xml/src/tokenizeXml.js +26 -3
  22. package/extensions/builtin.language-basics-yaml/src/tokenizeYaml.js +7 -1
  23. package/extensions/builtin.theme-atom-one-dark/color-theme.json +4 -0
  24. package/extensions/builtin.theme-cobalt2/color-theme.json +4 -0
  25. package/extensions/builtin.theme-gruvbox/color-theme.json +4 -0
  26. package/extensions/builtin.vscode-icons/icon-theme.json +40 -2
  27. package/extensions/builtin.vscode-icons/icons/file_type_bazel_ignore.svg +1 -0
  28. package/extensions/builtin.vscode-icons/icons/file_type_bazel_version.svg +1 -0
  29. package/extensions/builtin.vscode-icons/icons/file_type_eleventy.svg +1 -0
  30. package/extensions/builtin.vscode-icons/icons/file_type_eleventy2.svg +1 -0
  31. package/extensions/builtin.vscode-icons/icons/file_type_light_eleventy.svg +1 -0
  32. package/extensions/builtin.vscode-icons/icons/file_type_light_eleventy2.svg +1 -0
  33. package/extensions/builtin.vscode-icons/icons/file_type_light_rome.svg +1 -0
  34. package/extensions/builtin.vscode-icons/icons/file_type_light_tree.svg +1 -0
  35. package/extensions/builtin.vscode-icons/icons/file_type_mondoo.svg +1 -0
  36. package/extensions/builtin.vscode-icons/icons/file_type_nuxt.svg +1 -1
  37. package/extensions/builtin.vscode-icons/icons/file_type_rome.svg +1 -0
  38. package/extensions/builtin.vscode-icons/icons/file_type_sapphire_framework_cli.svg +1 -0
  39. package/extensions/builtin.vscode-icons/icons/file_type_shellcheck.svg +91 -0
  40. package/extensions/builtin.vscode-icons/icons/file_type_shuttle.svg +1 -0
  41. package/extensions/builtin.vscode-icons/icons/file_type_tree.svg +1 -0
  42. package/extensions/builtin.vscode-icons/icons/folder_type_nuxt.svg +1 -1
  43. package/extensions/builtin.vscode-icons/icons/folder_type_nuxt_opened.svg +1 -1
  44. package/package.json +7 -6
  45. package/src/parts/CleanStack/CleanStack.js +5 -0
  46. package/src/parts/Cli/Cli.js +5 -4
  47. package/src/parts/CliCommandType/CliCommandType.js +10 -0
  48. package/src/parts/CliInstall/CliInstall.js +3 -2
  49. package/src/parts/CliLink/CliLink.js +3 -2
  50. package/src/parts/CliList/CliList.js +3 -1
  51. package/src/parts/ClipBoard/ClipBoard.js +3 -2
  52. package/src/parts/ClipBoard/ClipBoardGnome.js +15 -31
  53. package/src/parts/CommandNotFoundError/CommandNotFoundError.js +9 -0
  54. package/src/parts/DesktopType/DesktopType.js +3 -0
  55. package/src/parts/Download/Download.js +1 -1
  56. package/src/parts/DownloadAndExtract/DownloadAndExtract.js +2 -2
  57. package/src/parts/Error/FileSystemError.js +1 -1
  58. package/src/parts/ErrorCodes/ErrorCodes.js +2 -0
  59. package/src/parts/ErrorHandling/ErrorHandling.js +4 -3
  60. package/src/parts/ExecCommand/ExecCommand.js +25 -0
  61. package/src/parts/ExecPromise/ExecPromise.js +4 -0
  62. package/src/parts/ExitCode/ExitCode.js +5 -0
  63. package/src/parts/ExportStatic/ExportStatic.js +2 -2
  64. package/src/parts/ExtensionHost/ExtensionHost.ipc.js +0 -1
  65. package/src/parts/ExtensionHost/ExtensionHost.js +1 -1
  66. package/src/parts/ExtensionHostIpc/ExtensionHostIpcWithChildProcess.js +3 -8
  67. package/src/parts/ExtensionHostIpc/ExtensionHostIpcWithWorker.js +3 -7
  68. package/src/parts/ExtensionInstallFromFile/ExtensionInstallFromFile.js +2 -5
  69. package/src/parts/ExtensionInstallFromGitHub/ExtensionInstallFromGitHub.js +1 -1
  70. package/src/parts/ExtensionInstallFromUrl/ExtensionInstallFromUrl.js +3 -3
  71. package/src/parts/ExtensionLink/ExtensionLink.js +19 -0
  72. package/src/parts/ExtensionManagement/ExtensionManagement.ipc.js +1 -1
  73. package/src/parts/ExtensionManagement/ExtensionManagementColorTheme.js +3 -2
  74. package/src/parts/ExtensionManagement/ExtensionManagementLanguages.js +7 -14
  75. package/src/parts/ExtensionManifest/ExtensionManifest.js +14 -4
  76. package/src/parts/ExtractZip/ExtractZip.js +1 -1
  77. package/src/parts/GetResponse/GetResponse.js +2 -1
  78. package/src/parts/GitLsFiles/GitLsFiles.ipc.js +2 -0
  79. package/src/parts/GitLsFiles/GitLsFiles.js +21 -5
  80. package/src/parts/Hash/Hash.js +7 -0
  81. package/src/parts/IpcChild/IpcChild.js +6 -0
  82. package/src/parts/IpcChildModule/IpcChildModule.js +12 -0
  83. package/src/parts/IpcChildType/IpcChildType.js +13 -0
  84. package/src/parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js +19 -0
  85. package/src/parts/IpcChildWithNodeWorker/IpcChildWithNodeWorker.js +27 -0
  86. package/src/parts/MergeStacks/MergeStacks.js +19 -0
  87. package/src/parts/ModuleMap/ModuleMap.js +4 -1
  88. package/src/parts/NormalizeErrorLine/NormalizeErrorLine.js +9 -0
  89. package/src/parts/OutputChannel/OutputChannel.ipc.js +1 -1
  90. package/src/parts/ParentIpc/ParentIpc.js +6 -10
  91. package/src/parts/ParseInt/ParseInt.js +3 -0
  92. package/src/parts/Platform/Platform.js +16 -21
  93. package/src/parts/Preferences/Preferences.js +2 -1
  94. package/src/parts/PrettyError/PrettyError.js +12 -23
  95. package/src/parts/PrintPrettyError/PrintPrettyError.js +3 -0
  96. package/src/parts/Process/Process.js +2 -2
  97. package/src/parts/ProtocolType/ProtocolType.js +3 -0
  98. package/src/parts/RecentlyOpened/RecentlyOpened.js +1 -1
  99. package/src/parts/Stats/Stats.js +8 -11
  100. package/src/parts/SymLink/SymLink.js +2 -14
  101. package/src/parts/TextDocument/TextDocument.js +3 -1
  102. package/src/parts/VError/VError.js +5 -22
@@ -22,6 +22,12 @@ export const TokenType = {
22
22
  String: 4,
23
23
  Numeric: 5,
24
24
  Attribute: 6,
25
+ KeywordReturn: 8,
26
+ LanguageConstant: 9,
27
+ KeywordImport: 10,
28
+ KeywordControl: 11,
29
+ KeywordOperator: 12,
30
+ KeywordFunction: 13,
25
31
  }
26
32
 
27
33
  export const TokenMap = {
@@ -34,6 +40,12 @@ export const TokenMap = {
34
40
  [TokenType.String]: 'String',
35
41
  [TokenType.Numeric]: 'Numeric',
36
42
  [TokenType.Attribute]: 'Attribute',
43
+ [TokenType.KeywordReturn]: 'KeywordReturn',
44
+ [TokenType.KeywordImport]: 'KeywordImport',
45
+ [TokenType.LanguageConstant]: 'LanguageConstant',
46
+ [TokenType.KeywordControl]: 'KeywordControl',
47
+ [TokenType.KeywordOperator]: 'KeywordOperator',
48
+ [TokenType.KeywordFunction]: 'KeywordFunction',
37
49
  }
38
50
 
39
51
  export const initialLineState = {
@@ -69,7 +81,46 @@ export const tokenizeLine = (line, lineState) => {
69
81
  token = TokenType.Whitespace
70
82
  state = State.TopLevelContent
71
83
  } else if ((next = part.match(RE_KEYWORD))) {
72
- token = TokenType.Keyword
84
+ switch (next[0]) {
85
+ case 'true':
86
+ case 'false':
87
+ token = TokenType.LanguageConstant
88
+ break
89
+ case 'import':
90
+ case 'export':
91
+ token = TokenType.KeywordImport
92
+ break
93
+ case 'begin':
94
+ case 'break':
95
+ case 'catch':
96
+ case 'continue':
97
+ case 'do':
98
+ case 'else':
99
+ case 'elseif':
100
+ case 'end':
101
+ case 'finally':
102
+ case 'for':
103
+ case 'if':
104
+ case 'try':
105
+ case 'catch':
106
+ case 'finally':
107
+ case 'continue':
108
+ case 'while':
109
+ token = TokenType.KeywordControl
110
+ break
111
+ case 'return':
112
+ token = TokenType.KeywordReturn
113
+ break
114
+ case 'in':
115
+ token = TokenType.KeywordOperator
116
+ break
117
+ case 'function':
118
+ token = TokenType.KeywordFunction
119
+ break
120
+ default:
121
+ token = TokenType.Keyword
122
+ break
123
+ }
73
124
  state = State.TopLevelContent
74
125
  } else if ((next = part.match(RE_VARIABLE_NAME))) {
75
126
  token = TokenType.VariableName
@@ -41,6 +41,8 @@ export const TokenType = {
41
41
  NewLine: 891,
42
42
  Heading: 13,
43
43
  MarkdownString: 18,
44
+ MarkdownLinkName: 19,
45
+ MarkdownLinkUrl: 20,
44
46
  }
45
47
 
46
48
  export const TokenMap = {
@@ -58,6 +60,8 @@ export const TokenMap = {
58
60
  [TokenType.PunctuationString]: 'PunctuationString',
59
61
  [TokenType.Heading]: 'Heading',
60
62
  [TokenType.MarkdownString]: 'MarkdownString',
63
+ [TokenType.MarkdownLinkName]: 'MarkdownLinkName',
64
+ [TokenType.MarkdownLinkUrl]: 'MarkdownLinkUrl',
61
65
  }
62
66
 
63
67
  const RE_ANGLE_BRACKET_CLOSE = /^>/
@@ -89,16 +93,47 @@ const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
89
93
  const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^']+/
90
94
  const RE_TAG_TEXT = /^[^\s>]+/
91
95
  const RE_TAGNAME = /^[!\w]+/
92
- const RE_TEXT = /^[^<>\n\`]+/
96
+ const RE_TEXT = /^[^<>\n\`\[\]]+/
93
97
  const RE_WHITESPACE = /^\s+/
94
98
  const RE_WORD = /^[^\s]+/
95
99
  const RE_HEADING = /^\#.*/s
96
100
  const RE_TRIPLE_BACKTICK = /^`{3,}/
97
- const RE_TRIPLE_QUOTED_STRING_CONTENT = /[^`]/s
101
+ const RE_TRIPLE_QUOTED_STRING_CONTENT = /[^`]+/s
98
102
  const RE_STRING_ESCAPE = /^\\./
103
+ const RE_LINK = /^\[([^\[\]\\]+?)\]\((.*)\)/
104
+ const RE_ANYTHING_UNTIL_END = /^.+/s
105
+ const RE_ATTRIBUTE_VALUE_UNQUOTED = /^[^<>\s]+/
106
+
107
+ /**
108
+ *
109
+ * @param {string} attribute
110
+ * @returns {string}
111
+ */
112
+ const getEmbeddedLanguageId = (attribute) => {
113
+ switch (attribute) {
114
+ case 'js':
115
+ return 'javascript'
116
+ case 'shell':
117
+ return 'shellscript'
118
+ case 'md':
119
+ return 'markdown'
120
+ case 'text':
121
+ return 'plaintext'
122
+ default:
123
+ if (attribute.includes(':')) {
124
+ const parts = attribute.split(':')
125
+ const firstPart = parts[0]
126
+ return getEmbeddedLanguageId(firstPart)
127
+ }
128
+ return attribute
129
+ }
130
+ }
99
131
 
100
132
  export const initialLineState = {
101
133
  state: State.TopLevelContent,
134
+ embeddedLanguage: '',
135
+ embeddedLanguageStart: 0,
136
+ embeddedLanguageEnd: 0,
102
137
  }
103
138
 
104
139
  /**
@@ -125,6 +160,9 @@ export const tokenizeLine = (line, lineState) => {
125
160
  let tokens = []
126
161
  let token = TokenType.None
127
162
  let state = lineState.state
163
+ let embeddedLanguage = lineState.embeddedLanguage
164
+ let embeddedLanguageStart = lineState.embeddedLanguageStart
165
+ let embeddedLanguageEnd = lineState.embeddedLanguageEnd
128
166
  while (index < line.length) {
129
167
  const part = line.slice(index)
130
168
  switch (state) {
@@ -152,6 +190,30 @@ export const tokenizeLine = (line, lineState) => {
152
190
  } else if ((next = part.match(RE_ANGLE_BRACKET_OPEN))) {
153
191
  token = TokenType.Text
154
192
  state = State.TopLevelContent
193
+ } else if ((next = part.match(RE_LINK))) {
194
+ const tokenLength = next[0].length
195
+ index += tokenLength
196
+ const linkName = next[1]
197
+ const linkUrl = next[2]
198
+ tokens.push(
199
+ TokenType.Punctuation,
200
+ 1,
201
+ TokenType.MarkdownLinkName,
202
+ linkName.length,
203
+ TokenType.Punctuation,
204
+ 1,
205
+ TokenType.Punctuation,
206
+ 1,
207
+ TokenType.MarkdownLinkUrl,
208
+ linkUrl.length,
209
+ TokenType.Punctuation,
210
+ 1
211
+ )
212
+ tokens.push(token, tokenLength)
213
+ continue
214
+ } else if ((next = part.match(RE_ANYTHING_UNTIL_END))) {
215
+ token = TokenType.Text
216
+ state = State.TopLevelContent
155
217
  } else {
156
218
  part //?
157
219
  console.log({ part })
@@ -273,6 +335,9 @@ export const tokenizeLine = (line, lineState) => {
273
335
  } else if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
274
336
  token = TokenType.PunctuationTag
275
337
  state = State.TopLevelContent
338
+ } else if ((next = part.match(RE_ATTRIBUTE_VALUE_UNQUOTED))) {
339
+ token = TokenType.String
340
+ state = State.InsideOpeningTag
276
341
  } else {
277
342
  throw new Error('no')
278
343
  }
@@ -314,6 +379,8 @@ export const tokenizeLine = (line, lineState) => {
314
379
  if ((next = part.match(RE_WORD))) {
315
380
  token = TokenType.String
316
381
  state = State.AfterTripleBackTickAfterLanguageId
382
+ embeddedLanguage = getEmbeddedLanguageId(next[0])
383
+ embeddedLanguageStart = index + next[0].length
317
384
  } else if ((next = part.match(RE_WHITESPACE))) {
318
385
  token = TokenType.Whitespace
319
386
  state = State.AfterTripleBackTick
@@ -325,10 +392,20 @@ export const tokenizeLine = (line, lineState) => {
325
392
  if ((next = part.match(RE_TRIPLE_BACKTICK))) {
326
393
  token = TokenType.PunctuationString
327
394
  state = State.TopLevelContent
395
+ embeddedLanguage = ''
396
+ embeddedLanguageStart = 0
397
+ embeddedLanguageEnd = 0
328
398
  } else if ((next = part.match(RE_TRIPLE_QUOTED_STRING_CONTENT))) {
329
399
  token = TokenType.String
330
400
  state = State.AfterTripleBackTickAfterLanguageId
401
+ embeddedLanguageStart = Math.min(embeddedLanguageStart, index)
402
+ embeddedLanguageEnd = index + next[0].length
403
+ } else if ((next = part.match(RE_QUOTE_BACKTICK))) {
404
+ token = TokenType.Text
405
+ state = State.AfterTripleBackTickAfterLanguageId
406
+ embeddedLanguageEnd = index + next[0].length
331
407
  } else {
408
+ part
332
409
  throw new Error('no')
333
410
  }
334
411
  break
@@ -357,5 +434,8 @@ export const tokenizeLine = (line, lineState) => {
357
434
  return {
358
435
  state,
359
436
  tokens,
437
+ embeddedLanguage,
438
+ embeddedLanguageStart,
439
+ embeddedLanguageEnd,
360
440
  }
361
441
  }
@@ -0,0 +1,14 @@
1
+ # Language Basics Mdx
2
+
3
+ ## Contributing
4
+
5
+ ```sh
6
+ git clone git@github.com:lvce-editor/language-basics-mdx.git &&
7
+ cd language-basics-mdx &&
8
+ npm ci &&
9
+ npm test
10
+ ```
11
+
12
+ ## Gitpod
13
+
14
+ [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/lvce-editor/language-basics-mdx)
@@ -0,0 +1,12 @@
1
+ {
2
+ "id": "builtin.language-basics-mdx",
3
+ "name": "Language Basics Mdx",
4
+ "description": "Provides syntax highlighting and bracket matching in Mdx files.",
5
+ "languages": [
6
+ {
7
+ "id": "mdx",
8
+ "extensions": [".mdx"],
9
+ "tokenize": "src/tokenizeMdx.js"
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,395 @@
1
+ /**
2
+ * @enum number
3
+ */
4
+ const State = {
5
+ TopLevelContent: 1,
6
+ AfterOpeningAngleBracket: 2,
7
+ InsideOpeningTag: 3,
8
+ InsideOpeningTagAndHasSeenWhitespace: 4,
9
+ AfterClosingTagAngleBrackets: 5,
10
+ AfterClosingTagName: 6,
11
+ AfterAttributeName: 7,
12
+ AfterAttributeEqualSign: 8,
13
+ InsideAttributeDoubleQuote: 9,
14
+ InsideBlockComment: 10,
15
+ None: 11,
16
+ InsideDoubleQuoteString: 12,
17
+ InsideSingleQuoteString: 13,
18
+ AfterTripleBackTick: 14,
19
+ AfterTripleBackTickAfterLanguageId: 15,
20
+ InsideBackTickString: 16,
21
+ }
22
+
23
+ export const StateMap = {}
24
+
25
+ /**
26
+ * @enum number
27
+ */
28
+ export const TokenType = {
29
+ None: 99999999,
30
+ Numeric: 30,
31
+ String: 50,
32
+ Whitespace: 0,
33
+ Comment: 60,
34
+ Text: 117,
35
+ PunctuationTag: 228,
36
+ TagName: 118,
37
+ AttributeName: 119,
38
+ Punctuation: 10,
39
+ Error: 141,
40
+ PunctuationString: 11,
41
+ NewLine: 891,
42
+ Heading: 13,
43
+ MarkdownString: 18,
44
+ MarkdownLinkName: 19,
45
+ MarkdownLinkUrl: 20,
46
+ }
47
+
48
+ export const TokenMap = {
49
+ [TokenType.None]: 'None',
50
+ [TokenType.Numeric]: 'Numeric',
51
+ [TokenType.String]: 'String',
52
+ [TokenType.Whitespace]: 'Whitespace',
53
+ [TokenType.Comment]: 'Comment',
54
+ [TokenType.Text]: 'Text',
55
+ [TokenType.PunctuationTag]: 'PunctuationTag',
56
+ [TokenType.TagName]: 'TagName',
57
+ [TokenType.AttributeName]: 'AttributeName',
58
+ [TokenType.Punctuation]: 'Punctuation',
59
+ [TokenType.Error]: 'Error',
60
+ [TokenType.PunctuationString]: 'PunctuationString',
61
+ [TokenType.Heading]: 'Heading',
62
+ [TokenType.MarkdownString]: 'MarkdownString',
63
+ [TokenType.MarkdownLinkName]: 'MarkdownLinkName',
64
+ [TokenType.MarkdownLinkUrl]: 'MarkdownLinkUrl',
65
+ }
66
+
67
+ const RE_ANGLE_BRACKET_CLOSE = /^>/
68
+ const RE_ANGLE_BRACKET_ONLY = /^</
69
+ const RE_ANGLE_BRACKET_OPEN = /^</
70
+ const RE_ANGLE_BRACKET_OPEN_TAG = /^<(?!\s)/
71
+ const RE_ANY_TEXT = /^[^\n]+/
72
+ const RE_ATTRIBUTE_NAME = /^[a-zA-Z\d\-]+/
73
+ const RE_BLOCK_COMMENT_CONTENT = /^.(?:.*?)(?=-->|$)/s
74
+ const RE_BLOCK_COMMENT_END = /^-->/
75
+ const RE_BLOCK_COMMENT_START = /^<!--/
76
+ const RE_DASH_DASH = /^\-\-/
77
+ const RE_DOUBLE_QUOTE = /^"/
78
+ const RE_EQUAL_SIGN = /^=/
79
+ const RE_EXCLAMATION_MARK = /^!/
80
+ const RE_INVALID_INSIDE_ClOSING_TAG = /^[^a-zA-Z>]/
81
+ const RE_INVALID_INSIDE_OPENING_TAG = /^[^a-zA-Z>]/
82
+ const RE_NEWLINE = /^\n/
83
+ const RE_NEWLINE_WHITESPACE = /^\n\s*/
84
+ const RE_NOT_TAGNAME = /^[^a-zA-Z\d]+/
85
+ const RE_PUNCTUATION = /^[<;'".,]/
86
+ const RE_PUNCTUATION_SELF_CLOSING = /^\/>/
87
+ const RE_SELF_CLOSING = /^\/>/
88
+ const RE_SINGLE_QUOTE = /^'/
89
+ const RE_QUOTE_BACKTICK = /^`/
90
+ const RE_SLASH = /^\//
91
+ const RE_STRING_BACKTICK_QUOTE_CONTENT = /^[^`]+/
92
+ const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
93
+ const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^']+/
94
+ const RE_TAG_TEXT = /^[^\s>]+/
95
+ const RE_TAGNAME = /^[!\w]+/
96
+ const RE_TEXT = /^[^<>\n\`\[\]]+/
97
+ const RE_WHITESPACE = /^\s+/
98
+ const RE_WORD = /^[^\s]+/
99
+ const RE_HEADING = /^\#.*/s
100
+ const RE_TRIPLE_BACKTICK = /^`{3,}/
101
+ const RE_TRIPLE_QUOTED_STRING_CONTENT = /[^`]/s
102
+ const RE_STRING_ESCAPE = /^\\./
103
+ const RE_LINK = /^\[([^\[\]\\]+?)\]\((.*)\)/
104
+ const RE_ANYTHING_UNTIL_END = /^.+/s
105
+
106
+ export const initialLineState = {
107
+ state: State.TopLevelContent,
108
+ }
109
+
110
+ /**
111
+ *
112
+ * @param {any} lineStateA
113
+ * @param {any} lineStateB
114
+ * @returns
115
+ */
116
+ export const isLineStateEqual = (lineStateA, lineStateB) => {
117
+ return lineStateA.state === lineStateB.state
118
+ }
119
+
120
+ export const hasArrayReturn = true
121
+
122
+ /**
123
+ *
124
+ * @param {string} line
125
+ * @param {any} lineState
126
+ * @returns
127
+ */
128
+ export const tokenizeLine = (line, lineState) => {
129
+ let next = null
130
+ let index = 0
131
+ let tokens = []
132
+ let token = TokenType.None
133
+ let state = lineState.state
134
+ while (index < line.length) {
135
+ const part = line.slice(index)
136
+ switch (state) {
137
+ case State.TopLevelContent:
138
+ if ((next = part.match(RE_BLOCK_COMMENT_START))) {
139
+ token = TokenType.Comment
140
+ state = State.InsideBlockComment
141
+ } else if ((next = part.match(RE_ANGLE_BRACKET_OPEN_TAG))) {
142
+ token = TokenType.PunctuationTag
143
+ state = State.AfterOpeningAngleBracket
144
+ } else if ((next = part.match(RE_HEADING))) {
145
+ token = TokenType.Heading
146
+ } else if ((next = part.match(RE_TRIPLE_BACKTICK))) {
147
+ token = TokenType.PunctuationString
148
+ state = State.AfterTripleBackTick
149
+ } else if ((next = part.match(RE_TEXT))) {
150
+ token = TokenType.Text
151
+ state = State.TopLevelContent
152
+ } else if ((next = part.match(RE_QUOTE_BACKTICK))) {
153
+ token = TokenType.Punctuation
154
+ state = State.InsideBackTickString
155
+ } else if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
156
+ token = TokenType.Text
157
+ state = State.TopLevelContent
158
+ } else if ((next = part.match(RE_ANGLE_BRACKET_OPEN))) {
159
+ token = TokenType.Text
160
+ state = State.TopLevelContent
161
+ } else if ((next = part.match(RE_LINK))) {
162
+ const tokenLength = next[0].length
163
+ index += tokenLength
164
+ const linkName = next[1]
165
+ const linkUrl = next[2]
166
+ tokens.push(
167
+ TokenType.Punctuation,
168
+ 1,
169
+ TokenType.MarkdownLinkName,
170
+ linkName.length,
171
+ TokenType.Punctuation,
172
+ 1,
173
+ TokenType.Punctuation,
174
+ 1,
175
+ TokenType.MarkdownLinkUrl,
176
+ linkUrl.length,
177
+ TokenType.Punctuation,
178
+ 1
179
+ )
180
+ tokens.push(token, tokenLength)
181
+ continue
182
+ } else if ((next = part.match(RE_ANYTHING_UNTIL_END))) {
183
+ token = TokenType.Text
184
+ state = State.TopLevelContent
185
+ } else {
186
+ part //?
187
+ console.log({ part })
188
+ throw new Error('no')
189
+ }
190
+ break
191
+ case State.AfterOpeningAngleBracket:
192
+ if ((next = part.match(RE_TAGNAME))) {
193
+ token = TokenType.TagName
194
+ state = State.InsideOpeningTag
195
+ } else if ((next = part.match(RE_SLASH))) {
196
+ token = TokenType.PunctuationTag
197
+ state = State.AfterClosingTagAngleBrackets
198
+ } else if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
199
+ token = TokenType.PunctuationTag
200
+ state = State.TopLevelContent
201
+ } else if ((next = part.match(RE_ANY_TEXT))) {
202
+ token = TokenType.Text
203
+ state = State.TopLevelContent
204
+ } else {
205
+ part //?
206
+ throw new Error('no')
207
+ }
208
+ break
209
+ case State.InsideOpeningTag:
210
+ if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
211
+ token = TokenType.PunctuationTag
212
+ state = State.TopLevelContent
213
+ } else if ((next = part.match(RE_EXCLAMATION_MARK))) {
214
+ token = TokenType.PunctuationTag
215
+ state = State.InsideOpeningTag
216
+ } else if ((next = part.match(RE_WHITESPACE))) {
217
+ token = TokenType.Whitespace
218
+ state = State.InsideOpeningTagAndHasSeenWhitespace
219
+ } else if ((next = part.match(RE_DASH_DASH))) {
220
+ token = TokenType.Comment
221
+ state = State.InsideBlockComment
222
+ } else if ((next = part.match(RE_TAG_TEXT))) {
223
+ token = TokenType.Text
224
+ state = State.InsideOpeningTag
225
+ } else {
226
+ part //?
227
+ throw new Error('no')
228
+ }
229
+ break
230
+ case State.AfterClosingTagAngleBrackets:
231
+ if ((next = part.match(RE_TAGNAME))) {
232
+ token = TokenType.TagName
233
+ state = State.AfterClosingTagName
234
+ } else if ((next = part.match(RE_ANY_TEXT))) {
235
+ token = TokenType.Text
236
+ state = State.TopLevelContent
237
+ } else {
238
+ part //?
239
+ throw new Error('no')
240
+ }
241
+ break
242
+ case State.AfterClosingTagName:
243
+ if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
244
+ token = TokenType.PunctuationTag
245
+ state = State.TopLevelContent
246
+ } else if ((next = part.match(RE_TEXT))) {
247
+ token = TokenType.Text
248
+ state = State.TopLevelContent
249
+ } else {
250
+ throw new Error('no')
251
+ }
252
+ break
253
+ case State.InsideOpeningTagAndHasSeenWhitespace:
254
+ if ((next = part.match(RE_ATTRIBUTE_NAME))) {
255
+ token = TokenType.AttributeName
256
+ state = State.AfterAttributeName
257
+ } else if ((next = part.match(RE_SELF_CLOSING))) {
258
+ token = TokenType.PunctuationTag
259
+ state = State.TopLevelContent
260
+ } else if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
261
+ token = TokenType.PunctuationTag
262
+ state = State.TopLevelContent
263
+ } else if ((next = part.match(RE_TAG_TEXT))) {
264
+ token = TokenType.Text
265
+ state = State.TopLevelContent
266
+ } else {
267
+ part //?
268
+ throw new Error('no')
269
+ }
270
+ break
271
+ case State.AfterAttributeName:
272
+ if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
273
+ token = TokenType.PunctuationTag
274
+ state = State.TopLevelContent
275
+ } else if ((next = part.match(RE_EQUAL_SIGN))) {
276
+ token = TokenType.Punctuation
277
+ state = State.AfterAttributeEqualSign
278
+ } else if ((next = part.match(RE_DOUBLE_QUOTE))) {
279
+ token = TokenType.PunctuationString
280
+ state = State.InsideDoubleQuoteString
281
+ } else if ((next = part.match(RE_SINGLE_QUOTE))) {
282
+ token = TokenType.PunctuationString
283
+ state = State.InsideSingleQuoteString
284
+ } else if ((next = part.match(RE_TAG_TEXT))) {
285
+ token = TokenType.Text
286
+ state = State.InsideOpeningTag
287
+ } else if ((next = part.match(RE_WHITESPACE))) {
288
+ token = TokenType.Whitespace
289
+ state = State.InsideOpeningTagAndHasSeenWhitespace
290
+ } else {
291
+ // TODO check quotation mark
292
+ part //?
293
+ throw new Error('no')
294
+ }
295
+ break
296
+ case State.AfterAttributeEqualSign:
297
+ if ((next = part.match(RE_DOUBLE_QUOTE))) {
298
+ token = TokenType.PunctuationString
299
+ state = State.InsideDoubleQuoteString
300
+ } else if ((next = part.match(RE_SINGLE_QUOTE))) {
301
+ token = TokenType.PunctuationString
302
+ state = State.InsideSingleQuoteString
303
+ } else if ((next = part.match(RE_ANGLE_BRACKET_CLOSE))) {
304
+ token = TokenType.PunctuationTag
305
+ state = State.TopLevelContent
306
+ } else {
307
+ throw new Error('no')
308
+ }
309
+ break
310
+ case State.InsideDoubleQuoteString:
311
+ if ((next = part.match(RE_DOUBLE_QUOTE))) {
312
+ token = TokenType.PunctuationString
313
+ state = State.InsideOpeningTag
314
+ } else if ((next = part.match(RE_STRING_DOUBLE_QUOTE_CONTENT))) {
315
+ token = TokenType.String
316
+ state = State.InsideDoubleQuoteString
317
+ } else {
318
+ throw new Error('no')
319
+ }
320
+ break
321
+ case State.InsideSingleQuoteString:
322
+ if ((next = part.match(RE_SINGLE_QUOTE))) {
323
+ token = TokenType.PunctuationString
324
+ state = State.InsideOpeningTag
325
+ } else if ((next = part.match(RE_STRING_SINGLE_QUOTE_CONTENT))) {
326
+ token = TokenType.String
327
+ state = State.InsideSingleQuoteString
328
+ } else {
329
+ throw new Error('no')
330
+ }
331
+ break
332
+ case State.InsideBlockComment:
333
+ if ((next = part.match(RE_BLOCK_COMMENT_END))) {
334
+ token = TokenType.Comment
335
+ state = State.TopLevelContent
336
+ } else if ((next = part.match(RE_BLOCK_COMMENT_CONTENT))) {
337
+ token = TokenType.Comment
338
+ state = State.InsideBlockComment
339
+ } else {
340
+ throw new Error('no')
341
+ }
342
+ break
343
+ case State.AfterTripleBackTick:
344
+ if ((next = part.match(RE_WORD))) {
345
+ token = TokenType.String
346
+ state = State.AfterTripleBackTickAfterLanguageId
347
+ } else if ((next = part.match(RE_WHITESPACE))) {
348
+ token = TokenType.Whitespace
349
+ state = State.AfterTripleBackTick
350
+ } else {
351
+ throw new Error('no')
352
+ }
353
+ break
354
+ case State.AfterTripleBackTickAfterLanguageId:
355
+ if ((next = part.match(RE_TRIPLE_BACKTICK))) {
356
+ token = TokenType.PunctuationString
357
+ state = State.TopLevelContent
358
+ } else if ((next = part.match(RE_TRIPLE_QUOTED_STRING_CONTENT))) {
359
+ token = TokenType.String
360
+ state = State.AfterTripleBackTickAfterLanguageId
361
+ } else if ((next = part.match(RE_QUOTE_BACKTICK))) {
362
+ token = TokenType.Text
363
+ state = State.AfterTripleBackTickAfterLanguageId
364
+ } else {
365
+ part
366
+ throw new Error('no')
367
+ }
368
+ break
369
+ case State.InsideBackTickString:
370
+ if ((next = part.match(RE_QUOTE_BACKTICK))) {
371
+ token = TokenType.Punctuation
372
+ state = State.TopLevelContent
373
+ } else if ((next = part.match(RE_STRING_BACKTICK_QUOTE_CONTENT))) {
374
+ token = TokenType.MarkdownString
375
+ state = State.InsideBackTickString
376
+ } else if ((next = part.match(RE_STRING_ESCAPE))) {
377
+ token = TokenType.String
378
+ state = State.InsideBackTickString
379
+ } else {
380
+ throw new Error('no')
381
+ }
382
+ break
383
+ default:
384
+ state
385
+ throw new Error('no')
386
+ }
387
+ const tokenLength = next[0].length
388
+ index += tokenLength
389
+ tokens.push(token, tokenLength)
390
+ }
391
+ return {
392
+ state,
393
+ tokens,
394
+ }
395
+ }