@ptengine/inline-editor 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/panels/CodeMirrorField.d.ts +6 -1
- package/dist/panels/CodeMirrorField.js +111 -23
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.12
|
|
4
|
+
|
|
5
|
+
依赖不变,可以直接发。
|
|
6
|
+
|
|
7
|
+
**变更**
|
|
8
|
+
|
|
9
|
+
- 代码框 JS 补全补齐到老编辑器的口径:还没敲到 `ptKit.`、敲标识符(如 `pt`)时就列出 `ptKit.query(...)` 等整句片段,
|
|
10
|
+
选中插入完整模板(此前只有敲完 `ptKit.` 才有成员补全,用户敲 `pt` 看不到任何提示)。按常用程度排序,`query` 在前。
|
|
11
|
+
- 新增常用浏览器全局对象的补全(`document` / `window` / `console` / `setTimeout` / `localStorage` / `MutationObserver` …)
|
|
12
|
+
及其成员(`document.querySelector` 等);用白名单作用域,不把编辑器所在页面的全局与 Object.prototype 成员补出来。
|
|
13
|
+
- 字符串、注释里与别的对象的成员访问(`foo.pt`)不出 ptKit 整句补全。
|
|
14
|
+
|
|
3
15
|
## 0.1.11
|
|
4
16
|
|
|
5
17
|
依赖不变,可以直接发。
|
|
@@ -21,8 +21,13 @@ export interface CodeMirrorFieldProps {
|
|
|
21
21
|
ariaLabel?: string;
|
|
22
22
|
'data-testid'?: string;
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
24
|
+
/** 敲 `ptKit.` 之后:成员补全。 */
|
|
25
25
|
export declare const PT_KIT_COMPLETIONS: import("@codemirror/autocomplete").Completion[];
|
|
26
|
+
/**
|
|
27
|
+
* 敲标识符时(如 `pt`):整句补全 `ptKit.query(...)` 等 —— 老编辑器(`ptKitConfig.js`)就是这样提示的,
|
|
28
|
+
* 用户不知道有 `ptKit` 时也能从这里发现它。`boost` 让它们排在关键字片段前面。
|
|
29
|
+
*/
|
|
30
|
+
export declare const PT_KIT_IDENT_COMPLETIONS: import("@codemirror/autocomplete").Completion[];
|
|
26
31
|
export declare function ptKitCompletion(context: CompletionContext): CompletionResult | null;
|
|
27
32
|
/**
|
|
28
33
|
* 语法错误提示:解析树里的出错节点(Lezer 遇到写不下去的地方会插一个 error 节点)。
|
|
@@ -7,44 +7,131 @@ import { bracketMatching, defaultHighlightStyle, foldGutter, indentOnInput, ensu
|
|
|
7
7
|
import { autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap, snippetCompletion } from '@codemirror/autocomplete';
|
|
8
8
|
import { lintGutter, linter } from '@codemirror/lint';
|
|
9
9
|
import { css } from '@codemirror/lang-css';
|
|
10
|
-
import { javascript, javascriptLanguage } from '@codemirror/lang-javascript';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import { javascript, javascriptLanguage, scopeCompletionSource } from '@codemirror/lang-javascript';
|
|
11
|
+
const PT_KIT_DEFS = [
|
|
12
|
+
{
|
|
13
|
+
name: 'query',
|
|
14
|
+
template: "query('${selector}').then(function (el) {\n\t${}\n});",
|
|
14
15
|
detail: '(selector, options?) → Promise<Element>',
|
|
15
16
|
info: '轮询等待元素出现(默认最长 60 秒、每 500ms 查一次),找到后 resolve。'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'queryAll',
|
|
20
|
+
template: "queryAll('${selector}').then(function (list) {\n\t${}\n});",
|
|
19
21
|
detail: '(selector, options?) → Promise<Element[]>',
|
|
20
22
|
info: '轮询等待至少一个匹配元素出现,resolve 全部匹配元素。'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'querySelector',
|
|
26
|
+
template: "querySelector('${selector}')",
|
|
24
27
|
detail: '(selector, context?) → Element | null',
|
|
25
28
|
info: '立即查找一个元素(含 Ptengine 弹窗的 Shadow DOM)。'
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'querySelectorAll',
|
|
32
|
+
template: "querySelectorAll('${selector}')",
|
|
29
33
|
detail: '(selector, context?) → Element[]',
|
|
30
34
|
info: '立即查找全部匹配元素(含 Ptengine 弹窗的 Shadow DOM)。'
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'observe',
|
|
38
|
+
template: "observe('${selector}', function (el) {\n\t${}\n});",
|
|
34
39
|
detail: '(selector, callback, options?)',
|
|
35
40
|
info: '元素已在或之后被插入页面时执行回调(MutationObserver)。'
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'moveElement',
|
|
44
|
+
template: "moveElement('${target}', '${relative}', '${after}');",
|
|
39
45
|
detail: "(target, relative, 'before' | 'after', options?)",
|
|
40
46
|
info: '等两个元素都出现后,把 target 移到 relative 的前面或后面。'
|
|
41
|
-
}
|
|
47
|
+
}
|
|
42
48
|
];
|
|
49
|
+
export const PT_KIT_COMPLETIONS = PT_KIT_DEFS.map((d, i) => snippetCompletion(d.template, {
|
|
50
|
+
label: d.name,
|
|
51
|
+
detail: d.detail,
|
|
52
|
+
info: d.info,
|
|
53
|
+
boost: 6 - i,
|
|
54
|
+
type: 'function'
|
|
55
|
+
}));
|
|
56
|
+
export const PT_KIT_IDENT_COMPLETIONS = PT_KIT_DEFS.map((d, i) => snippetCompletion(`ptKit.${d.template}`, {
|
|
57
|
+
label: `ptKit.${d.name}`,
|
|
58
|
+
detail: d.detail,
|
|
59
|
+
info: d.info,
|
|
60
|
+
type: 'function',
|
|
61
|
+
boost: 20 - i
|
|
62
|
+
}));
|
|
63
|
+
function inStringOrComment(context) {
|
|
64
|
+
const tree = ensureSyntaxTree(context.state, context.pos, 20) ?? syntaxTree(context.state);
|
|
65
|
+
const node = tree.resolveInner(context.pos, -1);
|
|
66
|
+
return /String|Comment|TemplateString/.test(node.type.name);
|
|
67
|
+
}
|
|
43
68
|
export function ptKitCompletion(context) {
|
|
44
|
-
|
|
45
|
-
if (!before)
|
|
69
|
+
if (inStringOrComment(context))
|
|
46
70
|
return null;
|
|
47
|
-
|
|
71
|
+
const member = context.matchBefore(/ptKit\.\w*/);
|
|
72
|
+
if (member)
|
|
73
|
+
return {
|
|
74
|
+
from: member.from + 'ptKit.'.length,
|
|
75
|
+
options: PT_KIT_COMPLETIONS,
|
|
76
|
+
validFor: /^\w*$/
|
|
77
|
+
};
|
|
78
|
+
const word = context.matchBefore(/[\w$]+/);
|
|
79
|
+
const from = word ? word.from : context.pos;
|
|
80
|
+
if (from > 0 && context.state.sliceDoc(from - 1, from) === '.')
|
|
81
|
+
return null;
|
|
82
|
+
if (!word)
|
|
83
|
+
return context.explicit ? { from, options: PT_KIT_IDENT_COMPLETIONS } : null;
|
|
84
|
+
return { from, options: PT_KIT_IDENT_COMPLETIONS, validFor: /^[\w$]*$/ };
|
|
85
|
+
}
|
|
86
|
+
function browserScope() {
|
|
87
|
+
if (typeof window === 'undefined')
|
|
88
|
+
return {};
|
|
89
|
+
const names = [
|
|
90
|
+
'window',
|
|
91
|
+
'document',
|
|
92
|
+
'console',
|
|
93
|
+
'location',
|
|
94
|
+
'navigator',
|
|
95
|
+
'history',
|
|
96
|
+
'localStorage',
|
|
97
|
+
'sessionStorage',
|
|
98
|
+
'JSON',
|
|
99
|
+
'Math',
|
|
100
|
+
'Date',
|
|
101
|
+
'Promise',
|
|
102
|
+
'Array',
|
|
103
|
+
'Object',
|
|
104
|
+
'String',
|
|
105
|
+
'Number',
|
|
106
|
+
'Boolean',
|
|
107
|
+
'RegExp',
|
|
108
|
+
'setTimeout',
|
|
109
|
+
'clearTimeout',
|
|
110
|
+
'setInterval',
|
|
111
|
+
'clearInterval',
|
|
112
|
+
'requestAnimationFrame',
|
|
113
|
+
'fetch',
|
|
114
|
+
'MutationObserver',
|
|
115
|
+
'IntersectionObserver',
|
|
116
|
+
'ResizeObserver',
|
|
117
|
+
'Event',
|
|
118
|
+
'CustomEvent',
|
|
119
|
+
'URL',
|
|
120
|
+
'URLSearchParams',
|
|
121
|
+
'encodeURIComponent',
|
|
122
|
+
'decodeURIComponent',
|
|
123
|
+
'parseInt',
|
|
124
|
+
'parseFloat'
|
|
125
|
+
];
|
|
126
|
+
const scope = Object.create(null);
|
|
127
|
+
for (const name of names) {
|
|
128
|
+
try {
|
|
129
|
+
scope[name] = window[name];
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return scope;
|
|
48
135
|
}
|
|
49
136
|
export function findSyntaxErrors(state, message) {
|
|
50
137
|
const diagnostics = [];
|
|
@@ -90,6 +177,7 @@ function languageExtensions(language, errorMessage) {
|
|
|
90
177
|
return [
|
|
91
178
|
javascript(),
|
|
92
179
|
javascriptLanguage.data.of({ autocomplete: ptKitCompletion }),
|
|
180
|
+
javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(browserScope()) }),
|
|
93
181
|
syntaxLinter(errorMessage)
|
|
94
182
|
];
|
|
95
183
|
}
|