@citisen/litearea 0.1.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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +514 -0
  3. package/README.zh.md +362 -0
  4. package/dist/grammars.cjs +1228 -0
  5. package/dist/grammars.cjs.map +1 -0
  6. package/dist/grammars.js +1213 -0
  7. package/dist/grammars.js.map +1 -0
  8. package/dist/index.cjs +3103 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.js +3040 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/react.cjs +3032 -0
  13. package/dist/react.cjs.map +1 -0
  14. package/dist/react.js +3010 -0
  15. package/dist/react.js.map +1 -0
  16. package/dist/styles.cjs +453 -0
  17. package/dist/styles.cjs.map +1 -0
  18. package/dist/styles.css +432 -0
  19. package/dist/styles.js +447 -0
  20. package/dist/styles.js.map +1 -0
  21. package/dist/types/core/complete.d.ts +70 -0
  22. package/dist/types/core/complete.d.ts.map +1 -0
  23. package/dist/types/core/format.d.ts +34 -0
  24. package/dist/types/core/format.d.ts.map +1 -0
  25. package/dist/types/core/grammar.d.ts +14 -0
  26. package/dist/types/core/grammar.d.ts.map +1 -0
  27. package/dist/types/core/hover.d.ts +23 -0
  28. package/dist/types/core/hover.d.ts.map +1 -0
  29. package/dist/types/core/index.d.ts +12 -0
  30. package/dist/types/core/index.d.ts.map +1 -0
  31. package/dist/types/core/inspect.d.ts +34 -0
  32. package/dist/types/core/inspect.d.ts.map +1 -0
  33. package/dist/types/core/rank.d.ts +82 -0
  34. package/dist/types/core/rank.d.ts.map +1 -0
  35. package/dist/types/core/scan.d.ts +51 -0
  36. package/dist/types/core/scan.d.ts.map +1 -0
  37. package/dist/types/core/segments.d.ts +44 -0
  38. package/dist/types/core/segments.d.ts.map +1 -0
  39. package/dist/types/core/text.d.ts +113 -0
  40. package/dist/types/core/text.d.ts.map +1 -0
  41. package/dist/types/core/types.d.ts +604 -0
  42. package/dist/types/core/types.d.ts.map +1 -0
  43. package/dist/types/core/vocabulary.d.ts +82 -0
  44. package/dist/types/core/vocabulary.d.ts.map +1 -0
  45. package/dist/types/dom/create.d.ts +17 -0
  46. package/dist/types/dom/create.d.ts.map +1 -0
  47. package/dist/types/dom/editing.d.ts +89 -0
  48. package/dist/types/dom/editing.d.ts.map +1 -0
  49. package/dist/types/dom/editor.d.ts +366 -0
  50. package/dist/types/dom/editor.d.ts.map +1 -0
  51. package/dist/types/dom/index.d.ts +9 -0
  52. package/dist/types/dom/index.d.ts.map +1 -0
  53. package/dist/types/dom/mirror.d.ts +107 -0
  54. package/dist/types/dom/mirror.d.ts.map +1 -0
  55. package/dist/types/dom/overlay.d.ts +52 -0
  56. package/dist/types/dom/overlay.d.ts.map +1 -0
  57. package/dist/types/dom/popup.d.ts +95 -0
  58. package/dist/types/dom/popup.d.ts.map +1 -0
  59. package/dist/types/dom/support.d.ts +41 -0
  60. package/dist/types/dom/support.d.ts.map +1 -0
  61. package/dist/types/dom/tooltip.d.ts +39 -0
  62. package/dist/types/dom/tooltip.d.ts.map +1 -0
  63. package/dist/types/grammars/dshFont.d.ts +127 -0
  64. package/dist/types/grammars/dshFont.d.ts.map +1 -0
  65. package/dist/types/grammars/dshSentry.d.ts +84 -0
  66. package/dist/types/grammars/dshSentry.d.ts.map +1 -0
  67. package/dist/types/grammars/index.d.ts +3 -0
  68. package/dist/types/grammars/index.d.ts.map +1 -0
  69. package/dist/types/index.d.ts +15 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/react/index.d.ts +91 -0
  72. package/dist/types/react/index.d.ts.map +1 -0
  73. package/dist/types/styles.d.ts +29 -0
  74. package/dist/types/styles.d.ts.map +1 -0
  75. package/docs/architecture.md +316 -0
  76. package/docs/completion.md +320 -0
  77. package/docs/grammar.md +823 -0
  78. package/package.json +105 -0
  79. package/scripts/browser-check.mjs +838 -0
  80. package/scripts/build-css.mjs +35 -0
  81. package/scripts/release.mjs +91 -0
  82. package/scripts/verify-package.mjs +253 -0
  83. package/src/core/complete.ts +286 -0
  84. package/src/core/format.ts +71 -0
  85. package/src/core/grammar.ts +40 -0
  86. package/src/core/hover.ts +129 -0
  87. package/src/core/index.ts +98 -0
  88. package/src/core/inspect.ts +198 -0
  89. package/src/core/rank.ts +317 -0
  90. package/src/core/scan.ts +720 -0
  91. package/src/core/segments.ts +185 -0
  92. package/src/core/text.ts +238 -0
  93. package/src/core/types.ts +681 -0
  94. package/src/core/vocabulary.ts +196 -0
  95. package/src/dom/create.ts +31 -0
  96. package/src/dom/editing.ts +213 -0
  97. package/src/dom/editor.ts +1143 -0
  98. package/src/dom/index.ts +46 -0
  99. package/src/dom/mirror.ts +305 -0
  100. package/src/dom/overlay.ts +106 -0
  101. package/src/dom/popup.ts +323 -0
  102. package/src/dom/support.ts +88 -0
  103. package/src/dom/tooltip.ts +112 -0
  104. package/src/grammars/dshFont.ts +1004 -0
  105. package/src/grammars/dshSentry.ts +742 -0
  106. package/src/grammars/index.ts +57 -0
  107. package/src/index.ts +122 -0
  108. package/src/react/index.tsx +248 -0
  109. package/src/styles.ts +529 -0
