mountly-vite-plugin 1.6.0 → 1.7.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/index.js +320 -12
- package/dist/types.d.ts +16 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -613,8 +613,8 @@ function getSelfContainedExternals(framework) {
|
|
|
613
613
|
|
|
614
614
|
// src/embed.ts
|
|
615
615
|
import { globSync, readFileSync as readFileSync2 } from "fs";
|
|
616
|
-
import { basename, dirname as
|
|
617
|
-
import { parseAst as
|
|
616
|
+
import { basename, dirname as dirname4, extname, relative as relative3, resolve as resolve3 } from "path";
|
|
617
|
+
import { parseAst as parseAst4 } from "vite";
|
|
618
618
|
|
|
619
619
|
// src/docs.ts
|
|
620
620
|
import { parseAst as parseAst2 } from "vite";
|
|
@@ -1099,6 +1099,283 @@ function extractDocs(code, options = {}) {
|
|
|
1099
1099
|
}
|
|
1100
1100
|
}
|
|
1101
1101
|
|
|
1102
|
+
// src/types.ts
|
|
1103
|
+
import { dirname as dirname3, resolve as resolvePath } from "path";
|
|
1104
|
+
import { parseAst as parseAst3 } from "vite";
|
|
1105
|
+
function parseModule(file, code) {
|
|
1106
|
+
const sfc = /\.(vue|svelte)$/.exec(file)?.[1];
|
|
1107
|
+
const source = sfc ? scriptOf(code) : code;
|
|
1108
|
+
const body = parseAst3(source, { lang: sfc ? "ts" : "tsx" }).body;
|
|
1109
|
+
const mod = {
|
|
1110
|
+
file,
|
|
1111
|
+
source,
|
|
1112
|
+
body,
|
|
1113
|
+
types: /* @__PURE__ */ new Map(),
|
|
1114
|
+
imports: /* @__PURE__ */ new Map(),
|
|
1115
|
+
exports: /* @__PURE__ */ new Map(),
|
|
1116
|
+
opaque: /* @__PURE__ */ new Set()
|
|
1117
|
+
};
|
|
1118
|
+
for (const raw of body) {
|
|
1119
|
+
const node = raw.declaration ?? raw;
|
|
1120
|
+
if (node.type === "TSInterfaceDeclaration" || node.type === "TSTypeAliasDeclaration") {
|
|
1121
|
+
if (mod.types.has(node.id.name) || mod.opaque.has(node.id.name)) {
|
|
1122
|
+
mod.types.delete(node.id.name);
|
|
1123
|
+
mod.opaque.add(node.id.name);
|
|
1124
|
+
} else {
|
|
1125
|
+
mod.types.set(node.id.name, node);
|
|
1126
|
+
}
|
|
1127
|
+
} else if (node.type === "ImportDeclaration" || raw.source && raw.specifiers) {
|
|
1128
|
+
for (const s of node.specifiers ?? []) {
|
|
1129
|
+
if (s.type !== "ImportSpecifier" && s.type !== "ExportSpecifier") {
|
|
1130
|
+
mod.opaque.add(s.local.name);
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
const name2 = s.imported ?? s.local;
|
|
1134
|
+
const local = s.type === "ExportSpecifier" ? s.exported : s.local;
|
|
1135
|
+
mod.imports.set(local.name ?? local.value, {
|
|
1136
|
+
from: node.source.value,
|
|
1137
|
+
name: name2.name ?? name2.value
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
} else if (raw.type === "ExportNamedDeclaration" && !raw.declaration) {
|
|
1141
|
+
for (const s of raw.specifiers) {
|
|
1142
|
+
mod.exports.set(s.exported.name ?? s.exported.value, s.local.name ?? s.local.value);
|
|
1143
|
+
}
|
|
1144
|
+
} else if (node.id?.name) {
|
|
1145
|
+
mod.opaque.add(node.id.name);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
const params = (node) => {
|
|
1149
|
+
if (Array.isArray(node)) return node.forEach(params);
|
|
1150
|
+
if (!node || typeof node !== "object") return;
|
|
1151
|
+
const n = node;
|
|
1152
|
+
if (n.type === "TSTypeParameter") mod.opaque.add(n.name.name);
|
|
1153
|
+
for (const key in n) params(n[key]);
|
|
1154
|
+
};
|
|
1155
|
+
params(body);
|
|
1156
|
+
for (const [, list = ""] of code.matchAll(/<script\b[^>]*\bgenerics?="([^"]*)"/g)) {
|
|
1157
|
+
for (const part of list.split(",")) mod.opaque.add(part.trim().split(/\s/)[0] ?? "");
|
|
1158
|
+
}
|
|
1159
|
+
return mod;
|
|
1160
|
+
}
|
|
1161
|
+
function rewrite(source, node, edits) {
|
|
1162
|
+
let out = source.slice(node.start, node.end);
|
|
1163
|
+
for (const [start, end, text] of [...edits].sort((a, b) => b[0] - a[0])) {
|
|
1164
|
+
out = out.slice(0, start - node.start) + text + out.slice(end - node.start);
|
|
1165
|
+
}
|
|
1166
|
+
return out;
|
|
1167
|
+
}
|
|
1168
|
+
function introduced(node) {
|
|
1169
|
+
const names = (node.typeParameters?.params ?? []).map((p) => p.name.name);
|
|
1170
|
+
if (node.type === "TSMappedType" && node.key?.name) names.push(node.key.name);
|
|
1171
|
+
if (node.type === "TSConditionalType") {
|
|
1172
|
+
const infer = (n) => {
|
|
1173
|
+
if (Array.isArray(n)) return n.forEach(infer);
|
|
1174
|
+
if (!n || typeof n !== "object") return;
|
|
1175
|
+
if (n.type === "TSInferType") names.push(n.typeParameter.name.name);
|
|
1176
|
+
for (const key in n) infer(n[key]);
|
|
1177
|
+
};
|
|
1178
|
+
infer(node.extendsType);
|
|
1179
|
+
}
|
|
1180
|
+
return names;
|
|
1181
|
+
}
|
|
1182
|
+
function tupleElement(node) {
|
|
1183
|
+
if (!node || node.type === "TSRestType") return void 0;
|
|
1184
|
+
if (node.type === "TSNamedTupleMember") {
|
|
1185
|
+
if (node.elementType?.type === "TSRestType") return void 0;
|
|
1186
|
+
const inner = node.elementType?.type === "TSOptionalType" ? node.elementType.typeAnnotation : node.elementType;
|
|
1187
|
+
return { type: inner, optional: Boolean(node.optional) || inner !== node.elementType };
|
|
1188
|
+
}
|
|
1189
|
+
if (node.type === "TSOptionalType") return { type: node.typeAnnotation, optional: true };
|
|
1190
|
+
return { type: node, optional: false };
|
|
1191
|
+
}
|
|
1192
|
+
var UTILITY_TYPES = /* @__PURE__ */ new Set([
|
|
1193
|
+
"Array",
|
|
1194
|
+
"ArrayLike",
|
|
1195
|
+
"AsyncIterable",
|
|
1196
|
+
"Awaited",
|
|
1197
|
+
"Capitalize",
|
|
1198
|
+
"ConstructorParameters",
|
|
1199
|
+
"Exclude",
|
|
1200
|
+
"Extract",
|
|
1201
|
+
"InstanceType",
|
|
1202
|
+
"Iterable",
|
|
1203
|
+
"Lowercase",
|
|
1204
|
+
"NoInfer",
|
|
1205
|
+
"NonNullable",
|
|
1206
|
+
"Omit",
|
|
1207
|
+
"Parameters",
|
|
1208
|
+
"Partial",
|
|
1209
|
+
"Pick",
|
|
1210
|
+
"PromiseLike",
|
|
1211
|
+
"PropertyKey",
|
|
1212
|
+
"Readonly",
|
|
1213
|
+
"ReadonlyArray",
|
|
1214
|
+
"ReadonlyMap",
|
|
1215
|
+
"ReadonlySet",
|
|
1216
|
+
"Record",
|
|
1217
|
+
"Required",
|
|
1218
|
+
"ReturnType",
|
|
1219
|
+
"Uncapitalize",
|
|
1220
|
+
"Uppercase"
|
|
1221
|
+
]);
|
|
1222
|
+
var NODE_ONLY = /* @__PURE__ */ new Set(["Buffer", "process", "global", "require", "module", "exports"]);
|
|
1223
|
+
function isGlobal(name2) {
|
|
1224
|
+
if (UTILITY_TYPES.has(name2)) return true;
|
|
1225
|
+
if (NODE_ONLY.has(name2)) return false;
|
|
1226
|
+
if (/^(?:HTML|SVG)\w*Element$|^\w*Event(?:Init|Target)?$|^(?:Element|Node|Document|Window|ShadowRoot|DOMRect|FileList|DataTransfer|CSSStyleDeclaration|NodeList)$/.test(
|
|
1227
|
+
name2
|
|
1228
|
+
)) {
|
|
1229
|
+
return true;
|
|
1230
|
+
}
|
|
1231
|
+
return name2 in globalThis;
|
|
1232
|
+
}
|
|
1233
|
+
function unwrap(type) {
|
|
1234
|
+
if (type?.type === "TSParenthesizedType") return unwrap(type.typeAnnotation);
|
|
1235
|
+
if (type?.type !== "TSUnionType") return type;
|
|
1236
|
+
const real = type.types.filter(
|
|
1237
|
+
(t) => t.type !== "TSUndefinedKeyword" && t.type !== "TSNullKeyword"
|
|
1238
|
+
);
|
|
1239
|
+
return real.length === 1 ? unwrap(real[0]) : type;
|
|
1240
|
+
}
|
|
1241
|
+
var CANDIDATES = ["", ".ts", ".tsx", ".d.ts", "/index.ts", "/index.tsx"];
|
|
1242
|
+
function embedTypes(code, options) {
|
|
1243
|
+
const result = { props: {}, events: {}, declarations: [] };
|
|
1244
|
+
const named = /* @__PURE__ */ new Map();
|
|
1245
|
+
const taken = /* @__PURE__ */ new Set();
|
|
1246
|
+
const modules = /* @__PURE__ */ new Map();
|
|
1247
|
+
const load = (file) => {
|
|
1248
|
+
if (!modules.has(file)) {
|
|
1249
|
+
let mod = null;
|
|
1250
|
+
try {
|
|
1251
|
+
const text = options.load?.(file);
|
|
1252
|
+
if (text !== void 0) mod = parseModule(file, text);
|
|
1253
|
+
} catch {
|
|
1254
|
+
}
|
|
1255
|
+
modules.set(file, mod);
|
|
1256
|
+
}
|
|
1257
|
+
return modules.get(file) ?? null;
|
|
1258
|
+
};
|
|
1259
|
+
const resolve4 = (mod, name2, depth = 0) => {
|
|
1260
|
+
const decl = mod.types.get(name2);
|
|
1261
|
+
if (decl) return { decl, mod };
|
|
1262
|
+
if (mod.opaque.has(name2) || depth > 8) return null;
|
|
1263
|
+
const imp = mod.imports.get(name2);
|
|
1264
|
+
if (!imp) return isGlobal(name2) ? void 0 : null;
|
|
1265
|
+
if (!imp.from.startsWith(".")) return null;
|
|
1266
|
+
const base = resolvePath(dirname3(mod.file), imp.from.replace(/\.[cm]?js$/, ""));
|
|
1267
|
+
for (const ext of CANDIDATES) {
|
|
1268
|
+
const other = load(base + ext);
|
|
1269
|
+
if (other) return resolve4(other, other.exports.get(imp.name) ?? imp.name, depth + 1) ?? null;
|
|
1270
|
+
}
|
|
1271
|
+
return null;
|
|
1272
|
+
};
|
|
1273
|
+
const emit = (decl, mod) => {
|
|
1274
|
+
const existing = named.get(decl);
|
|
1275
|
+
if (existing) return existing;
|
|
1276
|
+
let as = `${options.scope}_${decl.id.name}`;
|
|
1277
|
+
for (let n = 2; taken.has(as); n++) as = `${options.scope}_${decl.id.name}${n}`;
|
|
1278
|
+
named.set(decl, as);
|
|
1279
|
+
taken.add(as);
|
|
1280
|
+
const edits = [[decl.id.start, decl.id.end, as]];
|
|
1281
|
+
if (!walk(decl, mod, /* @__PURE__ */ new Set(), edits)) return void 0;
|
|
1282
|
+
result.declarations.push(`export ${rewrite(mod.source, decl, edits)}`);
|
|
1283
|
+
return as;
|
|
1284
|
+
};
|
|
1285
|
+
const walk = (node, mod, scope, edits) => {
|
|
1286
|
+
if (Array.isArray(node)) return node.every((n2) => walk(n2, mod, scope, edits));
|
|
1287
|
+
if (!node || typeof node !== "object") return true;
|
|
1288
|
+
const n = node;
|
|
1289
|
+
if (n.type === "TSTypeQuery" || n.type === "TSImportType" || n.type === "TSQualifiedName" || n.type === "MemberExpression" || n.computed && n.key?.type !== "Literal") {
|
|
1290
|
+
return false;
|
|
1291
|
+
}
|
|
1292
|
+
const own = introduced(n);
|
|
1293
|
+
const inner = own.length ? /* @__PURE__ */ new Set([...scope, ...own]) : scope;
|
|
1294
|
+
const ref = n.type === "TSTypeReference" ? n.typeName : n.type === "TSInterfaceHeritage" ? n.expression : null;
|
|
1295
|
+
if (ref?.type === "Identifier" && !inner.has(ref.name)) {
|
|
1296
|
+
const target = resolve4(mod, ref.name);
|
|
1297
|
+
if (target === null) return false;
|
|
1298
|
+
if (target) {
|
|
1299
|
+
const as = emit(target.decl, target.mod);
|
|
1300
|
+
if (!as) return false;
|
|
1301
|
+
edits.push([ref.start, ref.end, as]);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
for (const key in n) if (!walk(n[key], mod, inner, edits)) return false;
|
|
1305
|
+
return true;
|
|
1306
|
+
};
|
|
1307
|
+
const typed = (node, mod) => {
|
|
1308
|
+
if (!node) return void 0;
|
|
1309
|
+
const mark = result.declarations.length;
|
|
1310
|
+
const before = new Map(named);
|
|
1311
|
+
const edits = [];
|
|
1312
|
+
if (walk(node, mod, /* @__PURE__ */ new Set(), edits)) return rewrite(mod.source, node, edits);
|
|
1313
|
+
result.declarations.length = mark;
|
|
1314
|
+
named.clear();
|
|
1315
|
+
taken.clear();
|
|
1316
|
+
for (const [decl, as] of before) {
|
|
1317
|
+
named.set(decl, as);
|
|
1318
|
+
taken.add(as);
|
|
1319
|
+
}
|
|
1320
|
+
return void 0;
|
|
1321
|
+
};
|
|
1322
|
+
const detail = (params, mod, skip = 0) => {
|
|
1323
|
+
const param = params?.[skip];
|
|
1324
|
+
if (!param || param.type === "RestElement") return void 0;
|
|
1325
|
+
const text = typed(param.typeAnnotation?.typeAnnotation, mod);
|
|
1326
|
+
return text && param.optional ? `${text} | null` : text;
|
|
1327
|
+
};
|
|
1328
|
+
try {
|
|
1329
|
+
const file = options.file ?? "component.tsx";
|
|
1330
|
+
const mod = parseModule(file, code);
|
|
1331
|
+
modules.set(file, mod);
|
|
1332
|
+
const aliases = localTypes(mod.body);
|
|
1333
|
+
const sfc = /\.(vue|svelte)$/.exec(file)?.[1];
|
|
1334
|
+
let declared;
|
|
1335
|
+
if (sfc === "vue") declared = macroCall(mod.body, "defineProps")?.typeArguments?.params?.[0];
|
|
1336
|
+
else if (sfc === "svelte") declared = svelteProps(mod.body)?.id?.typeAnnotation?.typeAnnotation;
|
|
1337
|
+
else {
|
|
1338
|
+
const declaration = findExport(mod.body, options.exportName ?? "default");
|
|
1339
|
+
declared = declaration ? propsType(declaration) : void 0;
|
|
1340
|
+
}
|
|
1341
|
+
for (const member2 of membersOf(declared, aliases) ?? []) {
|
|
1342
|
+
const name2 = keyOf(member2);
|
|
1343
|
+
if (!name2) continue;
|
|
1344
|
+
if (/^on[A-Z]/.test(name2)) {
|
|
1345
|
+
const fn = member2.type === "TSMethodSignature" ? member2 : unwrap(member2.typeAnnotation?.typeAnnotation);
|
|
1346
|
+
if (fn?.type !== "TSFunctionType" && fn?.type !== "TSMethodSignature") continue;
|
|
1347
|
+
if (fn.typeParameters) continue;
|
|
1348
|
+
const text2 = detail(fn.params, mod);
|
|
1349
|
+
if (text2) result.events[eventName(name2)] = text2;
|
|
1350
|
+
continue;
|
|
1351
|
+
}
|
|
1352
|
+
if (member2.type !== "TSPropertySignature") continue;
|
|
1353
|
+
const text = typed(member2.typeAnnotation?.typeAnnotation, mod);
|
|
1354
|
+
if (text) result.props[name2] = text;
|
|
1355
|
+
}
|
|
1356
|
+
if (sfc === "vue") {
|
|
1357
|
+
const emits = macroCall(mod.body, "defineEmits")?.typeArguments?.params?.[0];
|
|
1358
|
+
for (const member2 of membersOf(emits, aliases) ?? []) {
|
|
1359
|
+
if (member2.type === "TSPropertySignature") {
|
|
1360
|
+
const event = keyOf(member2);
|
|
1361
|
+
const tuple = member2.typeAnnotation?.typeAnnotation;
|
|
1362
|
+
const first = tuple?.type === "TSTupleType" ? tuple.elementTypes[0] : void 0;
|
|
1363
|
+
const element = tupleElement(first);
|
|
1364
|
+
const text = element && typed(element.type, mod);
|
|
1365
|
+
if (event && text) result.events[event] = element.optional ? `${text} | null` : text;
|
|
1366
|
+
}
|
|
1367
|
+
if (member2.type === "TSCallSignatureDeclaration") {
|
|
1368
|
+
const event = member2.params?.[0]?.typeAnnotation?.typeAnnotation?.literal?.value;
|
|
1369
|
+
const text = detail(member2.params, mod, 1);
|
|
1370
|
+
if (typeof event === "string" && text) result.events[event] = text;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
} catch {
|
|
1375
|
+
}
|
|
1376
|
+
return result;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1102
1379
|
// src/embed.ts
|
|
1103
1380
|
function frameworkFor(file) {
|
|
1104
1381
|
if (file.endsWith(".vue")) return "vue";
|
|
@@ -1148,18 +1425,25 @@ function normalize(options, root) {
|
|
|
1148
1425
|
return unique(entries);
|
|
1149
1426
|
}
|
|
1150
1427
|
function declarations(elements) {
|
|
1151
|
-
const blocks = elements.map(({ tag, props }) => {
|
|
1428
|
+
const blocks = elements.map(({ tag, props, types, docs }) => {
|
|
1152
1429
|
const id = name(tag);
|
|
1153
|
-
const members = props.filter((spec) => spec.kind !== "event").map(
|
|
1154
|
-
|
|
1430
|
+
const members = props.filter((spec) => spec.kind !== "event").map(
|
|
1431
|
+
(spec) => `${jsdoc(docs.props[spec.name]?.description, " ")} ${member(spec.name)}?: ${types.props[spec.name] ?? TS_TYPE[spec.kind] ?? "unknown"};`
|
|
1432
|
+
);
|
|
1433
|
+
const events = props.filter((spec) => spec.kind === "event").map((spec) => {
|
|
1434
|
+
const detail = spec.event && types.events[spec.event];
|
|
1435
|
+
return `${jsdoc(docs.props[spec.name]?.description, " ")} ${JSON.stringify(spec.event)}: CustomEvent${detail ? `<${detail}>` : ""};`;
|
|
1436
|
+
});
|
|
1155
1437
|
const block = (kind, lines) => lines.length ? `export interface ${id}${kind} {
|
|
1156
1438
|
${lines.join("\n")}
|
|
1157
1439
|
}` : `export interface ${id}${kind} {}`;
|
|
1158
|
-
return `${
|
|
1440
|
+
return `${types.declarations.map((text) => `${text}
|
|
1441
|
+
|
|
1442
|
+
`).join("")}${block("Props", members)}
|
|
1159
1443
|
|
|
1160
1444
|
${block("EventMap", events)}
|
|
1161
1445
|
|
|
1162
|
-
export interface ${id}Element extends MountlyElement<${id}Props> {
|
|
1446
|
+
${jsdoc(docs.description, "")}export interface ${id}Element extends MountlyElement<${id}Props> {
|
|
1163
1447
|
addEventListener<K extends keyof ${id}EventMap>(
|
|
1164
1448
|
type: K,
|
|
1165
1449
|
listener: (this: ${id}Element, event: ${id}EventMap[K]) => unknown,
|
|
@@ -1225,6 +1509,16 @@ ${jsx.join("\n")}
|
|
|
1225
1509
|
}
|
|
1226
1510
|
`;
|
|
1227
1511
|
}
|
|
1512
|
+
function jsdoc(text, indent) {
|
|
1513
|
+
if (!text) return "";
|
|
1514
|
+
const lines = text.replace(/\*\//g, "*\\/").split("\n");
|
|
1515
|
+
if (lines.length === 1) return `${indent}/** ${lines[0]} */
|
|
1516
|
+
`;
|
|
1517
|
+
return `${indent}/**
|
|
1518
|
+
${lines.map((line) => `${indent} *${line ? ` ${line}` : ""}`).join("\n")}
|
|
1519
|
+
${indent} */
|
|
1520
|
+
`;
|
|
1521
|
+
}
|
|
1228
1522
|
function member(prop) {
|
|
1229
1523
|
return /^[A-Za-z_$][\w$]*$/.test(prop) ? prop : JSON.stringify(prop);
|
|
1230
1524
|
}
|
|
@@ -1336,7 +1630,7 @@ function resolveCssToken(bundle) {
|
|
|
1336
1630
|
output.code = output.code.replace(token, "void 0");
|
|
1337
1631
|
continue;
|
|
1338
1632
|
}
|
|
1339
|
-
const href = relative3(
|
|
1633
|
+
const href = relative3(dirname4(output.fileName), stylesheet).replace(/\\/g, "/");
|
|
1340
1634
|
output.code = output.code.replace(
|
|
1341
1635
|
token,
|
|
1342
1636
|
`new URL(${JSON.stringify(`./${href}`)}, import.meta.url).href`
|
|
@@ -1444,7 +1738,7 @@ function shimWorkers(code) {
|
|
|
1444
1738
|
walk(child, node, outside ? shadowed : hidden);
|
|
1445
1739
|
}
|
|
1446
1740
|
};
|
|
1447
|
-
walk(
|
|
1741
|
+
walk(parseAst4(code, { lang: "js" }), void 0, false);
|
|
1448
1742
|
if (!callees.length) return null;
|
|
1449
1743
|
let out = code;
|
|
1450
1744
|
for (const { start, end } of callees.sort((a, b) => b.start - a.start)) {
|
|
@@ -1493,7 +1787,20 @@ function readElementSource(entry, tag, root) {
|
|
|
1493
1787
|
`[mountly] cannot read the props of ${entry.component} for <${tag}>. Declare the props type in that file, or pass \`props\` on the element entry.`
|
|
1494
1788
|
);
|
|
1495
1789
|
}
|
|
1496
|
-
|
|
1790
|
+
const docs = extractDocs(source, opts);
|
|
1791
|
+
const types = entry.props ? { props: {}, events: {}, declarations: [] } : embedTypes(source, {
|
|
1792
|
+
...opts,
|
|
1793
|
+
file: resolve3(root, entry.component),
|
|
1794
|
+
scope: name(tag),
|
|
1795
|
+
load: (file) => {
|
|
1796
|
+
try {
|
|
1797
|
+
return readFileSync2(file, "utf8");
|
|
1798
|
+
} catch {
|
|
1799
|
+
return void 0;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
});
|
|
1803
|
+
return { props, docs, types };
|
|
1497
1804
|
}
|
|
1498
1805
|
function defineElementsConfig(options) {
|
|
1499
1806
|
const entryId = "virtual:mountly-embed";
|
|
@@ -1510,13 +1817,14 @@ function defineElementsConfig(options) {
|
|
|
1510
1817
|
root = config.root;
|
|
1511
1818
|
assertSingleCompiler(config.plugins);
|
|
1512
1819
|
elements = normalize(options, root).map(([tag, entry]) => {
|
|
1513
|
-
const { props, docs } = readElementSource(entry, tag, root);
|
|
1820
|
+
const { props, docs, types } = readElementSource(entry, tag, root);
|
|
1514
1821
|
return {
|
|
1515
1822
|
tag,
|
|
1516
1823
|
entry,
|
|
1517
1824
|
props,
|
|
1518
1825
|
framework: entry.framework ?? frameworkFor(entry.component),
|
|
1519
|
-
docs
|
|
1826
|
+
docs,
|
|
1827
|
+
types
|
|
1520
1828
|
};
|
|
1521
1829
|
});
|
|
1522
1830
|
const warn = config.logger?.warn.bind(config.logger) ?? console.warn;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ExtractOptions } from "./props.js";
|
|
2
|
+
export interface EmbedTypes {
|
|
3
|
+
/** Per prop, its type as written, with copied names renamed. */
|
|
4
|
+
props: Record<string, string>;
|
|
5
|
+
/** Per DOM event, the type of its `detail`: the callback's first argument. */
|
|
6
|
+
events: Record<string, string>;
|
|
7
|
+
/** The declarations those types name, to emit beside them. */
|
|
8
|
+
declarations: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface EmbedTypesOptions extends ExtractOptions {
|
|
11
|
+
/** Prefix for copied declarations, so two elements' `Line` types cannot collide. */
|
|
12
|
+
scope: string;
|
|
13
|
+
/** Read a file an import points at. Absent or `undefined`: imports stay opaque. */
|
|
14
|
+
load?: (file: string) => string | undefined;
|
|
15
|
+
}
|
|
16
|
+
export declare function embedTypes(code: string, options: EmbedTypesOptions): EmbedTypes;
|