@marko/language-tools 2.5.63 → 2.6.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/dist/extractors/css-module/index.d.ts +19 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +297 -11
- package/dist/index.mjs +294 -10
- package/dist/parser.d.ts +2 -2
- package/dist/processors/css-module.d.ts +15 -0
- package/dist/processors/index.d.ts +6 -2
- package/dist/processors/marko.d.ts +1 -1
- package/dist/util/extractor.d.ts +15 -4
- package/dist/util/find-style-selectors.d.ts +14 -0
- package/package.json +5 -5
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Range } from "../../parser";
|
|
2
|
+
import { type Extracted, Extractor } from "../../util/extractor";
|
|
3
|
+
export interface ExtractCSSModuleOptions {
|
|
4
|
+
code: string;
|
|
5
|
+
fileName: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Produce a virtual TypeScript module typing a CSS module's default export as
|
|
9
|
+
* an object of its class/id names. The type is exported directly (not via a
|
|
10
|
+
* named `const`) so no internal binding name leaks into hover/go-to-definition,
|
|
11
|
+
* and each name is mapped back to every selector it was defined at.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractCSSModule(opts: ExtractCSSModuleOptions): Extracted;
|
|
14
|
+
/**
|
|
15
|
+
* Write an object type whose properties are the given CSS module class/id
|
|
16
|
+
* names, each source-mapped to the selector(s) it was defined at. Shared by the
|
|
17
|
+
* standalone `.module.css` extractor and the embedded `<style/var>` extractor.
|
|
18
|
+
*/
|
|
19
|
+
export declare function writeStyleModuleType(extractor: Extractor, selectors: Map<string, Range[]>): void;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
Project: () => project_exports,
|
|
36
36
|
ScriptLang: () => ScriptLang,
|
|
37
37
|
UNFINISHED: () => UNFINISHED,
|
|
38
|
+
extractCSSModule: () => extractCSSModule,
|
|
38
39
|
extractHTML: () => extractHTML,
|
|
39
40
|
extractScript: () => extractScript,
|
|
40
41
|
extractStyle: () => extractStyle,
|
|
@@ -45,7 +46,8 @@ __export(index_exports, {
|
|
|
45
46
|
isControlFlowTag: () => isControlFlowTag,
|
|
46
47
|
isDefinitionFile: () => isDefinitionFile,
|
|
47
48
|
normalizePath: () => normalizePath,
|
|
48
|
-
parse: () => parse
|
|
49
|
+
parse: () => parse,
|
|
50
|
+
writeStyleModuleType: () => writeStyleModuleType
|
|
49
51
|
});
|
|
50
52
|
module.exports = __toCommonJS(index_exports);
|
|
51
53
|
|
|
@@ -1087,6 +1089,187 @@ function pushUniqueRange(ranges, start, end) {
|
|
|
1087
1089
|
ranges.push({ start, end });
|
|
1088
1090
|
}
|
|
1089
1091
|
|
|
1092
|
+
// src/util/find-style-selectors.ts
|
|
1093
|
+
function findStyleSelectors(code, offset = 0) {
|
|
1094
|
+
const result = /* @__PURE__ */ new Map();
|
|
1095
|
+
const pending = [];
|
|
1096
|
+
const braceStack = [];
|
|
1097
|
+
const parenStack = [];
|
|
1098
|
+
let bareGlobal = false;
|
|
1099
|
+
let pendingScope = null;
|
|
1100
|
+
const len = code.length;
|
|
1101
|
+
let i = 0;
|
|
1102
|
+
const blockGlobal = () => braceStack.length ? braceStack[braceStack.length - 1] : false;
|
|
1103
|
+
while (i < len) {
|
|
1104
|
+
const ch = code[i];
|
|
1105
|
+
const next = code[i + 1];
|
|
1106
|
+
if (ch === "/" && next === "*") {
|
|
1107
|
+
i += 2;
|
|
1108
|
+
while (i < len && !(code[i] === "*" && code[i + 1] === "/")) i++;
|
|
1109
|
+
i += 2;
|
|
1110
|
+
} else if (ch === "/" && next === "/") {
|
|
1111
|
+
i += 2;
|
|
1112
|
+
while (i < len && code[i] !== "\n") i++;
|
|
1113
|
+
} else if (ch === '"' || ch === "'") {
|
|
1114
|
+
i = skipString(code, i);
|
|
1115
|
+
} else if (isInterpolationStart(ch) && next === "{") {
|
|
1116
|
+
i = skipBalanced(code, i + 1);
|
|
1117
|
+
} else if (ch === ":") {
|
|
1118
|
+
let end = i + 1;
|
|
1119
|
+
while (end < len && isNameChar(code[end])) end++;
|
|
1120
|
+
const pseudo = code.slice(i + 1, end).toLowerCase();
|
|
1121
|
+
if (pseudo === "global" || pseudo === "local") {
|
|
1122
|
+
const isGlobal = pseudo === "global";
|
|
1123
|
+
if (code[end] === "(") {
|
|
1124
|
+
pendingScope = isGlobal;
|
|
1125
|
+
} else {
|
|
1126
|
+
let j = end;
|
|
1127
|
+
while (j < len && isWhitespace(code[j])) j++;
|
|
1128
|
+
if (code[j] === "{") {
|
|
1129
|
+
pendingScope = isGlobal;
|
|
1130
|
+
} else {
|
|
1131
|
+
bareGlobal = isGlobal;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
i = end;
|
|
1136
|
+
} else if (ch === "(") {
|
|
1137
|
+
parenStack.push(
|
|
1138
|
+
pendingScope ?? (parenStack.length ? parenStack[parenStack.length - 1] : bareGlobal)
|
|
1139
|
+
);
|
|
1140
|
+
pendingScope = null;
|
|
1141
|
+
i++;
|
|
1142
|
+
} else if (ch === ")") {
|
|
1143
|
+
parenStack.pop();
|
|
1144
|
+
i++;
|
|
1145
|
+
} else if (ch === "." || ch === "#") {
|
|
1146
|
+
const start = i + 1;
|
|
1147
|
+
if (isNameStart(code[start])) {
|
|
1148
|
+
let end = start + 1;
|
|
1149
|
+
while (end < len && isNameChar(code[end])) end++;
|
|
1150
|
+
if (!(isInterpolationStart(code[end]) && code[end + 1] === "{")) {
|
|
1151
|
+
const global = parenStack.length ? parenStack[parenStack.length - 1] : bareGlobal;
|
|
1152
|
+
if (!global) pending.push({ start, end });
|
|
1153
|
+
}
|
|
1154
|
+
i = end;
|
|
1155
|
+
} else {
|
|
1156
|
+
i++;
|
|
1157
|
+
}
|
|
1158
|
+
} else if (ch === "{") {
|
|
1159
|
+
for (const range of pending) {
|
|
1160
|
+
const name = code.slice(range.start, range.end);
|
|
1161
|
+
const offsetRange = {
|
|
1162
|
+
start: range.start + offset,
|
|
1163
|
+
end: range.end + offset
|
|
1164
|
+
};
|
|
1165
|
+
const ranges = result.get(name);
|
|
1166
|
+
if (ranges) {
|
|
1167
|
+
ranges.push(offsetRange);
|
|
1168
|
+
} else {
|
|
1169
|
+
result.set(name, [offsetRange]);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
pending.length = 0;
|
|
1173
|
+
braceStack.push(pendingScope ?? blockGlobal());
|
|
1174
|
+
pendingScope = null;
|
|
1175
|
+
parenStack.length = 0;
|
|
1176
|
+
bareGlobal = blockGlobal();
|
|
1177
|
+
i++;
|
|
1178
|
+
} else if (ch === "}") {
|
|
1179
|
+
pending.length = 0;
|
|
1180
|
+
braceStack.pop();
|
|
1181
|
+
parenStack.length = 0;
|
|
1182
|
+
bareGlobal = blockGlobal();
|
|
1183
|
+
i++;
|
|
1184
|
+
} else if (ch === ";") {
|
|
1185
|
+
pending.length = 0;
|
|
1186
|
+
parenStack.length = 0;
|
|
1187
|
+
bareGlobal = blockGlobal();
|
|
1188
|
+
i++;
|
|
1189
|
+
} else if (ch === ",") {
|
|
1190
|
+
bareGlobal = blockGlobal();
|
|
1191
|
+
i++;
|
|
1192
|
+
} else {
|
|
1193
|
+
i++;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
return result;
|
|
1197
|
+
}
|
|
1198
|
+
function skipString(code, start) {
|
|
1199
|
+
const quote = code[start];
|
|
1200
|
+
const len = code.length;
|
|
1201
|
+
let i = start + 1;
|
|
1202
|
+
while (i < len) {
|
|
1203
|
+
const ch = code[i];
|
|
1204
|
+
if (ch === "\\") {
|
|
1205
|
+
i += 2;
|
|
1206
|
+
} else if (ch === quote) {
|
|
1207
|
+
return i + 1;
|
|
1208
|
+
} else {
|
|
1209
|
+
i++;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
return i;
|
|
1213
|
+
}
|
|
1214
|
+
function skipBalanced(code, openBrace) {
|
|
1215
|
+
const len = code.length;
|
|
1216
|
+
let depth = 0;
|
|
1217
|
+
let i = openBrace;
|
|
1218
|
+
while (i < len) {
|
|
1219
|
+
const ch = code[i];
|
|
1220
|
+
if (ch === "{") {
|
|
1221
|
+
depth++;
|
|
1222
|
+
} else if (ch === "}") {
|
|
1223
|
+
if (--depth === 0) return i + 1;
|
|
1224
|
+
}
|
|
1225
|
+
i++;
|
|
1226
|
+
}
|
|
1227
|
+
return i;
|
|
1228
|
+
}
|
|
1229
|
+
function isNameStart(ch) {
|
|
1230
|
+
if (ch === void 0) return false;
|
|
1231
|
+
const code = ch.charCodeAt(0);
|
|
1232
|
+
return code >= 97 && code <= 122 || // a-z
|
|
1233
|
+
code >= 65 && code <= 90 || // A-Z
|
|
1234
|
+
ch === "_" || ch === "-" || code >= 128;
|
|
1235
|
+
}
|
|
1236
|
+
function isNameChar(ch) {
|
|
1237
|
+
const code = ch.charCodeAt(0);
|
|
1238
|
+
return code >= 48 && code <= 57 || isNameStart(ch);
|
|
1239
|
+
}
|
|
1240
|
+
function isInterpolationStart(ch) {
|
|
1241
|
+
return ch === "#" || ch === "@" || ch === "$";
|
|
1242
|
+
}
|
|
1243
|
+
function isWhitespace(ch) {
|
|
1244
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/extractors/css-module/index.ts
|
|
1248
|
+
function extractCSSModule(opts) {
|
|
1249
|
+
const { code, fileName } = opts;
|
|
1250
|
+
const extractor = new Extractor(createSource(code, fileName));
|
|
1251
|
+
extractor.write("export default {} as unknown as ");
|
|
1252
|
+
writeStyleModuleType(extractor, findStyleSelectors(code));
|
|
1253
|
+
extractor.write(";\n");
|
|
1254
|
+
return extractor.end();
|
|
1255
|
+
}
|
|
1256
|
+
function writeStyleModuleType(extractor, selectors) {
|
|
1257
|
+
extractor.write("{");
|
|
1258
|
+
for (const ranges of selectors.values()) {
|
|
1259
|
+
extractor.write(' "').copy(ranges).write('": string;');
|
|
1260
|
+
}
|
|
1261
|
+
extractor.write(" }");
|
|
1262
|
+
}
|
|
1263
|
+
function createSource(code, fileName) {
|
|
1264
|
+
const lines = (0, import_htmljs_parser2.getLines)(code);
|
|
1265
|
+
return {
|
|
1266
|
+
code,
|
|
1267
|
+
filename: normalizePath(fileName),
|
|
1268
|
+
positionAt: (offset) => (0, import_htmljs_parser2.getPosition)(lines, offset),
|
|
1269
|
+
locationAt: (range) => (0, import_htmljs_parser2.getLocation)(lines, range.start, range.end)
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1090
1273
|
// src/extractors/html/keywords.ts
|
|
1091
1274
|
var builtinTagsRegex = (
|
|
1092
1275
|
/* cspell:disable-next-line */
|
|
@@ -2950,7 +3133,11 @@ constructor(_) {}
|
|
|
2950
3133
|
if (tag.var) {
|
|
2951
3134
|
this.#closeBrackets[this.#closeBrackets.length - 1]++;
|
|
2952
3135
|
this.#extractor.write("{const ");
|
|
2953
|
-
if (
|
|
3136
|
+
if (tagName === "style") {
|
|
3137
|
+
this.#extractor.copy(tag.var.value).write(" = ");
|
|
3138
|
+
this.#writeStyleModuleVar(tag);
|
|
3139
|
+
this.#extractor.write(";\n");
|
|
3140
|
+
} else if (isHTML) {
|
|
2954
3141
|
this.#extractor.copy(tag.var.value).write(` = ${varShared("el")}(${JSON.stringify(def.name)});
|
|
2955
3142
|
`);
|
|
2956
3143
|
} else {
|
|
@@ -2990,6 +3177,40 @@ constructor(_) {}
|
|
|
2990
3177
|
}
|
|
2991
3178
|
}
|
|
2992
3179
|
}
|
|
3180
|
+
/** Types a `<style/foo>` CSS module var as an object of its class/id names. */
|
|
3181
|
+
#writeStyleModuleVar(tag) {
|
|
3182
|
+
const selectors = this.#getStyleModuleSelectors(tag);
|
|
3183
|
+
if (this.#scriptLang === "ts" /* ts */) {
|
|
3184
|
+
this.#extractor.write(`${varShared("any")} as `);
|
|
3185
|
+
writeStyleModuleType(this.#extractor, selectors);
|
|
3186
|
+
} else {
|
|
3187
|
+
this.#extractor.write("/** @type {");
|
|
3188
|
+
writeStyleModuleType(this.#extractor, selectors);
|
|
3189
|
+
this.#extractor.write(`} */(${varShared("any")})`);
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
#getStyleModuleSelectors(tag) {
|
|
3193
|
+
const result = /* @__PURE__ */ new Map();
|
|
3194
|
+
if (tag.body) {
|
|
3195
|
+
for (const child of tag.body) {
|
|
3196
|
+
if (child.type === 17 /* Text */) {
|
|
3197
|
+
const found = findStyleSelectors(
|
|
3198
|
+
this.#code.slice(child.start, child.end),
|
|
3199
|
+
child.start
|
|
3200
|
+
);
|
|
3201
|
+
for (const [name, ranges] of found) {
|
|
3202
|
+
const existing = result.get(name);
|
|
3203
|
+
if (existing) {
|
|
3204
|
+
existing.push(...ranges);
|
|
3205
|
+
} else {
|
|
3206
|
+
result.set(name, ranges);
|
|
3207
|
+
}
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
return result;
|
|
3213
|
+
}
|
|
2993
3214
|
#endChildren() {
|
|
2994
3215
|
const pendingBrackets = this.#closeBrackets.pop();
|
|
2995
3216
|
if (pendingBrackets) {
|
|
@@ -3973,7 +4194,9 @@ var processors_exports = {};
|
|
|
3973
4194
|
__export(processors_exports, {
|
|
3974
4195
|
create: () => create,
|
|
3975
4196
|
extensions: () => extensions,
|
|
3976
|
-
|
|
4197
|
+
getProcessorExtension: () => getProcessorExtension,
|
|
4198
|
+
has: () => has,
|
|
4199
|
+
isCSSModule: () => isCSSModule
|
|
3977
4200
|
});
|
|
3978
4201
|
|
|
3979
4202
|
// src/util/get-ext.ts
|
|
@@ -3982,6 +4205,34 @@ function getExt(fileName) {
|
|
|
3982
4205
|
if (extIndex !== -1) return fileName.slice(extIndex);
|
|
3983
4206
|
}
|
|
3984
4207
|
|
|
4208
|
+
// src/processors/css-module.ts
|
|
4209
|
+
var css_module_default = {
|
|
4210
|
+
extensions: [".module.css", ".module.scss", ".module.less"],
|
|
4211
|
+
create({ ts }) {
|
|
4212
|
+
return {
|
|
4213
|
+
getScriptExtension() {
|
|
4214
|
+
return ts.Extension.Ts;
|
|
4215
|
+
},
|
|
4216
|
+
getScriptKind() {
|
|
4217
|
+
return ts.ScriptKind.TS;
|
|
4218
|
+
},
|
|
4219
|
+
extract(fileName, code) {
|
|
4220
|
+
return extractCSSModule({ code, fileName });
|
|
4221
|
+
},
|
|
4222
|
+
print({ extracted }) {
|
|
4223
|
+
return { code: extracted.toString() };
|
|
4224
|
+
},
|
|
4225
|
+
printTypes({ sourceFile, printer }) {
|
|
4226
|
+
let code = "";
|
|
4227
|
+
for (const statement of sourceFile.statements) {
|
|
4228
|
+
code += printer.printNode(ts.EmitHint.Unspecified, statement, sourceFile) + "\n";
|
|
4229
|
+
}
|
|
4230
|
+
return { code };
|
|
4231
|
+
}
|
|
4232
|
+
};
|
|
4233
|
+
}
|
|
4234
|
+
};
|
|
4235
|
+
|
|
3985
4236
|
// src/processors/marko.ts
|
|
3986
4237
|
var import_path4 = __toESM(require("path"));
|
|
3987
4238
|
|
|
@@ -4225,7 +4476,7 @@ function interopDefault(mod) {
|
|
|
4225
4476
|
var isRemapExtensionReg = /\.ts$/;
|
|
4226
4477
|
var skipRemapExtensionsReg = /\.(?:[cm]?jsx?|json|marko|css|less|sass|scss|styl|stylus|pcss|postcss|sss|a?png|jpe?g|jfif|pipeg|pjp|gif|svg|ico|web[pm]|avif|mp4|ogg|mp3|wav|flac|aac|opus|woff2?|eot|[ot]tf|webmanifest|pdf|txt)$/;
|
|
4227
4478
|
var marko_default = {
|
|
4228
|
-
|
|
4479
|
+
extensions: [".marko"],
|
|
4229
4480
|
create({ ts, host, configFile }) {
|
|
4230
4481
|
const currentDirectory = host.getCurrentDirectory ? host.getCurrentDirectory() : ts.sys.getCurrentDirectory();
|
|
4231
4482
|
const defaultScriptLang = configFile && /tsconfig/.test(configFile) ? "ts" /* ts */ : "js" /* js */;
|
|
@@ -4422,15 +4673,48 @@ function castType(type) {
|
|
|
4422
4673
|
}
|
|
4423
4674
|
|
|
4424
4675
|
// src/processors/index.ts
|
|
4425
|
-
var
|
|
4676
|
+
var configs = [marko_default, css_module_default];
|
|
4677
|
+
var simpleExtensions = /* @__PURE__ */ new Set();
|
|
4678
|
+
var compoundExtensions = [];
|
|
4679
|
+
for (const config of configs) {
|
|
4680
|
+
for (const extension of config.extensions) {
|
|
4681
|
+
if (extension.indexOf(".", 1) === -1) {
|
|
4682
|
+
simpleExtensions.add(extension);
|
|
4683
|
+
} else {
|
|
4684
|
+
compoundExtensions.push(extension);
|
|
4685
|
+
}
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
var cssModuleExtensions = new Set(css_module_default.extensions);
|
|
4689
|
+
var extensions = configs.flatMap(
|
|
4690
|
+
(config) => config.extensions
|
|
4691
|
+
);
|
|
4426
4692
|
function create(options) {
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4693
|
+
const result = {};
|
|
4694
|
+
for (const config of configs) {
|
|
4695
|
+
const processor = config.create(options);
|
|
4696
|
+
for (const extension of config.extensions) {
|
|
4697
|
+
result[extension] = processor;
|
|
4698
|
+
}
|
|
4699
|
+
}
|
|
4700
|
+
return result;
|
|
4430
4701
|
}
|
|
4431
|
-
function
|
|
4702
|
+
function getProcessorExtension(fileName) {
|
|
4432
4703
|
const ext = getExt(fileName);
|
|
4433
|
-
|
|
4704
|
+
if (ext && simpleExtensions.has(ext)) return ext;
|
|
4705
|
+
if (compoundExtensions.length) {
|
|
4706
|
+
const lower = fileName.toLowerCase();
|
|
4707
|
+
for (const compound of compoundExtensions) {
|
|
4708
|
+
if (lower.endsWith(compound)) return compound;
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
function has(fileName) {
|
|
4713
|
+
return getProcessorExtension(fileName) !== void 0;
|
|
4714
|
+
}
|
|
4715
|
+
function isCSSModule(fileName) {
|
|
4716
|
+
const ext = getProcessorExtension(fileName);
|
|
4717
|
+
return ext !== void 0 && cssModuleExtensions.has(ext);
|
|
4434
4718
|
}
|
|
4435
4719
|
|
|
4436
4720
|
// src/util/is-definition-file.ts
|
|
@@ -4444,6 +4728,7 @@ function isDefinitionFile(fileName) {
|
|
|
4444
4728
|
Project,
|
|
4445
4729
|
ScriptLang,
|
|
4446
4730
|
UNFINISHED,
|
|
4731
|
+
extractCSSModule,
|
|
4447
4732
|
extractHTML,
|
|
4448
4733
|
extractScript,
|
|
4449
4734
|
extractStyle,
|
|
@@ -4454,5 +4739,6 @@ function isDefinitionFile(fileName) {
|
|
|
4454
4739
|
isControlFlowTag,
|
|
4455
4740
|
isDefinitionFile,
|
|
4456
4741
|
normalizePath,
|
|
4457
|
-
parse
|
|
4742
|
+
parse,
|
|
4743
|
+
writeStyleModuleType
|
|
4458
4744
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1046,6 +1046,187 @@ function pushUniqueRange(ranges, start, end) {
|
|
|
1046
1046
|
ranges.push({ start, end });
|
|
1047
1047
|
}
|
|
1048
1048
|
|
|
1049
|
+
// src/util/find-style-selectors.ts
|
|
1050
|
+
function findStyleSelectors(code, offset = 0) {
|
|
1051
|
+
const result = /* @__PURE__ */ new Map();
|
|
1052
|
+
const pending = [];
|
|
1053
|
+
const braceStack = [];
|
|
1054
|
+
const parenStack = [];
|
|
1055
|
+
let bareGlobal = false;
|
|
1056
|
+
let pendingScope = null;
|
|
1057
|
+
const len = code.length;
|
|
1058
|
+
let i = 0;
|
|
1059
|
+
const blockGlobal = () => braceStack.length ? braceStack[braceStack.length - 1] : false;
|
|
1060
|
+
while (i < len) {
|
|
1061
|
+
const ch = code[i];
|
|
1062
|
+
const next = code[i + 1];
|
|
1063
|
+
if (ch === "/" && next === "*") {
|
|
1064
|
+
i += 2;
|
|
1065
|
+
while (i < len && !(code[i] === "*" && code[i + 1] === "/")) i++;
|
|
1066
|
+
i += 2;
|
|
1067
|
+
} else if (ch === "/" && next === "/") {
|
|
1068
|
+
i += 2;
|
|
1069
|
+
while (i < len && code[i] !== "\n") i++;
|
|
1070
|
+
} else if (ch === '"' || ch === "'") {
|
|
1071
|
+
i = skipString(code, i);
|
|
1072
|
+
} else if (isInterpolationStart(ch) && next === "{") {
|
|
1073
|
+
i = skipBalanced(code, i + 1);
|
|
1074
|
+
} else if (ch === ":") {
|
|
1075
|
+
let end = i + 1;
|
|
1076
|
+
while (end < len && isNameChar(code[end])) end++;
|
|
1077
|
+
const pseudo = code.slice(i + 1, end).toLowerCase();
|
|
1078
|
+
if (pseudo === "global" || pseudo === "local") {
|
|
1079
|
+
const isGlobal = pseudo === "global";
|
|
1080
|
+
if (code[end] === "(") {
|
|
1081
|
+
pendingScope = isGlobal;
|
|
1082
|
+
} else {
|
|
1083
|
+
let j = end;
|
|
1084
|
+
while (j < len && isWhitespace(code[j])) j++;
|
|
1085
|
+
if (code[j] === "{") {
|
|
1086
|
+
pendingScope = isGlobal;
|
|
1087
|
+
} else {
|
|
1088
|
+
bareGlobal = isGlobal;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
i = end;
|
|
1093
|
+
} else if (ch === "(") {
|
|
1094
|
+
parenStack.push(
|
|
1095
|
+
pendingScope ?? (parenStack.length ? parenStack[parenStack.length - 1] : bareGlobal)
|
|
1096
|
+
);
|
|
1097
|
+
pendingScope = null;
|
|
1098
|
+
i++;
|
|
1099
|
+
} else if (ch === ")") {
|
|
1100
|
+
parenStack.pop();
|
|
1101
|
+
i++;
|
|
1102
|
+
} else if (ch === "." || ch === "#") {
|
|
1103
|
+
const start = i + 1;
|
|
1104
|
+
if (isNameStart(code[start])) {
|
|
1105
|
+
let end = start + 1;
|
|
1106
|
+
while (end < len && isNameChar(code[end])) end++;
|
|
1107
|
+
if (!(isInterpolationStart(code[end]) && code[end + 1] === "{")) {
|
|
1108
|
+
const global = parenStack.length ? parenStack[parenStack.length - 1] : bareGlobal;
|
|
1109
|
+
if (!global) pending.push({ start, end });
|
|
1110
|
+
}
|
|
1111
|
+
i = end;
|
|
1112
|
+
} else {
|
|
1113
|
+
i++;
|
|
1114
|
+
}
|
|
1115
|
+
} else if (ch === "{") {
|
|
1116
|
+
for (const range of pending) {
|
|
1117
|
+
const name = code.slice(range.start, range.end);
|
|
1118
|
+
const offsetRange = {
|
|
1119
|
+
start: range.start + offset,
|
|
1120
|
+
end: range.end + offset
|
|
1121
|
+
};
|
|
1122
|
+
const ranges = result.get(name);
|
|
1123
|
+
if (ranges) {
|
|
1124
|
+
ranges.push(offsetRange);
|
|
1125
|
+
} else {
|
|
1126
|
+
result.set(name, [offsetRange]);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
pending.length = 0;
|
|
1130
|
+
braceStack.push(pendingScope ?? blockGlobal());
|
|
1131
|
+
pendingScope = null;
|
|
1132
|
+
parenStack.length = 0;
|
|
1133
|
+
bareGlobal = blockGlobal();
|
|
1134
|
+
i++;
|
|
1135
|
+
} else if (ch === "}") {
|
|
1136
|
+
pending.length = 0;
|
|
1137
|
+
braceStack.pop();
|
|
1138
|
+
parenStack.length = 0;
|
|
1139
|
+
bareGlobal = blockGlobal();
|
|
1140
|
+
i++;
|
|
1141
|
+
} else if (ch === ";") {
|
|
1142
|
+
pending.length = 0;
|
|
1143
|
+
parenStack.length = 0;
|
|
1144
|
+
bareGlobal = blockGlobal();
|
|
1145
|
+
i++;
|
|
1146
|
+
} else if (ch === ",") {
|
|
1147
|
+
bareGlobal = blockGlobal();
|
|
1148
|
+
i++;
|
|
1149
|
+
} else {
|
|
1150
|
+
i++;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return result;
|
|
1154
|
+
}
|
|
1155
|
+
function skipString(code, start) {
|
|
1156
|
+
const quote = code[start];
|
|
1157
|
+
const len = code.length;
|
|
1158
|
+
let i = start + 1;
|
|
1159
|
+
while (i < len) {
|
|
1160
|
+
const ch = code[i];
|
|
1161
|
+
if (ch === "\\") {
|
|
1162
|
+
i += 2;
|
|
1163
|
+
} else if (ch === quote) {
|
|
1164
|
+
return i + 1;
|
|
1165
|
+
} else {
|
|
1166
|
+
i++;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
return i;
|
|
1170
|
+
}
|
|
1171
|
+
function skipBalanced(code, openBrace) {
|
|
1172
|
+
const len = code.length;
|
|
1173
|
+
let depth = 0;
|
|
1174
|
+
let i = openBrace;
|
|
1175
|
+
while (i < len) {
|
|
1176
|
+
const ch = code[i];
|
|
1177
|
+
if (ch === "{") {
|
|
1178
|
+
depth++;
|
|
1179
|
+
} else if (ch === "}") {
|
|
1180
|
+
if (--depth === 0) return i + 1;
|
|
1181
|
+
}
|
|
1182
|
+
i++;
|
|
1183
|
+
}
|
|
1184
|
+
return i;
|
|
1185
|
+
}
|
|
1186
|
+
function isNameStart(ch) {
|
|
1187
|
+
if (ch === void 0) return false;
|
|
1188
|
+
const code = ch.charCodeAt(0);
|
|
1189
|
+
return code >= 97 && code <= 122 || // a-z
|
|
1190
|
+
code >= 65 && code <= 90 || // A-Z
|
|
1191
|
+
ch === "_" || ch === "-" || code >= 128;
|
|
1192
|
+
}
|
|
1193
|
+
function isNameChar(ch) {
|
|
1194
|
+
const code = ch.charCodeAt(0);
|
|
1195
|
+
return code >= 48 && code <= 57 || isNameStart(ch);
|
|
1196
|
+
}
|
|
1197
|
+
function isInterpolationStart(ch) {
|
|
1198
|
+
return ch === "#" || ch === "@" || ch === "$";
|
|
1199
|
+
}
|
|
1200
|
+
function isWhitespace(ch) {
|
|
1201
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/extractors/css-module/index.ts
|
|
1205
|
+
function extractCSSModule(opts) {
|
|
1206
|
+
const { code, fileName } = opts;
|
|
1207
|
+
const extractor = new Extractor(createSource(code, fileName));
|
|
1208
|
+
extractor.write("export default {} as unknown as ");
|
|
1209
|
+
writeStyleModuleType(extractor, findStyleSelectors(code));
|
|
1210
|
+
extractor.write(";\n");
|
|
1211
|
+
return extractor.end();
|
|
1212
|
+
}
|
|
1213
|
+
function writeStyleModuleType(extractor, selectors) {
|
|
1214
|
+
extractor.write("{");
|
|
1215
|
+
for (const ranges of selectors.values()) {
|
|
1216
|
+
extractor.write(' "').copy(ranges).write('": string;');
|
|
1217
|
+
}
|
|
1218
|
+
extractor.write(" }");
|
|
1219
|
+
}
|
|
1220
|
+
function createSource(code, fileName) {
|
|
1221
|
+
const lines = getLines(code);
|
|
1222
|
+
return {
|
|
1223
|
+
code,
|
|
1224
|
+
filename: normalizePath(fileName),
|
|
1225
|
+
positionAt: (offset) => getPosition(lines, offset),
|
|
1226
|
+
locationAt: (range) => getLocation(lines, range.start, range.end)
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1049
1230
|
// src/extractors/html/keywords.ts
|
|
1050
1231
|
var builtinTagsRegex = (
|
|
1051
1232
|
/* cspell:disable-next-line */
|
|
@@ -2912,7 +3093,11 @@ constructor(_) {}
|
|
|
2912
3093
|
if (tag.var) {
|
|
2913
3094
|
this.#closeBrackets[this.#closeBrackets.length - 1]++;
|
|
2914
3095
|
this.#extractor.write("{const ");
|
|
2915
|
-
if (
|
|
3096
|
+
if (tagName === "style") {
|
|
3097
|
+
this.#extractor.copy(tag.var.value).write(" = ");
|
|
3098
|
+
this.#writeStyleModuleVar(tag);
|
|
3099
|
+
this.#extractor.write(";\n");
|
|
3100
|
+
} else if (isHTML) {
|
|
2916
3101
|
this.#extractor.copy(tag.var.value).write(` = ${varShared("el")}(${JSON.stringify(def.name)});
|
|
2917
3102
|
`);
|
|
2918
3103
|
} else {
|
|
@@ -2952,6 +3137,40 @@ constructor(_) {}
|
|
|
2952
3137
|
}
|
|
2953
3138
|
}
|
|
2954
3139
|
}
|
|
3140
|
+
/** Types a `<style/foo>` CSS module var as an object of its class/id names. */
|
|
3141
|
+
#writeStyleModuleVar(tag) {
|
|
3142
|
+
const selectors = this.#getStyleModuleSelectors(tag);
|
|
3143
|
+
if (this.#scriptLang === "ts" /* ts */) {
|
|
3144
|
+
this.#extractor.write(`${varShared("any")} as `);
|
|
3145
|
+
writeStyleModuleType(this.#extractor, selectors);
|
|
3146
|
+
} else {
|
|
3147
|
+
this.#extractor.write("/** @type {");
|
|
3148
|
+
writeStyleModuleType(this.#extractor, selectors);
|
|
3149
|
+
this.#extractor.write(`} */(${varShared("any")})`);
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
#getStyleModuleSelectors(tag) {
|
|
3153
|
+
const result = /* @__PURE__ */ new Map();
|
|
3154
|
+
if (tag.body) {
|
|
3155
|
+
for (const child of tag.body) {
|
|
3156
|
+
if (child.type === 17 /* Text */) {
|
|
3157
|
+
const found = findStyleSelectors(
|
|
3158
|
+
this.#code.slice(child.start, child.end),
|
|
3159
|
+
child.start
|
|
3160
|
+
);
|
|
3161
|
+
for (const [name, ranges] of found) {
|
|
3162
|
+
const existing = result.get(name);
|
|
3163
|
+
if (existing) {
|
|
3164
|
+
existing.push(...ranges);
|
|
3165
|
+
} else {
|
|
3166
|
+
result.set(name, ranges);
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
return result;
|
|
3173
|
+
}
|
|
2955
3174
|
#endChildren() {
|
|
2956
3175
|
const pendingBrackets = this.#closeBrackets.pop();
|
|
2957
3176
|
if (pendingBrackets) {
|
|
@@ -3935,7 +4154,9 @@ var processors_exports = {};
|
|
|
3935
4154
|
__export(processors_exports, {
|
|
3936
4155
|
create: () => create,
|
|
3937
4156
|
extensions: () => extensions,
|
|
3938
|
-
|
|
4157
|
+
getProcessorExtension: () => getProcessorExtension,
|
|
4158
|
+
has: () => has,
|
|
4159
|
+
isCSSModule: () => isCSSModule
|
|
3939
4160
|
});
|
|
3940
4161
|
|
|
3941
4162
|
// src/util/get-ext.ts
|
|
@@ -3944,6 +4165,34 @@ function getExt(fileName) {
|
|
|
3944
4165
|
if (extIndex !== -1) return fileName.slice(extIndex);
|
|
3945
4166
|
}
|
|
3946
4167
|
|
|
4168
|
+
// src/processors/css-module.ts
|
|
4169
|
+
var css_module_default = {
|
|
4170
|
+
extensions: [".module.css", ".module.scss", ".module.less"],
|
|
4171
|
+
create({ ts }) {
|
|
4172
|
+
return {
|
|
4173
|
+
getScriptExtension() {
|
|
4174
|
+
return ts.Extension.Ts;
|
|
4175
|
+
},
|
|
4176
|
+
getScriptKind() {
|
|
4177
|
+
return ts.ScriptKind.TS;
|
|
4178
|
+
},
|
|
4179
|
+
extract(fileName, code) {
|
|
4180
|
+
return extractCSSModule({ code, fileName });
|
|
4181
|
+
},
|
|
4182
|
+
print({ extracted }) {
|
|
4183
|
+
return { code: extracted.toString() };
|
|
4184
|
+
},
|
|
4185
|
+
printTypes({ sourceFile, printer }) {
|
|
4186
|
+
let code = "";
|
|
4187
|
+
for (const statement of sourceFile.statements) {
|
|
4188
|
+
code += printer.printNode(ts.EmitHint.Unspecified, statement, sourceFile) + "\n";
|
|
4189
|
+
}
|
|
4190
|
+
return { code };
|
|
4191
|
+
}
|
|
4192
|
+
};
|
|
4193
|
+
}
|
|
4194
|
+
};
|
|
4195
|
+
|
|
3947
4196
|
// src/processors/marko.ts
|
|
3948
4197
|
import path4 from "path";
|
|
3949
4198
|
|
|
@@ -4187,7 +4436,7 @@ function interopDefault(mod) {
|
|
|
4187
4436
|
var isRemapExtensionReg = /\.ts$/;
|
|
4188
4437
|
var skipRemapExtensionsReg = /\.(?:[cm]?jsx?|json|marko|css|less|sass|scss|styl|stylus|pcss|postcss|sss|a?png|jpe?g|jfif|pipeg|pjp|gif|svg|ico|web[pm]|avif|mp4|ogg|mp3|wav|flac|aac|opus|woff2?|eot|[ot]tf|webmanifest|pdf|txt)$/;
|
|
4189
4438
|
var marko_default = {
|
|
4190
|
-
|
|
4439
|
+
extensions: [".marko"],
|
|
4191
4440
|
create({ ts, host, configFile }) {
|
|
4192
4441
|
const currentDirectory = host.getCurrentDirectory ? host.getCurrentDirectory() : ts.sys.getCurrentDirectory();
|
|
4193
4442
|
const defaultScriptLang = configFile && /tsconfig/.test(configFile) ? "ts" /* ts */ : "js" /* js */;
|
|
@@ -4384,15 +4633,48 @@ function castType(type) {
|
|
|
4384
4633
|
}
|
|
4385
4634
|
|
|
4386
4635
|
// src/processors/index.ts
|
|
4387
|
-
var
|
|
4636
|
+
var configs = [marko_default, css_module_default];
|
|
4637
|
+
var simpleExtensions = /* @__PURE__ */ new Set();
|
|
4638
|
+
var compoundExtensions = [];
|
|
4639
|
+
for (const config of configs) {
|
|
4640
|
+
for (const extension of config.extensions) {
|
|
4641
|
+
if (extension.indexOf(".", 1) === -1) {
|
|
4642
|
+
simpleExtensions.add(extension);
|
|
4643
|
+
} else {
|
|
4644
|
+
compoundExtensions.push(extension);
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
var cssModuleExtensions = new Set(css_module_default.extensions);
|
|
4649
|
+
var extensions = configs.flatMap(
|
|
4650
|
+
(config) => config.extensions
|
|
4651
|
+
);
|
|
4388
4652
|
function create(options) {
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4653
|
+
const result = {};
|
|
4654
|
+
for (const config of configs) {
|
|
4655
|
+
const processor = config.create(options);
|
|
4656
|
+
for (const extension of config.extensions) {
|
|
4657
|
+
result[extension] = processor;
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
return result;
|
|
4392
4661
|
}
|
|
4393
|
-
function
|
|
4662
|
+
function getProcessorExtension(fileName) {
|
|
4394
4663
|
const ext = getExt(fileName);
|
|
4395
|
-
|
|
4664
|
+
if (ext && simpleExtensions.has(ext)) return ext;
|
|
4665
|
+
if (compoundExtensions.length) {
|
|
4666
|
+
const lower = fileName.toLowerCase();
|
|
4667
|
+
for (const compound of compoundExtensions) {
|
|
4668
|
+
if (lower.endsWith(compound)) return compound;
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4672
|
+
function has(fileName) {
|
|
4673
|
+
return getProcessorExtension(fileName) !== void 0;
|
|
4674
|
+
}
|
|
4675
|
+
function isCSSModule(fileName) {
|
|
4676
|
+
const ext = getProcessorExtension(fileName);
|
|
4677
|
+
return ext !== void 0 && cssModuleExtensions.has(ext);
|
|
4396
4678
|
}
|
|
4397
4679
|
|
|
4398
4680
|
// src/util/is-definition-file.ts
|
|
@@ -4405,6 +4687,7 @@ export {
|
|
|
4405
4687
|
project_exports as Project,
|
|
4406
4688
|
ScriptLang,
|
|
4407
4689
|
UNFINISHED,
|
|
4690
|
+
extractCSSModule,
|
|
4408
4691
|
extractHTML,
|
|
4409
4692
|
extractScript,
|
|
4410
4693
|
extractStyle,
|
|
@@ -4415,5 +4698,6 @@ export {
|
|
|
4415
4698
|
isControlFlowTag,
|
|
4416
4699
|
isDefinitionFile,
|
|
4417
4700
|
normalizePath,
|
|
4418
|
-
parse
|
|
4701
|
+
parse,
|
|
4702
|
+
writeStyleModuleType
|
|
4419
4703
|
};
|
package/dist/parser.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare namespace Node {
|
|
|
43
43
|
type AttrNode = AttrNamed | AttrSpread;
|
|
44
44
|
type ControlFlowTag = Tag & {
|
|
45
45
|
nameText: "if" | "else" | "else-if" | "for" | "while";
|
|
46
|
-
bodyType: TagType.html;
|
|
46
|
+
bodyType: typeof TagType.html;
|
|
47
47
|
};
|
|
48
48
|
type ChildNode = Tag | AttrTag | Text | Doctype | Declaration | CDATA | Placeholder | Scriptlet;
|
|
49
49
|
interface Commentable {
|
|
@@ -87,7 +87,7 @@ export declare namespace Node {
|
|
|
87
87
|
open: Range;
|
|
88
88
|
close: Range | undefined;
|
|
89
89
|
nameText: string;
|
|
90
|
-
bodyType: TagType.html;
|
|
90
|
+
bodyType: typeof TagType.html;
|
|
91
91
|
name: OpenTagName;
|
|
92
92
|
var: TagVar | undefined;
|
|
93
93
|
args: TagArgs | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
extensions: (".module.css" | ".module.scss" | ".module.less")[];
|
|
3
|
+
create({ ts }: import(".").CreateProcessorOptions): {
|
|
4
|
+
getScriptExtension(): import("typescript").Extension.Ts;
|
|
5
|
+
getScriptKind(): import("typescript").ScriptKind.TS;
|
|
6
|
+
extract(fileName: string, code: string): import("..").Extracted;
|
|
7
|
+
print({ extracted }: import(".").PrintContext): {
|
|
8
|
+
code: string;
|
|
9
|
+
};
|
|
10
|
+
printTypes({ sourceFile, printer }: import(".").PrintContext): {
|
|
11
|
+
code: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default _default;
|
|
@@ -2,7 +2,7 @@ import type ts from "typescript/lib/tsserverlibrary";
|
|
|
2
2
|
import { Extracted } from "../util/extractor";
|
|
3
3
|
export type ProcessorExtension = `.${string}`;
|
|
4
4
|
export interface ProcessorConfig {
|
|
5
|
-
|
|
5
|
+
extensions: ProcessorExtension[];
|
|
6
6
|
create(options: CreateProcessorOptions): Processor;
|
|
7
7
|
}
|
|
8
8
|
export interface CreateProcessorOptions {
|
|
@@ -32,5 +32,9 @@ export interface PrintContext {
|
|
|
32
32
|
formatSettings: Required<ts.FormatCodeSettings>;
|
|
33
33
|
}
|
|
34
34
|
export declare const extensions: ProcessorExtension[];
|
|
35
|
-
export declare function create(options: CreateProcessorOptions): Record
|
|
35
|
+
export declare function create(options: CreateProcessorOptions): Record<`.${string}`, Processor>;
|
|
36
|
+
/** Resolve a file's processor extension, including compound `.module.css`. */
|
|
37
|
+
export declare function getProcessorExtension(fileName: string): ProcessorExtension | undefined;
|
|
36
38
|
export declare function has(fileName: string): boolean;
|
|
39
|
+
/** Whether a file is a CSS module (`.module.css`, `.module.scss`, `.module.less`). */
|
|
40
|
+
export declare function isCSSModule(fileName: string): boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type ts from "typescript/lib/tsserverlibrary";
|
|
2
2
|
declare const _default: {
|
|
3
|
-
|
|
3
|
+
extensions: ".marko"[];
|
|
4
4
|
create({ ts, host, configFile }: import(".").CreateProcessorOptions): {
|
|
5
5
|
getRootNames(): string[];
|
|
6
6
|
getScriptExtension(fileName: string): ts.Extension.Ts | ts.Extension.Js;
|
package/dist/util/extractor.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import { type Location, type
|
|
1
|
+
import { type Location, type Position, type Range } from "../parser";
|
|
2
|
+
/**
|
|
3
|
+
* The minimal source an {@link Extractor} needs to maintain a source mapping.
|
|
4
|
+
* A Marko `Parsed` satisfies it, as does any other parsed source (eg a CSS
|
|
5
|
+
* module).
|
|
6
|
+
*/
|
|
7
|
+
export interface ExtractorSource {
|
|
8
|
+
code: string;
|
|
9
|
+
filename: string;
|
|
10
|
+
positionAt(offset: number): Position;
|
|
11
|
+
locationAt(range: Range): Location;
|
|
12
|
+
}
|
|
2
13
|
declare const enum Mapping {
|
|
3
14
|
full = 0,
|
|
4
15
|
alias = 1,
|
|
@@ -17,7 +28,7 @@ interface Token {
|
|
|
17
28
|
*/
|
|
18
29
|
export declare class Extractor {
|
|
19
30
|
#private;
|
|
20
|
-
constructor(parsed:
|
|
31
|
+
constructor(parsed: ExtractorSource);
|
|
21
32
|
write(str: string): this;
|
|
22
33
|
copy(range: Range | Range[] | string | false | void | undefined | null): this;
|
|
23
34
|
anchor(range: Range | false | void | undefined | null): this;
|
|
@@ -25,8 +36,8 @@ export declare class Extractor {
|
|
|
25
36
|
}
|
|
26
37
|
export declare class Extracted {
|
|
27
38
|
#private;
|
|
28
|
-
parsed:
|
|
29
|
-
constructor(parsed:
|
|
39
|
+
parsed: ExtractorSource;
|
|
40
|
+
constructor(parsed: ExtractorSource, generated: string, tokens: Token[]);
|
|
30
41
|
sourceOffsetAt(generatedOffset: number): number | undefined;
|
|
31
42
|
sourcePositionAt(generatedOffset: number): Position | undefined;
|
|
32
43
|
sourceRangeAt(generatedStart: number, generatedEnd: number): {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Range } from "../parser";
|
|
2
|
+
/**
|
|
3
|
+
* Collect class (`.name`) and id (`#name`) selectors, mapping each unique name
|
|
4
|
+
* to every source {@link Range} it was defined at. A name only counts when it
|
|
5
|
+
* appears in a prelude that ends with `{`; names in declaration values or
|
|
6
|
+
* at-rules (ending with `;`/`}`) are discarded, which keeps hex colors and
|
|
7
|
+
* numbers out. Names in `:global` scope -- `:global(.x)`, a bare `:global .x`,
|
|
8
|
+
* or a `:global { ... }` block (and their `:local` inverses) -- are excluded,
|
|
9
|
+
* matching what a CSS module actually exports. Comments, strings and
|
|
10
|
+
* interpolations are skipped. `offset` is added to every range so callers can
|
|
11
|
+
* scan a slice of a larger document (eg an embedded `<style>` block) in the
|
|
12
|
+
* original document's coordinate space.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findStyleSelectors(code: string, offset?: number): Map<string, Range[]>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marko/language-tools",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Marko Language Tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"analysis",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@luxass/strip-json-comments": "^1.4.0",
|
|
40
|
-
"@marko/compiler": "^5.39.
|
|
41
|
-
"htmljs-parser": "^5.
|
|
40
|
+
"@marko/compiler": "^5.39.66",
|
|
41
|
+
"htmljs-parser": "^5.11.0",
|
|
42
42
|
"relative-import-path": "^1.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/babel__code-frame": "^7.27.0",
|
|
46
46
|
"@typescript/vfs": "^1.6.4",
|
|
47
|
-
"marko": "^5.
|
|
47
|
+
"marko": "^5.39.11",
|
|
48
48
|
"mitata": "^1.0.34",
|
|
49
|
-
"tsx": "^4.
|
|
49
|
+
"tsx": "^4.22.4"
|
|
50
50
|
}
|
|
51
51
|
}
|