@lvce-editor/shared-process 0.11.6 → 0.11.7

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.
@@ -326,7 +326,7 @@
326
326
  "label": "File: Open Recent"
327
327
  },
328
328
  {
329
- "id": "Dialog.showAbout",
329
+ "id": "About.showAbout",
330
330
  "label": "Help: About"
331
331
  },
332
332
  {
@@ -149,7 +149,7 @@
149
149
  },
150
150
  {
151
151
  "key": "ctrl+Enter",
152
- "command": "SourceControl.acceptInput",
152
+ "command": "Source Control.acceptInput",
153
153
  "when": "focus.sourceControlInput"
154
154
  },
155
155
  {
@@ -4,6 +4,9 @@
4
4
  export const State = {
5
5
  TopLevelContent: 1,
6
6
  InsideLineComment: 2,
7
+ AfterPropertyName: 3,
8
+ AfterPropertyNameAfterEqualSign: 4,
9
+ InsideString: 5,
7
10
  }
8
11
 
9
12
  export const StateMap = {
@@ -23,6 +26,10 @@ export const TokenType = {
23
26
  Comment: 885,
24
27
  Query: 886,
25
28
  Text: 887,
29
+ PropertyName: 12,
30
+ PropertyValueString: 14,
31
+ Punctuation: 13,
32
+ LanguageConstant: 11,
26
33
  }
27
34
 
28
35
  export const TokenMap = {
@@ -34,13 +41,19 @@ export const TokenMap = {
34
41
  [TokenType.Comment]: 'Comment',
35
42
  [TokenType.Query]: 'Query',
36
43
  [TokenType.Text]: 'Text',
44
+ [TokenType.Punctuation]: 'Punctuation',
45
+ [TokenType.LanguageConstant]: 'LanguageConstant',
46
+ [TokenType.PropertyName]: 'JsonPropertyName',
47
+ [TokenType.LanguageConstant]: 'LanguageConstant',
48
+ [TokenType.Punctuation]: 'Punctuation',
49
+ [TokenType.PropertyValueString]: 'YamlPropertyValueString',
37
50
  }
38
51
 
39
52
  const RE_LINE_COMMENT_START = /^#/
40
53
  const RE_WHITESPACE = /^ +/
41
54
  const RE_CURLY_OPEN = /^\{/
42
55
  const RE_CURLY_CLOSE = /^\}/
43
- const RE_PROPERTY_NAME = /^[a-zA-Z\-]+\b/
56
+ const RE_PROPERTY_NAME = /^[a-zA-Z\-\_\d]+\b(?=\s*=)/
44
57
  const RE_COLON = /^:/
45
58
  const RE_PROPERTY_VALUE = /^[^;\}]+/
46
59
  const RE_SEMICOLON = /^;/
@@ -62,6 +75,11 @@ const RE_STAR = /^\*/
62
75
  const RE_QUERY_NAME = /^[a-z\-]+/
63
76
  const RE_QUERY_CONTENT = /^[^\)]+/
64
77
  const RE_COMBINATOR = /^[\+\>\~]/
78
+ const RE_EQUAL_SIGN = /^=/
79
+ const RE_QUOTE_DOUBLE = /^"/
80
+ const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
81
+ const RE_LINE_COMMENT = /^#.*/s
82
+ const RE_LANGUAGE_CONSTANT = /^(?:true|false)\b/
65
83
 
66
84
  export const initialLineState = {
67
85
  state: State.TopLevelContent,
@@ -85,9 +103,12 @@ export const tokenizeLine = (line, lineState) => {
85
103
  const part = line.slice(index)
86
104
  switch (state) {
87
105
  case State.TopLevelContent:
88
- if ((next = part.match(RE_LINE_COMMENT_START))) {
106
+ if ((next = part.match(RE_PROPERTY_NAME))) {
107
+ token = TokenType.PropertyName
108
+ state = State.AfterPropertyName
109
+ } else if ((next = part.match(RE_LINE_COMMENT))) {
89
110
  token = TokenType.Comment
90
- state = State.InsideLineComment
111
+ state = State.TopLevelContent
91
112
  } else if ((next = part.match(RE_WHITESPACE))) {
92
113
  token = TokenType.Whitespace
93
114
  state = State.TopLevelContent
@@ -99,10 +120,33 @@ export const tokenizeLine = (line, lineState) => {
99
120
  throw new Error('no')
100
121
  }
101
122
  break
102
- case State.InsideLineComment:
103
- if ((next = part.match(RE_ANYTHING))) {
123
+ case State.AfterPropertyName:
124
+ if ((next = part.match(RE_EQUAL_SIGN))) {
125
+ token = TokenType.Punctuation
126
+ state = State.AfterPropertyNameAfterEqualSign
127
+ } else if ((next = part.match(RE_WHITESPACE))) {
128
+ token = TokenType.Whitespace
129
+ state = State.AfterPropertyName
130
+ } else {
131
+ throw new Error('no')
132
+ }
133
+ break
134
+ case State.AfterPropertyNameAfterEqualSign:
135
+ if ((next = part.match(RE_WHITESPACE))) {
136
+ token = TokenType.Whitespace
137
+ state = State.AfterPropertyNameAfterEqualSign
138
+ } else if ((next = part.match(RE_LANGUAGE_CONSTANT))) {
139
+ token = TokenType.LanguageConstant
140
+ state = State.TopLevelContent
141
+ } else if ((next = part.match(RE_LINE_COMMENT))) {
104
142
  token = TokenType.Comment
105
143
  state = State.TopLevelContent
144
+ } else if ((next = part.match(RE_QUOTE_DOUBLE))) {
145
+ token = TokenType.Punctuation
146
+ state = State.InsideString
147
+ } else if ((next = part.match(RE_ANYTHING))) {
148
+ token = TokenType.PropertyValueString
149
+ state = State.TopLevelContent
106
150
  } else {
107
151
  throw new Error('no')
108
152
  }
@@ -37,6 +37,7 @@
37
37
  "fileNames": [
38
38
  "APKBUILD",
39
39
  "PKGBUILD",
40
+ ".INSTALL",
40
41
  ".envrc",
41
42
  ".hushlogin",
42
43
  "zshrc",
@@ -79,7 +79,7 @@ const RE_SLASH = /^\//
79
79
  const RE_STRING_DOUBLE_QUOTE_CONTENT = /^[^"]+/
80
80
  const RE_STRING_SINGLE_QUOTE_CONTENT = /^[^']+/
81
81
  const RE_TAG_TEXT = /^[^\s>]+/
82
- const RE_TAGNAME = /^[!\w]+/
82
+ const RE_TAGNAME = /^[!\w\-]+/
83
83
  const RE_TEXT = /^[^<>\n]+/
84
84
  const RE_WHITESPACE = /^\s+/
85
85
  const RE_WORD = /^[^\s]+/
package/index.js CHANGED
@@ -5,12 +5,15 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
5
5
 
6
6
  export const sharedProcessPath = join(__dirname, 'src', 'sharedProcessMain.js')
7
7
 
8
- export const exportStatic = async ({ extensionPath = process.cwd() } = {}) => {
8
+ export const exportStatic = async ({
9
+ extensionPath = process.cwd(),
10
+ testPath = '',
11
+ } = {}) => {
9
12
  const fn = await import('./src/parts/ExportStatic/ExportStatic.js')
10
13
  const root = process.cwd()
11
14
  if (extensionPath !== root) {
12
15
  extensionPath = join(root, extensionPath)
13
16
  }
14
17
  const pathPrefix = process.env.PATH_PREFIX || ''
15
- await fn.exportStatic({ root, pathPrefix, extensionPath })
18
+ await fn.exportStatic({ root, pathPrefix, extensionPath, testPath })
16
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.11.6",
3
+ "version": "0.11.7",
4
4
  "description": "Utility package for @lvce-editor/server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -17,12 +17,12 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@babel/code-frame": "^7.18.6",
20
- "@lvce-editor/extension-host": "0.11.6",
21
- "@lvce-editor/extension-host-helper-process": "0.11.6",
22
- "@lvce-editor/pty-host": "0.11.6",
20
+ "@lvce-editor/extension-host": "0.11.7",
21
+ "@lvce-editor/extension-host-helper-process": "0.11.7",
22
+ "@lvce-editor/pty-host": "0.11.7",
23
23
  "debug": "^4.3.4",
24
24
  "execa": "^6.1.0",
25
- "exit-hook": "^3.1.2",
25
+ "exit-hook": "^3.1.4",
26
26
  "got": "^12.5.3",
27
27
  "is-object": "^1.0.2",
28
28
  "lines-and-columns": "^2.0.3",
@@ -637,11 +637,76 @@ const addExtension = async ({
637
637
  })
638
638
  }
639
639
 
640
+ const generateTestOverviewHtml = (dirents) => {
641
+ const pre = `<!DOCTYPE html>
642
+ <html lang="en">
643
+ <head>
644
+ <meta charset="UTF-8" />
645
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
646
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
647
+ <title>Tests</title>
648
+ </head>
649
+ <body>
650
+ <h1>Tests</h1>
651
+ <p>Available Tests</p>
652
+ <ul>
653
+ `
654
+ let middle = ``
655
+ // TODO properly escape name
656
+ for (const dirent of dirents) {
657
+ const name = dirent
658
+ middle += ` <li><a href="./${name}.html">${name}</a></li>
659
+ `
660
+ }
661
+
662
+ const post = ` </ul>
663
+ </body>
664
+ </html>
665
+ `
666
+ return pre + middle + post
667
+ }
668
+
669
+ const getName = (name) => {
670
+ return name.slice(0, -'.js'.length)
671
+ }
672
+ const isTestFile = (file) => {
673
+ return file !== '_all.js'
674
+ }
675
+
676
+ const getTestFiles = (testFilesRaw) => {
677
+ return testFilesRaw.map(getName).filter(isTestFile)
678
+ }
679
+
680
+ const addTestFiles = async ({ testPath, commitHash, root, pathPrefix }) => {
681
+ await FileSystem.copy(
682
+ `${root}/${testPath}/src`,
683
+ `${root}/dist/${commitHash}/packages/extension-host-worker-tests/src`
684
+ )
685
+ const testFilesRaw = await FileSystem.readDir(`${root}/${testPath}/src`)
686
+ const testFiles = getTestFiles(testFilesRaw)
687
+ await FileSystem.mkdir(`${root}/dist/${commitHash}/tests`)
688
+ await FileSystem.mkdir(`${root}/dist/tests`)
689
+ console.log({ testFiles })
690
+ for (const testFile of testFiles) {
691
+ await FileSystem.copyFile(
692
+ `${root}/dist/index.html`,
693
+ `${root}/dist/tests/${testFile}.html`
694
+ )
695
+ }
696
+ const testOverviewHtml = generateTestOverviewHtml(testFiles)
697
+ await FileSystem.writeFile(`${root}/dist/tests/index.html`, testOverviewHtml)
698
+ }
699
+
640
700
  /**
641
701
  *
642
- * @param {{root:string, pathPrefix:string , extensionPath:string }} param0
702
+ * @param {{root:string, pathPrefix:string , extensionPath:string, testPath:string }} param0
643
703
  */
644
- export const exportStatic = async ({ root, pathPrefix, extensionPath }) => {
704
+ export const exportStatic = async ({
705
+ root,
706
+ pathPrefix,
707
+ extensionPath,
708
+ testPath,
709
+ }) => {
645
710
  if (pathPrefix === 'auto') {
646
711
  const extensionJson = await readExtensionManifest(
647
712
  Path.join(extensionPath, 'extension.json')
@@ -679,4 +744,15 @@ export const exportStatic = async ({ root, pathPrefix, extensionPath }) => {
679
744
  root,
680
745
  })
681
746
  console.timeEnd('addExtension')
747
+
748
+ if (testPath) {
749
+ console.time('addTestFiles')
750
+ await addTestFiles({
751
+ testPath,
752
+ commitHash,
753
+ pathPrefix,
754
+ root,
755
+ })
756
+ console.timeEnd('addTestFiles')
757
+ }
682
758
  }
@@ -1,11 +1,11 @@
1
- import VError from 'verror'
1
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
2
2
  import * as ExtensionManifest from '../ExtensionManifest/ExtensionManifest.js'
3
3
  import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
4
4
  import * as FileSystem from '../FileSystem/FileSystem.js'
5
- import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
6
5
  import * as Path from '../Path/Path.js'
7
6
  import * as Platform from '../Platform/Platform.js'
8
7
  import * as SymLink from '../SymLink/SymLink.js'
8
+ import { VError } from '../VError/VError.js'
9
9
 
10
10
  const linkFallBack = async (path) => {
11
11
  try {
@@ -19,7 +19,6 @@ const linkFallBack = async (path) => {
19
19
  await FileSystem.remove(to)
20
20
  await SymLink.createSymLink(path, to)
21
21
  } catch (error) {
22
- console.log({ error })
23
22
  throw new VError(error, `Failed to link extension`)
24
23
  }
25
24
  }
@@ -1,5 +1,5 @@
1
1
  import { mkdir, rename, rm } from 'node:fs/promises'
2
- import VError from 'verror'
2
+ import { VError } from '../VError/VError.js'
3
3
  import * as Debug from '../Debug/Debug.js'
4
4
  import * as ExtensionManifestInputType from '../ExtensionManifestInputType/ExtensionManifestInputType.js'
5
5
  import * as ExtensionManifests from '../ExtensionManifests/ExtensionManifests.js'
@@ -1,9 +1,9 @@
1
1
  import isObject from 'is-object'
2
- import VError from 'verror'
2
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
3
3
  import * as ExtensionManifestStatus from '../ExtensionManifestStatus/ExtensionManifestStatus.js'
4
4
  import * as ReadJson from '../JsonFile/JsonFile.js'
5
5
  import * as Path from '../Path/Path.js'
6
- import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
6
+ import { VError } from '../VError/VError.js'
7
7
 
8
8
  const RE_EXTENSION_FRAGMENT = /.+(\/|\\)(.+)$/
9
9
 
@@ -2,16 +2,30 @@ import { spawn } from 'node:child_process'
2
2
  import * as Platform from '../Platform/Platform.js'
3
3
  import * as RgPath from '../RgPath/RgPath.js'
4
4
  import * as RipGrepParsedLineType from '../RipGrepParsedLineType/RipGrepParsedLineType.js'
5
- import * as SplitLines from '../SplitLines/SplitLines.js'
5
+ import * as TextSearchResultType from '../TextSearchResultType/TextSearchResultType.js'
6
6
 
7
7
  const MAX_SEARCH_RESULTS = 300
8
8
 
9
+ const BEFORE = 20
10
+ const AFTER = 20
11
+
9
12
  const toSearchResult = (parsedLine) => {
10
- return {
11
- preview: parsedLine.data.lines.text,
12
- absoluteOffset: parsedLine.data.absolute_offset,
13
- lineNumber: parsedLine.data.line_number - 1,
13
+ const results = []
14
+ const lines = parsedLine.data.lines.text
15
+ const lineNumber = parsedLine.data.line_number
16
+ for (const submatch of parsedLine.data.submatches) {
17
+ const previewStart = Math.max(submatch.start - BEFORE, 0)
18
+ const previewEnd = Math.min(submatch.end + AFTER, lines.length)
19
+ const previewText = lines.slice(previewStart, previewEnd)
20
+ results.push({
21
+ type: TextSearchResultType.Match,
22
+ start: submatch.start - previewStart,
23
+ end: submatch.end - previewStart,
24
+ lineNumber,
25
+ text: previewText,
26
+ })
14
27
  }
28
+ return results
15
29
  }
16
30
 
17
31
  // TODO update vscode-ripgrep when https://github.com/mhinz/vim-grepper/issues/244, https://github.com/BurntSushi/ripgrep/issues/1892 is fixed
@@ -52,32 +66,53 @@ export const search = async (searchDir, searchString) => {
52
66
  let numberOfResults = 0
53
67
  // TODO use pipeline / transform stream maybe
54
68
 
69
+ const handleLine = (line) => {
70
+ const parsedLine = JSON.parse(line)
71
+ switch (parsedLine.type) {
72
+ case RipGrepParsedLineType.Begin:
73
+ allSearchResults[parsedLine.data.path.text] = [
74
+ {
75
+ type: TextSearchResultType.File,
76
+ start: 0,
77
+ end: 0,
78
+ lineNumber: 0,
79
+ text: parsedLine.data.path.text,
80
+ },
81
+ ]
82
+ break
83
+ case RipGrepParsedLineType.Match:
84
+ numberOfResults++
85
+ allSearchResults[parsedLine.data.path.text].push(
86
+ ...toSearchResult(parsedLine)
87
+ )
88
+ break
89
+ case RipGrepParsedLineType.Summary:
90
+ stats = parsedLine.data
91
+ break
92
+ default:
93
+ break
94
+ }
95
+ }
96
+
97
+ let total = 0
55
98
  const handleData = (chunk) => {
56
- buffer += chunk
57
- const lines = SplitLines.splitLines(buffer)
58
- // @ts-ignore
59
- buffer = lines.pop()
60
- for (const line of lines) {
61
- const parsedLine = JSON.parse(line)
62
- console.log(parsedLine)
63
- switch (parsedLine.type) {
64
- case RipGrepParsedLineType.Begin: {
65
- allSearchResults[parsedLine.data.path.text] = []
66
- break
67
- }
68
- case RipGrepParsedLineType.Match:
69
- numberOfResults++
70
- allSearchResults[parsedLine.data.path.text].push(
71
- toSearchResult(parsedLine)
72
- )
73
- break
74
- case RipGrepParsedLineType.Summary:
75
- stats = parsedLine.data
76
- break
77
- default:
78
- break
79
- }
99
+ let newLineIndex = chunk.indexOf('\n')
100
+ const dataString = buffer + chunk
101
+ if (newLineIndex === -1) {
102
+ buffer = dataString
103
+ return
104
+ }
105
+ total += chunk.length
106
+ newLineIndex += buffer.length
107
+ let previousIndex = 0
108
+ while (newLineIndex >= 0) {
109
+ const line = dataString.slice(previousIndex, newLineIndex)
110
+ handleLine(line)
111
+ previousIndex = newLineIndex + 1
112
+ newLineIndex = dataString.indexOf('\n', previousIndex)
80
113
  }
114
+ buffer = dataString.slice(previousIndex)
115
+
81
116
  if (numberOfResults > MAX_SEARCH_RESULTS) {
82
117
  limitHit = true
83
118
  childProcess.kill()
@@ -85,8 +120,9 @@ export const search = async (searchDir, searchString) => {
85
120
  }
86
121
 
87
122
  const handleClose = () => {
123
+ const results = Object.values(allSearchResults).flat(1)
88
124
  resolve({
89
- results: Object.entries(allSearchResults),
125
+ results,
90
126
  stats,
91
127
  limitHit,
92
128
  })
@@ -100,6 +136,7 @@ export const search = async (searchDir, searchString) => {
100
136
  limitHit,
101
137
  })
102
138
  }
139
+ childProcess.stdout.setEncoding('utf8')
103
140
  childProcess.stdout.on('data', handleData)
104
141
  childProcess.once('close', handleClose)
105
142
  childProcess.once('error', handleError)
@@ -0,0 +1,2 @@
1
+ export const File = 1
2
+ export const Match = 2
@@ -0,0 +1,44 @@
1
+ const getCombinedMessage = (error, message) => {
2
+ let stringifiedError = `${error}`
3
+ if (stringifiedError.startsWith('Error: ')) {
4
+ stringifiedError = stringifiedError.slice(`Error: `.length)
5
+ } else if (stringifiedError.startsWith('VError: ')) {
6
+ stringifiedError = stringifiedError.slice(`VError: `.length)
7
+ }
8
+ if (message) {
9
+ return `${message}: ${stringifiedError}`
10
+ }
11
+ return stringifiedError
12
+ }
13
+
14
+ const mergeStacks = (parent, child) => {
15
+ if (!child) {
16
+ return parent
17
+ }
18
+ const parentNewLineIndex = parent.indexOf('\n')
19
+ const childNewLineIndex = child.indexOf('\n')
20
+ const parentFirstLine = parent.slice(0, parentNewLineIndex)
21
+ const childRest = child.slice(childNewLineIndex)
22
+ const childFirstLine = child.slice(0, childNewLineIndex)
23
+ if (parentFirstLine.includes(childFirstLine)) {
24
+ return parentFirstLine + childRest
25
+ }
26
+ return child
27
+ }
28
+
29
+ export class VError extends Error {
30
+ constructor(error, message) {
31
+ const combinedMessage = getCombinedMessage(error, message)
32
+ super(combinedMessage)
33
+ this.name = 'VError'
34
+ if (error instanceof Error) {
35
+ this.stack = mergeStacks(this.stack, error.stack)
36
+ }
37
+ if (error.codeFrame) {
38
+ this.codeFrame = error.codeFrame
39
+ }
40
+ if (error.code) {
41
+ this.code = error.code
42
+ }
43
+ }
44
+ }