@@ -0,0 +1,432 @@
1
+ .litearea {
2
+ --litearea-font: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
3
+ --litearea-font-size: 13px;
4
+ --litearea-line-height: 20px;
5
+ --litearea-padding-block: 6px;
6
+ --litearea-padding-inline: 10px;
7
+ --litearea-radius: 8px;
8
+ --litearea-fg: #1f2328;
9
+ --litearea-fg-dim: #6b7280;
10
+ --litearea-fg-strong: #111827;
11
+ --litearea-bg: #ffffff;
12
+ --litearea-bg-raised: #ffffff;
13
+ --litearea-border: #d8dbe0;
14
+ --litearea-border-focus: #4d6bfe;
15
+ --litearea-accent: #4d6bfe;
16
+ --litearea-accent-soft: rgba(77, 107, 254, 0.12);
17
+ --litearea-selection: rgba(77, 107, 254, 0.22);
18
+ --litearea-error: #e5484d;
19
+ --litearea-warning: #d97706;
20
+ --litearea-info: #4d6bfe;
21
+ --litearea-hint: #8b8f97;
22
+ --litearea-shadow: 0 6px 24px rgba(15, 23, 42, 0.14);
23
+
24
+ --litearea-scope-text: var(--litearea-fg);
25
+ --litearea-scope-word: var(--litearea-fg);
26
+ --litearea-scope-family: var(--litearea-fg);
27
+ --litearea-scope-family-generic: #7c3aed;
28
+ --litearea-scope-family-unknown: var(--litearea-warning);
29
+ --litearea-scope-family-unclosed: var(--litearea-error);
30
+ --litearea-scope-weight: var(--litearea-accent);
31
+ --litearea-scope-weight-missing: var(--litearea-warning);
32
+ --litearea-scope-state: var(--litearea-accent);
33
+ --litearea-scope-property: #7c3aed;
34
+ --litearea-scope-operator: var(--litearea-fg-dim);
35
+ --litearea-scope-separator: var(--litearea-fg-dim);
36
+ --litearea-scope-value-shape: #0f766e;
37
+ --litearea-scope-value-color: #0f766e;
38
+ --litearea-scope-value-pattern: #0f766e;
39
+ --litearea-scope-value-motion: #0f766e;
40
+ --litearea-scope-value-number: #b45309;
41
+ --litearea-scope-comment: var(--litearea-fg-dim);
42
+ --litearea-scope-invalid: var(--litearea-error);
43
+ --litearea-scope-keyword: var(--litearea-accent);
44
+ --litearea-scope-string: #0f766e;
45
+ --litearea-scope-number: #b45309;
46
+
47
+ position: relative;
48
+ display: block;
49
+ color: var(--litearea-fg);
50
+ }
51
+
52
+ @media (prefers-color-scheme: dark) {
53
+ .litearea {
54
+ --litearea-fg: #e6e8eb;
55
+ --litearea-fg-dim: #8b919b;
56
+ --litearea-fg-strong: #ffffff;
57
+ --litearea-bg: #1b1e24;
58
+ --litearea-bg-raised: #23262c;
59
+ --litearea-border: #363b44;
60
+ --litearea-scope-family-generic: #c4a2ff;
61
+ --litearea-scope-property: #c4a2ff;
62
+ --litearea-scope-value-shape: #5eead4;
63
+ --litearea-scope-value-color: #5eead4;
64
+ --litearea-scope-value-pattern: #5eead4;
65
+ --litearea-scope-value-motion: #5eead4;
66
+ --litearea-scope-value-number: #fbbf24;
67
+ --litearea-scope-string: #5eead4;
68
+ --litearea-scope-number: #fbbf24;
69
+ --litearea-error: #ff6b6b;
70
+ --litearea-warning: #f59e0b;
71
+ --litearea-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
72
+ }
73
+ }
74
+
75
+ /* ── the box ─────────────────────────────────────────────────────────────── */
76
+
77
+ .litearea-box {
78
+ position: relative;
79
+ display: block;
80
+ border: 1px solid var(--litearea-border);
81
+ border-radius: var(--litearea-radius);
82
+ background: var(--litearea-bg);
83
+ transition: border-color 120ms ease;
84
+ }
85
+
86
+ .litearea-box:focus-within {
87
+ border-color: var(--litearea-border-focus);
88
+ }
89
+
90
+ .litearea-invalid .litearea-box {
91
+ border-color: var(--litearea-error);
92
+ }
93
+
94
+ /*
95
+ * The layer and the field share this rule and nothing may be added to one alone.
96
+ * Every property here is a property the mirror copies too — three elements, one
97
+ * typography, or the paint drifts.
98
+ */
99
+ .litearea-layer,
100
+ .litearea-input {
101
+ box-sizing: border-box;
102
+ width: 100%;
103
+ margin: 0;
104
+ padding: var(--litearea-padding-block) var(--litearea-padding-inline);
105
+ border: none;
106
+ font-family: var(--litearea-font);
107
+ font-size: var(--litearea-font-size);
108
+ font-weight: 400;
109
+ font-style: normal;
110
+ font-stretch: normal;
111
+ font-variant-ligatures: none;
112
+ font-kerning: none;
113
+ font-feature-settings: "liga" 0, "calt" 0, "dlig" 0;
114
+ line-height: var(--litearea-line-height);
115
+ letter-spacing: normal;
116
+ word-spacing: normal;
117
+ text-transform: none;
118
+ text-indent: 0;
119
+ text-align: left;
120
+ direction: ltr;
121
+ tab-size: 2;
122
+ white-space: pre-wrap;
123
+ overflow-wrap: break-word;
124
+ word-break: break-word;
125
+ }
126
+
127
+ .litearea-layer {
128
+ position: absolute;
129
+ inset: 0;
130
+ overflow: hidden;
131
+ pointer-events: none;
132
+ user-select: none;
133
+ }
134
+
135
+ /*
136
+ * When the box is clamped to its maximum height the field grows a scrollbar, and a
137
+ * scrollbar narrows the text. If the layer kept the full width it would wrap
138
+ * differently from the field and every colour would slide off its character, so the
139
+ * field's measured scrollbar width is published as --litearea-scrollbar and added
140
+ * here. The value is 0 whenever no scrollbar is shown.
141
+ */
142
+ .litearea-layer {
143
+ padding-right: calc(var(--litearea-padding-inline) + var(--litearea-scrollbar, 0px));
144
+ }
145
+
146
+ .litearea-paint {
147
+ position: relative;
148
+ min-height: 100%;
149
+ /* A zero-width space keeps the layer's last line box as tall as the field's:
150
+ a trailing newline would otherwise collapse in the paint alone, and the box
151
+ would jump the moment one was typed. */
152
+ will-change: transform;
153
+ }
154
+
155
+ .litearea-input {
156
+ position: relative;
157
+ display: block;
158
+ resize: none;
159
+ background: transparent;
160
+ color: transparent;
161
+ caret-color: var(--litearea-fg);
162
+ outline: none;
163
+ overflow-y: hidden;
164
+ }
165
+
166
+ .litearea-growable .litearea-input {
167
+ resize: none;
168
+ }
169
+
170
+ .litearea-resizable .litearea-input {
171
+ resize: vertical;
172
+ }
173
+
174
+ .litearea-input::placeholder {
175
+ color: var(--litearea-fg-dim);
176
+ }
177
+
178
+ .litearea-input::selection {
179
+ background: var(--litearea-selection);
180
+ }
181
+
182
+ .litearea-readonly .litearea-input {
183
+ caret-color: transparent;
184
+ }
185
+
186
+ /*
187
+ * The rules that spend the variables, generated from the same list that declares them. There is
188
+ * deliberately NO catch-all rule setting a property on every painted span: there was one, and a
189
+ * class plus an element outranks a bare class on specificity, so it silently switched off every
190
+ * squiggle in the library.
191
+ *
192
+ * A scope that is not in the list gets no colour from here, and a host writing a grammar of its
193
+ * own styles it with a plain rule — .litearea-scope-my-thing { color: … } — since nothing in
194
+ * this file competes for that selector.
195
+ */
196
+ .litearea-scope-text { color: var(--litearea-scope-text); }
197
+ .litearea-scope-word { color: var(--litearea-scope-word); }
198
+ .litearea-scope-family { color: var(--litearea-scope-family); }
199
+ .litearea-scope-family-generic { color: var(--litearea-scope-family-generic); }
200
+ .litearea-scope-family-unknown { color: var(--litearea-scope-family-unknown); }
201
+ .litearea-scope-family-unclosed { color: var(--litearea-scope-family-unclosed); }
202
+ .litearea-scope-weight { color: var(--litearea-scope-weight); }
203
+ .litearea-scope-weight-missing { color: var(--litearea-scope-weight-missing); }
204
+ .litearea-scope-state { color: var(--litearea-scope-state); }
205
+ .litearea-scope-property { color: var(--litearea-scope-property); }
206
+ .litearea-scope-operator { color: var(--litearea-scope-operator); }
207
+ .litearea-scope-separator { color: var(--litearea-scope-separator); }
208
+ .litearea-scope-value-shape { color: var(--litearea-scope-value-shape); }
209
+ .litearea-scope-value-color { color: var(--litearea-scope-value-color); }
210
+ .litearea-scope-value-pattern { color: var(--litearea-scope-value-pattern); }
211
+ .litearea-scope-value-motion { color: var(--litearea-scope-value-motion); }
212
+ .litearea-scope-value-number { color: var(--litearea-scope-value-number); }
213
+ .litearea-scope-comment { color: var(--litearea-scope-comment); }
214
+ .litearea-scope-invalid { color: var(--litearea-scope-invalid); }
215
+ .litearea-scope-keyword { color: var(--litearea-scope-keyword); }
216
+ .litearea-scope-string { color: var(--litearea-scope-string); }
217
+ .litearea-scope-number { color: var(--litearea-scope-number); }
218
+
219
+ .litearea-dec-effective {
220
+ border-radius: 3px;
221
+ background: var(--litearea-accent-soft);
222
+ box-shadow: 0 0 0 1px var(--litearea-accent-soft);
223
+ }
224
+
225
+ /* The four shapes a diagnostic can take. Wavy for the two that mean "fix this", dotted for
226
+ the two that mean "worth knowing" — the same distinction VSCode draws, and the reason
227
+ severity is a class rather than an inline colour. */
228
+ .litearea-diag-error {
229
+ text-decoration-line: underline;
230
+ text-decoration-style: wavy;
231
+ text-decoration-color: var(--litearea-error);
232
+ text-decoration-skip-ink: none;
233
+ text-underline-offset: 3px;
234
+ }
235
+
236
+ .litearea-diag-warning {
237
+ text-decoration-line: underline;
238
+ text-decoration-style: wavy;
239
+ text-decoration-color: var(--litearea-warning);
240
+ text-decoration-skip-ink: none;
241
+ text-underline-offset: 3px;
242
+ }
243
+
244
+ .litearea-diag-info {
245
+ text-decoration-line: underline;
246
+ text-decoration-style: dotted;
247
+ text-decoration-color: var(--litearea-info);
248
+ text-decoration-skip-ink: none;
249
+ text-underline-offset: 3px;
250
+ }
251
+
252
+ .litearea-diag-hint {
253
+ text-decoration-line: underline;
254
+ text-decoration-style: dotted;
255
+ text-decoration-color: var(--litearea-hint);
256
+ text-decoration-skip-ink: none;
257
+ text-underline-offset: 3px;
258
+ }
259
+
260
+ /* ── the completion list ─────────────────────────────────────────────────── */
261
+
262
+ /*
263
+ * The container holds two things and scrolls NEITHER of them: the list scrolls itself, and the
264
+ * documentation is pinned below it. Putting the documentation inside the scroll range — which is
265
+ * what this used to do — makes it unreachable with a long list and a long explanation: the
266
+ * arrows move the active row rather than the scrollbar, so a keyboard user never sees it, and a
267
+ * mouse user has to scroll down to read it and back up to reach the next row.
268
+ */
269
+ .litearea-popup {
270
+ position: absolute;
271
+ z-index: 30;
272
+ display: none;
273
+ flex-direction: column;
274
+ max-width: 460px;
275
+ padding: 4px;
276
+ border: 1px solid var(--litearea-border);
277
+ border-radius: 10px;
278
+ background: var(--litearea-bg-raised);
279
+ box-shadow: var(--litearea-shadow);
280
+ font-family: var(--litearea-font);
281
+ font-size: 12px;
282
+ line-height: 18px;
283
+ color: var(--litearea-fg);
284
+ overflow: hidden;
285
+ }
286
+
287
+ .litearea-popup[data-open="true"] {
288
+ display: flex;
289
+ }
290
+
291
+ /* The rows, and the only part that scrolls. Its height is bounded so the documentation below
292
+ always has somewhere to live. */
293
+ .litearea-list {
294
+ min-height: 0;
295
+ max-height: 208px;
296
+ overflow-y: auto;
297
+ }
298
+
299
+ /*
300
+ * The explanation, pinned. Its own height is bounded and it scrolls ITSELF, so a long
301
+ * explanation stays readable while the rows stay put — and arrowing to the next row swaps the
302
+ * text in place instead of requiring a scroll back up.
303
+ */
304
+ .litearea-docs {
305
+ flex: none;
306
+ max-height: 132px;
307
+ overflow-y: auto;
308
+ margin: 4px -4px -4px;
309
+ padding: 6px 10px;
310
+ border-top: 1px solid var(--litearea-border);
311
+ background: var(--litearea-bg);
312
+ border-radius: 0 0 10px 10px;
313
+ color: var(--litearea-fg);
314
+ white-space: pre-wrap;
315
+ }
316
+
317
+ .litearea-popup[data-docs="false"] .litearea-docs {
318
+ display: none;
319
+ }
320
+
321
+ .litearea-row {
322
+ display: flex;
323
+ align-items: baseline;
324
+ gap: 8px;
325
+ padding: 3px 6px;
326
+ border-radius: 6px;
327
+ cursor: pointer;
328
+ white-space: nowrap;
329
+ overflow: hidden;
330
+ }
331
+
332
+ .litearea-row[aria-selected="true"] {
333
+ background: var(--litearea-accent-soft);
334
+ }
335
+
336
+ .litearea-rowKind {
337
+ flex: none;
338
+ width: 7px;
339
+ height: 7px;
340
+ border-radius: 2px;
341
+ background: var(--litearea-fg-dim);
342
+ transform: translateY(-1px);
343
+ }
344
+
345
+ .litearea-kind-family { background: var(--litearea-scope-family-generic); }
346
+ .litearea-kind-generic { background: var(--litearea-scope-family-generic); }
347
+ .litearea-kind-weight { background: var(--litearea-scope-weight); }
348
+ .litearea-kind-state { background: var(--litearea-scope-state); }
349
+ .litearea-kind-property { background: var(--litearea-scope-property); }
350
+ .litearea-kind-value { background: var(--litearea-scope-value-shape); }
351
+ .litearea-kind-number { background: var(--litearea-scope-value-number); }
352
+ .litearea-kind-custom { background: var(--litearea-fg-dim); }
353
+
354
+ .litearea-rowLabel {
355
+ flex: 1 1 auto;
356
+ min-width: 0;
357
+ overflow: hidden;
358
+ text-overflow: ellipsis;
359
+ }
360
+
361
+ .litearea-rowMatch {
362
+ color: var(--litearea-accent);
363
+ font-weight: 600;
364
+ }
365
+
366
+ .litearea-rowDetail {
367
+ flex: none;
368
+ color: var(--litearea-fg-dim);
369
+ font-size: 11px;
370
+ }
371
+
372
+ .litearea-docsTitle {
373
+ font-weight: 600;
374
+ }
375
+
376
+ .litearea-docsDetail {
377
+ color: var(--litearea-fg-dim);
378
+ }
379
+
380
+ .litearea-docsBody {
381
+ margin-top: 2px;
382
+ color: var(--litearea-fg-dim);
383
+ }
384
+
385
+ /* ── the hover tooltip ───────────────────────────────────────────────────── */
386
+
387
+ .litearea-tooltip {
388
+ position: absolute;
389
+ z-index: 40;
390
+ display: none;
391
+ max-width: 340px;
392
+ padding: 6px 10px;
393
+ border: 1px solid var(--litearea-border);
394
+ border-radius: 8px;
395
+ background: var(--litearea-bg-raised);
396
+ box-shadow: var(--litearea-shadow);
397
+ font-family: var(--litearea-font);
398
+ font-size: 11px;
399
+ line-height: 16px;
400
+ color: var(--litearea-fg);
401
+ pointer-events: none;
402
+ white-space: pre-wrap;
403
+ }
404
+
405
+ .litearea-tooltip[data-open="true"] {
406
+ display: block;
407
+ }
408
+
409
+ .litearea-tooltipTitle {
410
+ font-weight: 600;
411
+ }
412
+
413
+ .litearea-tooltipDetail {
414
+ color: var(--litearea-fg-dim);
415
+ }
416
+
417
+ .litearea-tooltipBody {
418
+ margin-top: 3px;
419
+ color: var(--litearea-fg-dim);
420
+ }
421
+
422
+ .litearea-srOnly {
423
+ position: absolute;
424
+ width: 1px;
425
+ height: 1px;
426
+ padding: 0;
427
+ margin: -1px;
428
+ overflow: hidden;
429
+ clip: rect(0, 0, 0, 0);
430
+ white-space: nowrap;
431
+ border: 0;
432
+ }