@bearcove/codemirror-lang-styx 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.
- package/README.md +58 -0
- package/dist/index.cjs +283 -0
- package/dist/index.d.cts +64 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +263 -0
- package/package.json +63 -0
- package/src/heredoc.ts +116 -0
- package/src/highlight.ts +37 -0
- package/src/index.ts +247 -0
- package/src/styx.grammar +110 -0
- package/src/syntax.grammar.terms.ts +29 -0
- package/src/syntax.grammar.ts +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# @bearcove/codemirror-lang-styx
|
|
2
|
+
|
|
3
|
+
[Styx](https://styx.bearcove.net) language support for [CodeMirror 6](https://codemirror.net/).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bearcove/codemirror-lang-styx
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { EditorView, basicSetup } from "codemirror";
|
|
15
|
+
import { styx } from "@bearcove/codemirror-lang-styx";
|
|
16
|
+
|
|
17
|
+
new EditorView({
|
|
18
|
+
doc: `// Example Styx config
|
|
19
|
+
server {
|
|
20
|
+
host localhost
|
|
21
|
+
port 8080
|
|
22
|
+
tls {
|
|
23
|
+
enabled true
|
|
24
|
+
cert "/etc/ssl/cert.pem"
|
|
25
|
+
}
|
|
26
|
+
}`,
|
|
27
|
+
extensions: [basicSetup, styx()],
|
|
28
|
+
parent: document.getElementById("editor")!,
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Syntax highlighting for all Styx constructs
|
|
35
|
+
- Code folding for objects, sequences, and heredocs
|
|
36
|
+
- Auto-closing brackets and quotes
|
|
37
|
+
- Basic autocompletion for common schema tags
|
|
38
|
+
- Comment toggling support
|
|
39
|
+
|
|
40
|
+
## Development
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Install dependencies
|
|
44
|
+
npm install
|
|
45
|
+
|
|
46
|
+
# Build the grammar and bundle
|
|
47
|
+
npm run build
|
|
48
|
+
|
|
49
|
+
# Watch mode for development
|
|
50
|
+
npm run dev
|
|
51
|
+
|
|
52
|
+
# Run tests
|
|
53
|
+
npm test
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
parser: () => parser,
|
|
24
|
+
styx: () => styx,
|
|
25
|
+
styxLanguage: () => styxLanguage
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/syntax.grammar.ts
|
|
30
|
+
var import_lr2 = require("@lezer/lr");
|
|
31
|
+
|
|
32
|
+
// src/heredoc.ts
|
|
33
|
+
var import_lr = require("@lezer/lr");
|
|
34
|
+
|
|
35
|
+
// src/syntax.grammar.terms.ts
|
|
36
|
+
var heredoc = 39;
|
|
37
|
+
|
|
38
|
+
// src/heredoc.ts
|
|
39
|
+
function isDelimiterStart(ch) {
|
|
40
|
+
return ch >= 65 && ch <= 90;
|
|
41
|
+
}
|
|
42
|
+
function isDelimiterChar(ch) {
|
|
43
|
+
return ch >= 65 && ch <= 90 || ch >= 48 && ch <= 57 || ch === 95;
|
|
44
|
+
}
|
|
45
|
+
function isLangHintChar(ch) {
|
|
46
|
+
return ch >= 97 && ch <= 122 || ch >= 48 && ch <= 57 || ch === 95 || ch === 46 || ch === 45;
|
|
47
|
+
}
|
|
48
|
+
var heredocTokenizer = new import_lr.ExternalTokenizer(
|
|
49
|
+
(input, stack) => {
|
|
50
|
+
if (input.next !== 60) return;
|
|
51
|
+
input.advance();
|
|
52
|
+
if (input.next !== 60) return;
|
|
53
|
+
input.advance();
|
|
54
|
+
if (!isDelimiterStart(input.next)) return;
|
|
55
|
+
let delimiter = "";
|
|
56
|
+
while (isDelimiterChar(input.next)) {
|
|
57
|
+
delimiter += String.fromCharCode(input.next);
|
|
58
|
+
input.advance();
|
|
59
|
+
}
|
|
60
|
+
if (input.next === 44) {
|
|
61
|
+
input.advance();
|
|
62
|
+
if (input.next >= 97 && input.next <= 122) {
|
|
63
|
+
while (isLangHintChar(input.next)) {
|
|
64
|
+
input.advance();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (input.next !== 10 && input.next !== 13) return;
|
|
69
|
+
if (input.next === 13) input.advance();
|
|
70
|
+
if (input.next === 10) input.advance();
|
|
71
|
+
while (input.next !== -1) {
|
|
72
|
+
while (input.next === 32 || input.next === 9) {
|
|
73
|
+
input.advance();
|
|
74
|
+
}
|
|
75
|
+
let matchPos = 0;
|
|
76
|
+
let isMatch = true;
|
|
77
|
+
const lineStart = input.pos;
|
|
78
|
+
for (let i = 0; i < delimiter.length && input.next !== -1; i++) {
|
|
79
|
+
if (input.next !== delimiter.charCodeAt(i)) {
|
|
80
|
+
isMatch = false;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
input.advance();
|
|
84
|
+
matchPos++;
|
|
85
|
+
}
|
|
86
|
+
if (isMatch && matchPos === delimiter.length) {
|
|
87
|
+
if (input.next === 10 || input.next === 13 || input.next === -1) {
|
|
88
|
+
input.acceptToken(heredoc);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
while (input.next !== 10 && input.next !== 13 && input.next !== -1) {
|
|
93
|
+
input.advance();
|
|
94
|
+
}
|
|
95
|
+
if (input.next === 13) input.advance();
|
|
96
|
+
if (input.next === 10) input.advance();
|
|
97
|
+
}
|
|
98
|
+
input.acceptToken(heredoc);
|
|
99
|
+
},
|
|
100
|
+
{ contextual: false }
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// src/highlight.ts
|
|
104
|
+
var import_highlight = require("@lezer/highlight");
|
|
105
|
+
var styxHighlight = (0, import_highlight.styleTags)({
|
|
106
|
+
// Keys (property names) - first atom in an Entry
|
|
107
|
+
"KeyAtom/BareScalar": import_highlight.tags.propertyName,
|
|
108
|
+
"KeyAtom/QuotedScalar": import_highlight.tags.propertyName,
|
|
109
|
+
"KeyPayload/BareScalar": import_highlight.tags.propertyName,
|
|
110
|
+
"KeyPayload/QuotedScalar": import_highlight.tags.propertyName,
|
|
111
|
+
// Values - second atom in an Entry
|
|
112
|
+
"ValueAtom/BareScalar": import_highlight.tags.string,
|
|
113
|
+
"ValueAtom/QuotedScalar": import_highlight.tags.string,
|
|
114
|
+
"ValuePayload/BareScalar": import_highlight.tags.string,
|
|
115
|
+
"ValuePayload/QuotedScalar": import_highlight.tags.string,
|
|
116
|
+
// Sequence items
|
|
117
|
+
"SeqAtom/BareScalar": import_highlight.tags.string,
|
|
118
|
+
"SeqAtom/QuotedScalar": import_highlight.tags.string,
|
|
119
|
+
"SeqPayload/BareScalar": import_highlight.tags.string,
|
|
120
|
+
"SeqPayload/QuotedScalar": import_highlight.tags.string,
|
|
121
|
+
// Tags (@foo)
|
|
122
|
+
Tag: import_highlight.tags.tagName,
|
|
123
|
+
// Raw strings and heredocs
|
|
124
|
+
RawScalar: import_highlight.tags.special(import_highlight.tags.string),
|
|
125
|
+
Heredoc: import_highlight.tags.special(import_highlight.tags.string),
|
|
126
|
+
// Inline attributes (key>value pairs)
|
|
127
|
+
Attributes: import_highlight.tags.special(import_highlight.tags.variableName),
|
|
128
|
+
Unit: import_highlight.tags.null,
|
|
129
|
+
Comment: import_highlight.tags.lineComment,
|
|
130
|
+
DocComment: import_highlight.tags.docComment,
|
|
131
|
+
"( )": import_highlight.tags.paren,
|
|
132
|
+
"{ }": import_highlight.tags.brace,
|
|
133
|
+
",": import_highlight.tags.separator
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// src/syntax.grammar.ts
|
|
137
|
+
var parser = import_lr2.LRParser.deserialize({
|
|
138
|
+
version: 14,
|
|
139
|
+
states: "*tQVQPOOOOQO'#C^'#C^OzQPO'#C_OOQQ'#Cb'#CbOOQQ'#Cd'#CdOOQQ'#Ce'#CeO#aQPO'#CnOOQQ'#Cs'#CsOOQQ'#Ct'#CtOOQQ'#Cv'#CvO$VQPO'#ChOOQQ'#Cw'#CwO$rQRO'#CaOOQQ'#Ca'#CaO%lQRO'#C`O&SQPO'#DWOOQO'#DW'#DWOOQO'#C|'#C|QVQPOOOOQO'#C}'#C}OOQO-E6{-E6{OOQO'#Cp'#CpOOQO'#DP'#DPO!lQPO'#CoOOQO'#Cr'#CrO&XQPO'#CrO&cQPO'#CoOOQQ,59Y,59YO&nQPO,59YOOQO'#DO'#DOO#hQPO'#CiOOQO'#Cu'#CuO&sQPO'#CjOOQO'#Cj'#CjO'gQPO'#CiOOQQ,59S,59SO'nQPO,59SOOQQ'#Cc'#CcOOQQ,58{,58{OOQO'#C{'#C{OOQO'#Cz'#CzO'sQPO'#CxOOQO'#Cx'#CxOOQO,58z,58zOOQO,59r,59rOOQO-E6z-E6zOOQO-E6}-E6}O(QQPO,59ZOOQO,59^,59^O(]QPO'#DPO(QQPO,59ZO(QQPO,59ZOOQQ1G.t1G.tOOQO-E6|-E6|O(sQPO,59TOOQO'#Ck'#CkOOQO,59U,59UO(sQPO,59TOOQO'#DR'#DRO(sQPO,59TOOQQ1G.n1G.nOOQO'#Cy'#CyOOQO,59d,59dO(zQPO1G.uO(zQPO1G.uOOQO,59l,59lOOQO-E7O-E7OO)VQPO1G.oO)VQPO1G.oOOQO,59m,59mOOQO-E7P-E7PO)^QPO7+$aP)iQPO'#DQO)vQPO7+$ZP#hQPO'#DO",
|
|
140
|
+
stateData: "*W~OyOS~OZYOaUO{PO|`O}cO!ORO!PSO!QTO!RVO!SWO!TXO~O}cO|RXZRXaRX!ORX!PRX!QRX!RRX!SRX!TRX~OZYOaUOeeO|eO}cO!ORO!PSO!QTO!RVO!SWO!TXO~O`kO~P!lOZYOaUO|mO!ORO!PSO!QTO!RVO!SWO!TXO~OYsO~P#hOZYOaUO!PSO!QTO!RVO!SWO~OZTXaTXwTX|TX!OTX!PTX!QTX!RTX!STX!TTX`TXeTX~P$^OwwO!ORO!TXO|SX`SXeSX~P$^O||O~O!ORO!TXO~P$^OeeO|eO`cX~O`!UO~OY^XZ^Xa^X|^X!O^X!P^X!Q^X!R^X!S^X!T^X~P$^OY]X~P#hOY!^O~O|lX`lXelX~P$^OeeO|eO`ca~O}cO!ORO!TXO`sXesX|sX~P$^OY]a~P#hOeeO|eO`ci~OY]i~P#hOeeO|eO`cq~O}cO!ORO!TXO~P$^OY]q~P#hO!O!R}{!Q!S!T{~",
|
|
141
|
+
goto: "(Q{PP|!Q![!i!r#[#_#_PP#_$Q$T$gPP#_$j$mP$z#_#_%U%b%z&T&W&Z%w&^&d&o'T'h'rPPPP'|T_ObS_ObXiUg!R!jS_ObWhUg!R!jR!Qi_^OUbgi!R!j^[OUbgi!R!jdpYnr!W!Z!]!e!f!k!lRy^Rv[^ZOUbgi!R!jdoYnr!W!Z!]!e!f!k!lQu[Qx^Q!XpR!_yRtYQrYQ!WnW![r!W!]!fX!g!Z!e!k!lR!YpRlUYfUg!S!a!iX!Rj!P!T!bQjUQ!PgT!c!R!jeqYnr!W!Z!]!e!f!k!l^ZOUbgi!R!jdoYnr!W!Z!]!e!f!k!lRx^_]OUbgi!R!jR{^R!`yRz^QbOR}b[QOUbg!R!jRdQQnYY!Vn!Z!e!k!lQ!ZrS!e!W!]R!k!fQgUW!Og!S!a!iQ!SjS!a!P!TR!i!bQ!TjQ!b!PT!d!T!bQ!]rQ!f!WT!h!]!fTaOb",
|
|
142
|
+
nodeNames: "\u26A0 Document Comment DocComment Entry KeyExpr Tag KeyPayload QuotedScalar RawScalar ) ( Sequence SeqContent SeqItem SeqPayload } { Object ObjContent ObjSep , ObjItem Unit Attributes SeqAtom BareScalar KeyAtom ValueExpr ValuePayload ValueAtom Heredoc",
|
|
143
|
+
maxTerm: 51,
|
|
144
|
+
nodeProps: [
|
|
145
|
+
["openedBy", 10, "(", 16, "{"],
|
|
146
|
+
["closedBy", 11, ")", 17, "}"]
|
|
147
|
+
],
|
|
148
|
+
propSources: [styxHighlight],
|
|
149
|
+
skippedNodes: [0],
|
|
150
|
+
repeatNodeCount: 6,
|
|
151
|
+
tokenData: "B[~RmOX!|XY(UYZ(aZ]!|]^(f^p!|pq(Uqr!|rs(lsx!|xy)syz)xz|!||})}}!P!|!P!Q*S!Q!^!|!^!_$Q!a!b!|!b!c?b!c#f!|#f#g@U#g#o!|#o#pBQ#p#q!|#q#rBV#r;'S!|;'S;=`(O<%lO!|~#R_!T~OX!|Z]!|^p!|qr!|sx!|z|!|}!^!|!^!_$Q!_!`!|!`!a$|!a#o!|#p#q!|#r;'S!|;'S;=`(O<%lO!|~$T]OX$QZ]$Q^p$Qqr$Qsx$Qz|$Q}!`$Q!`!a$|!a#o$Q#p#q$Q#r;'S$Q;'S;=`'r<%lO$Q~%PZOX%rZ]%r^p%rqr%rsx%rz|%r}#o%r#p#q%r#r;'S%r;'S;=`'x<%lO%r~%w]!S~OX%rXY&pZ]%r^p%rpq&pqr%rsx%rz|%r}#o%r#p#q%r#r;'S%r;'S;=`'x<%lO%r~&s_OX$QXY&pZ]$Q^p$Qpq&pqr$Qsx$Qz|$Q}!_$Q!a!b$Q!c#o$Q#p#q$Q#r;'S$Q;'S;=`'r<%lO$Q~'uP;=`<%l$Q~'{P;=`<%l%r~(RP;=`<%l!|~(ZQy~XY(Upq(U~(fO|~~(iPYZ(a~(oXOY(lZ](l^r(lrs)[s#O(l#O#P)a#P;'S(l;'S;=`)m<%lO(l~)aO!P~~)dRO;'S(l;'S;=`)m<%lO(l~)pP;=`<%l(l~)xOZ~~)}OY~~*SOe~~*Xa!T~OX!|Z]!|^p!|qr!|sx!|z|!|}!P!|!P!Q+^!Q!^!|!^!_$Q!_!`!|!`!a$|!a#o!|#p#q!|#r;'S!|;'S;=`(O<%lO!|~+ch!T~OX,}XY.pZ],}^p,}pq.pqr,}rs.psx,}xz.pz|,}|}.p}!P,}!P!Q5u!Q!^,}!^!_/_!_!`,}!`!a0x!a#o,}#o#p.p#p#q,}#q#r.p#r;'S,};'S;=`5o<%lO,}~-Uh{~!T~OX,}XY.pZ],}^p,}pq.pqr,}rs.psx,}xz.pz|,}|}.p}!^,}!^!_/_!_!`,}!`!a0x!a#Q,}#Q#R!|#R#o,}#o#p.p#p#q,}#q#r.p#r;'S,};'S;=`5o<%lO,}~.uU{~OY.pZ].p^#Q.p#R;'S.p;'S;=`/X<%lO.p~/[P;=`<%l.p~/df{~OX/_XY.pZ]/_^p/_pq.pqr/_rs.psx/_xz.pz|/_|}.p}!`/_!`!a0x!a#Q/_#Q#R$Q#R#o/_#o#p.p#p#q/_#q#r.p#r;'S/_;'S;=`5c<%lO/_~0}d{~OX2]XY.pZ]2]^p2]pq.pqr2]rs.psx2]xz.pz|2]|}.p}#Q2]#Q#R%r#R#o2]#o#p.p#p#q2]#q#r.p#r;'S2];'S;=`5i<%lO2]~2dd{~!S~OX2]XY3rZ]2]^p2]pq3rqr2]rs.psx2]xz.pz|2]|}.p}#Q2]#Q#R%r#R#o2]#o#p.p#p#q2]#q#r.p#r;'S2];'S;=`5i<%lO2]~3wh{~OX/_XY3rZ]/_^p/_pq3rqr/_rs.psx/_xz.pz|/_|}.p}!_/_!_!a.p!a!b/_!b!c.p!c#Q/_#Q#R$Q#R#o/_#o#p.p#p#q/_#q#r.p#r;'S/_;'S;=`5c<%lO/_~5fP;=`<%l/_~5lP;=`<%l2]~5rP;=`<%l,}~5zj!T~OX5uXY7lYZ8XZ]5u]^8^^p5upq7lqr5urs7lsx5uxz7lz|5u|}7l}!^5u!^!_8j!_!`5u!`!a:X!a#Q5u#Q#R!|#R#o5u#o#p7l#p#q5u#q#r7l#r;'S5u;'S;=`?[<%lO5u~7oWOY7lYZ8XZ]7l]^8^^#Q7l#R;'S7l;'S;=`8d<%lO7l~8^O}~~8aPYZ8X~8gP;=`<%l7l~8mhOX8jXY7lYZ8XZ]8j]^8^^p8jpq7lqr8jrs7lsx8jxz7lz|8j|}7l}!`8j!`!a:X!a#Q8j#Q#R$Q#R#o8j#o#p7l#p#q8j#q#r7l#r;'S8j;'S;=`?O<%lO8j~:[fOX;pXY7lYZ8XZ];p]^8^^p;ppq7lqr;prs7lsx;pxz7lz|;p|}7l}#Q;p#Q#R%r#R#o;p#o#p7l#p#q;p#q#r7l#r;'S;p;'S;=`?U<%lO;p~;uf!S~OX;pXY=ZYZ8XZ];p]^8^^p;ppq=Zqr;prs7lsx;pxz7lz|;p|}7l}#Q;p#Q#R%r#R#o;p#o#p7l#p#q;p#q#r7l#r;'S;p;'S;=`?U<%lO;p~=^jOX8jXY=ZYZ8XZ]8j]^8^^p8jpq=Zqr8jrs7lsx8jxz7lz|8j|}7l}!_8j!_!a7l!a!b8j!b!c7l!c#Q8j#Q#R$Q#R#o8j#o#p7l#p#q8j#q#r7l#r;'S8j;'S;=`?O<%lO8j~?RP;=`<%l8j~?XP;=`<%l;p~?_P;=`<%l5u~?gR!R~!c!}?p#R#S?p#T#o?p~?uT!O~}!O?p!Q![?p!c!}?p#R#S?p#T#o?p~@Za!T~OX!|Z]!|^p!|qr!|rsA`st@Utx!|z|!|}!^!|!^!_$Q!_!`!|!`!a$|!a#o!|#p#q!|#r;'S!|;'S;=`(O<%lO!|~AcTOrA`rsArs;'SA`;'S;=`Az<%lOA`~AwP!Q~stAr~A}P;=`<%lA`~BVOa~~B[O`~",
|
|
152
|
+
tokenizers: [0, heredocTokenizer],
|
|
153
|
+
topRules: { "Document": [0, 1] },
|
|
154
|
+
tokenPrec: 413
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// src/index.ts
|
|
158
|
+
var import_language = require("@codemirror/language");
|
|
159
|
+
var import_autocomplete = require("@codemirror/autocomplete");
|
|
160
|
+
var import_common = require("@lezer/common");
|
|
161
|
+
function parseHeredocText(text) {
|
|
162
|
+
const match = text.match(/^<<([A-Z][A-Z0-9_]*)(?:,([a-z][a-z0-9_.-]*))?\r?\n/);
|
|
163
|
+
if (!match) return null;
|
|
164
|
+
const delimiter = match[1];
|
|
165
|
+
const langHint = match[2] || null;
|
|
166
|
+
const headerLen = match[0].length;
|
|
167
|
+
const delimPattern = new RegExp(`^[ \\t]*${delimiter}$`, "m");
|
|
168
|
+
const contentMatch = text.slice(headerLen).match(delimPattern);
|
|
169
|
+
if (!contentMatch || contentMatch.index === void 0) {
|
|
170
|
+
return {
|
|
171
|
+
delimiter,
|
|
172
|
+
langHint,
|
|
173
|
+
contentStart: headerLen,
|
|
174
|
+
contentEnd: text.length
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
delimiter,
|
|
179
|
+
langHint,
|
|
180
|
+
contentStart: headerLen,
|
|
181
|
+
contentEnd: headerLen + contentMatch.index
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function createMixedParser(nestedLanguages) {
|
|
185
|
+
const langMap = /* @__PURE__ */ new Map();
|
|
186
|
+
for (const { tag, language } of nestedLanguages) {
|
|
187
|
+
langMap.set(tag, language.language.parser);
|
|
188
|
+
}
|
|
189
|
+
return (0, import_common.parseMixed)((node, input) => {
|
|
190
|
+
if (node.type.name !== "Heredoc") return null;
|
|
191
|
+
const text = input.read(node.from, node.to);
|
|
192
|
+
const parsed = parseHeredocText(text);
|
|
193
|
+
if (!parsed || !parsed.langHint) return null;
|
|
194
|
+
const nestedParser = langMap.get(parsed.langHint);
|
|
195
|
+
if (!nestedParser) return null;
|
|
196
|
+
return {
|
|
197
|
+
parser: nestedParser,
|
|
198
|
+
overlay: [{ from: node.from + parsed.contentStart, to: node.from + parsed.contentEnd }]
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
var styxFoldService = import_language.foldService.of((state, lineStart, lineEnd) => {
|
|
203
|
+
const tree = (0, import_language.syntaxTree)(state);
|
|
204
|
+
let node = tree.resolveInner(lineEnd, -1);
|
|
205
|
+
for (let cur = node; cur; cur = cur.parent) {
|
|
206
|
+
if (cur.type.name === "Object" || cur.type.name === "Sequence") {
|
|
207
|
+
const first = cur.firstChild;
|
|
208
|
+
const last = cur.lastChild;
|
|
209
|
+
if (first && last && first.to < last.from && first.from >= lineStart) {
|
|
210
|
+
return { from: first.to, to: last.from };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
});
|
|
216
|
+
var baseProps = [
|
|
217
|
+
import_language.indentNodeProp.add({
|
|
218
|
+
Object: (0, import_language.continuedIndent)({ except: /^\s*\}/ }),
|
|
219
|
+
Sequence: (0, import_language.continuedIndent)({ except: /^\s*\)/ })
|
|
220
|
+
}),
|
|
221
|
+
import_language.foldNodeProp.add({
|
|
222
|
+
Object: import_language.foldInside,
|
|
223
|
+
Sequence: import_language.foldInside
|
|
224
|
+
})
|
|
225
|
+
];
|
|
226
|
+
var styxLanguage = import_language.LRLanguage.define({
|
|
227
|
+
name: "styx",
|
|
228
|
+
parser: parser.configure({ props: baseProps }),
|
|
229
|
+
languageData: {
|
|
230
|
+
commentTokens: { line: "//" },
|
|
231
|
+
closeBrackets: { brackets: ["(", "{", '"'] }
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
function createStyxLanguage(nestedLanguages) {
|
|
235
|
+
if (nestedLanguages.length === 0) {
|
|
236
|
+
return styxLanguage;
|
|
237
|
+
}
|
|
238
|
+
const mixedParser = parser.configure({
|
|
239
|
+
props: baseProps,
|
|
240
|
+
wrap: createMixedParser(nestedLanguages)
|
|
241
|
+
});
|
|
242
|
+
return import_language.LRLanguage.define({
|
|
243
|
+
name: "styx",
|
|
244
|
+
parser: mixedParser,
|
|
245
|
+
languageData: {
|
|
246
|
+
commentTokens: { line: "//" },
|
|
247
|
+
closeBrackets: { brackets: ["(", "{", '"'] }
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
var builtinTags = [
|
|
252
|
+
"@string",
|
|
253
|
+
"@int",
|
|
254
|
+
"@float",
|
|
255
|
+
"@bool",
|
|
256
|
+
"@null",
|
|
257
|
+
"@object",
|
|
258
|
+
"@array",
|
|
259
|
+
"@optional",
|
|
260
|
+
"@required",
|
|
261
|
+
"@default",
|
|
262
|
+
"@enum",
|
|
263
|
+
"@pattern",
|
|
264
|
+
"@min",
|
|
265
|
+
"@max",
|
|
266
|
+
"@minLength",
|
|
267
|
+
"@maxLength"
|
|
268
|
+
].map((label) => ({ label, type: "keyword" }));
|
|
269
|
+
var styxCompletion = styxLanguage.data.of({
|
|
270
|
+
autocomplete: (0, import_autocomplete.completeFromList)(builtinTags)
|
|
271
|
+
});
|
|
272
|
+
function styx(config = {}) {
|
|
273
|
+
const nestedLanguages = config.nestedLanguages || [];
|
|
274
|
+
const lang = createStyxLanguage(nestedLanguages);
|
|
275
|
+
const nestedSupports = nestedLanguages.flatMap((n) => n.language.support);
|
|
276
|
+
return new import_language.LanguageSupport(lang, [styxCompletion, styxFoldService, ...nestedSupports]);
|
|
277
|
+
}
|
|
278
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
279
|
+
0 && (module.exports = {
|
|
280
|
+
parser,
|
|
281
|
+
styx,
|
|
282
|
+
styxLanguage
|
|
283
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { LanguageSupport, LRLanguage } from '@codemirror/language';
|
|
2
|
+
import { LRParser } from '@lezer/lr';
|
|
3
|
+
|
|
4
|
+
declare const parser: LRParser;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for nested languages in heredocs.
|
|
8
|
+
* Maps language hints (e.g., "sql", "json") to CodeMirror LanguageSupport objects.
|
|
9
|
+
*/
|
|
10
|
+
interface NestedLanguage {
|
|
11
|
+
/** Language hint as it appears after comma in heredoc (e.g., "sql" in <<SQL,sql) */
|
|
12
|
+
tag: string;
|
|
13
|
+
/** The CodeMirror LanguageSupport to use for parsing */
|
|
14
|
+
language: LanguageSupport;
|
|
15
|
+
}
|
|
16
|
+
declare const styxLanguage: LRLanguage;
|
|
17
|
+
/**
|
|
18
|
+
* Configuration options for Styx language support.
|
|
19
|
+
*/
|
|
20
|
+
interface StyxConfig {
|
|
21
|
+
/**
|
|
22
|
+
* Nested languages for heredoc content.
|
|
23
|
+
* Maps language hints to CodeMirror Language objects.
|
|
24
|
+
*
|
|
25
|
+
* Example:
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { sql } from "@codemirror/lang-sql";
|
|
28
|
+
*
|
|
29
|
+
* styx({
|
|
30
|
+
* nestedLanguages: [
|
|
31
|
+
* { tag: "sql", language: sql() }
|
|
32
|
+
* ]
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
nestedLanguages?: NestedLanguage[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Styx language support for CodeMirror 6.
|
|
40
|
+
*
|
|
41
|
+
* Usage:
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { styx } from "@bearcove/codemirror-lang-styx";
|
|
44
|
+
* import { EditorView, basicSetup } from "codemirror";
|
|
45
|
+
*
|
|
46
|
+
* new EditorView({
|
|
47
|
+
* extensions: [basicSetup, styx()],
|
|
48
|
+
* parent: document.body,
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* With nested language support:
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { sql } from "@codemirror/lang-sql";
|
|
55
|
+
*
|
|
56
|
+
* new EditorView({
|
|
57
|
+
* extensions: [basicSetup, styx({ nestedLanguages: [{ tag: "sql", language: sql() }] })],
|
|
58
|
+
* parent: document.body,
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function styx(config?: StyxConfig): LanguageSupport;
|
|
63
|
+
|
|
64
|
+
export { type NestedLanguage, type StyxConfig, parser, styx, styxLanguage };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { LanguageSupport, LRLanguage } from '@codemirror/language';
|
|
2
|
+
import { LRParser } from '@lezer/lr';
|
|
3
|
+
|
|
4
|
+
declare const parser: LRParser;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for nested languages in heredocs.
|
|
8
|
+
* Maps language hints (e.g., "sql", "json") to CodeMirror LanguageSupport objects.
|
|
9
|
+
*/
|
|
10
|
+
interface NestedLanguage {
|
|
11
|
+
/** Language hint as it appears after comma in heredoc (e.g., "sql" in <<SQL,sql) */
|
|
12
|
+
tag: string;
|
|
13
|
+
/** The CodeMirror LanguageSupport to use for parsing */
|
|
14
|
+
language: LanguageSupport;
|
|
15
|
+
}
|
|
16
|
+
declare const styxLanguage: LRLanguage;
|
|
17
|
+
/**
|
|
18
|
+
* Configuration options for Styx language support.
|
|
19
|
+
*/
|
|
20
|
+
interface StyxConfig {
|
|
21
|
+
/**
|
|
22
|
+
* Nested languages for heredoc content.
|
|
23
|
+
* Maps language hints to CodeMirror Language objects.
|
|
24
|
+
*
|
|
25
|
+
* Example:
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { sql } from "@codemirror/lang-sql";
|
|
28
|
+
*
|
|
29
|
+
* styx({
|
|
30
|
+
* nestedLanguages: [
|
|
31
|
+
* { tag: "sql", language: sql() }
|
|
32
|
+
* ]
|
|
33
|
+
* })
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
nestedLanguages?: NestedLanguage[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Styx language support for CodeMirror 6.
|
|
40
|
+
*
|
|
41
|
+
* Usage:
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { styx } from "@bearcove/codemirror-lang-styx";
|
|
44
|
+
* import { EditorView, basicSetup } from "codemirror";
|
|
45
|
+
*
|
|
46
|
+
* new EditorView({
|
|
47
|
+
* extensions: [basicSetup, styx()],
|
|
48
|
+
* parent: document.body,
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* With nested language support:
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { sql } from "@codemirror/lang-sql";
|
|
55
|
+
*
|
|
56
|
+
* new EditorView({
|
|
57
|
+
* extensions: [basicSetup, styx({ nestedLanguages: [{ tag: "sql", language: sql() }] })],
|
|
58
|
+
* parent: document.body,
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
declare function styx(config?: StyxConfig): LanguageSupport;
|
|
63
|
+
|
|
64
|
+
export { type NestedLanguage, type StyxConfig, parser, styx, styxLanguage };
|