@bagelink/blox 1.11.5 → 1.11.9

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.
@@ -1073,7 +1073,6 @@ function bloxPlugin() {
1073
1073
  return {
1074
1074
  name: "vite-plugin-blox",
1075
1075
  enforce: "pre",
1076
- // must run before @vitejs/plugin-vue
1077
1076
  transform(code, id) {
1078
1077
  if (!id.endsWith(".vue")) return;
1079
1078
  if (!code.includes("defineBlock")) return;
@@ -1084,41 +1083,75 @@ function bloxPlugin() {
1084
1083
  const attrs = setupMatch[2];
1085
1084
  const body = setupMatch[3];
1086
1085
  const closeTag = setupMatch[4];
1087
- const hoisted = [];
1088
1086
  let remaining = body;
1089
- while (true) {
1090
- const m = /^([ \t]*defineBlock\()/m.exec(remaining);
1091
- if (!m) break;
1092
- const start = m.index;
1093
- const parenStart = start + m[1].length - 1;
1094
- let depth = 1;
1095
- let i = parenStart + 1;
1096
- while (i < remaining.length && depth > 0) {
1097
- if (remaining[i] === "(") depth++;
1098
- else if (remaining[i] === ")") depth--;
1099
- i++;
1100
- }
1101
- if (remaining[i] === "\n") i++;
1102
- const fullCall = remaining.slice(start, i).trim();
1103
- const nameMatch = fullCall.match(/name\s*:\s*['"](\w+)['"]/);
1104
- if (!nameMatch) {
1105
- console.warn("[vite-plugin-blox] defineBlock() call missing `name` property — skipping");
1106
- break;
1087
+ const hoistedDecls = [];
1088
+ const blockCallMatch = /^[ \t]*defineBlock\(/m.exec(remaining);
1089
+ if (!blockCallMatch) return;
1090
+ const callStart = blockCallMatch.index;
1091
+ const parenStart = callStart + blockCallMatch[0].length - 1;
1092
+ let depth = 1;
1093
+ let i = parenStart + 1;
1094
+ while (i < remaining.length && depth > 0) {
1095
+ if (remaining[i] === "(") depth++;
1096
+ else if (remaining[i] === ")") depth--;
1097
+ i++;
1098
+ }
1099
+ if (remaining[i] === "\n") i++;
1100
+ const callExpr = remaining.slice(callStart, i).trimEnd();
1101
+ const nameMatch = callExpr.match(/name\s*:\s*['"](\w+)['"]/);
1102
+ if (!nameMatch) {
1103
+ console.warn("[vite-plugin-blox] defineBlock() missing `name` — skipping");
1104
+ return;
1105
+ }
1106
+ const blockName = nameMatch[1];
1107
+ remaining = remaining.slice(0, callStart) + remaining.slice(i);
1108
+ const identifiers = /* @__PURE__ */ new Set();
1109
+ const identRe = /\b([a-z_$][\w$]*)\b/gi;
1110
+ let identMatch;
1111
+ while ((identMatch = identRe.exec(callExpr)) !== null) {
1112
+ identifiers.add(identMatch[1]);
1113
+ }
1114
+ for (const ident of identifiers) {
1115
+ const declRe = new RegExp(`^([ \\t]*const\\s+${ident}\\s*=\\s*)`, "m");
1116
+ const declMatch = declRe.exec(remaining);
1117
+ if (!declMatch) continue;
1118
+ const declStart = declMatch.index;
1119
+ const exprStart = declStart + declMatch[0].length;
1120
+ let d = 0;
1121
+ let j = exprStart;
1122
+ while (j < remaining.length) {
1123
+ const ch = remaining[j];
1124
+ if (ch === "(" || ch === "[" || ch === "{") {
1125
+ d++;
1126
+ } else if (ch === ")" || ch === "]" || ch === "}") {
1127
+ d--;
1128
+ } else if (ch === "\n" && d === 0) {
1129
+ j++;
1130
+ break;
1131
+ }
1132
+ j++;
1107
1133
  }
1108
- const varName = nameMatch[1];
1109
- const callExpr = remaining.slice(start, i).trimEnd();
1110
- hoisted.push(`export const ${varName} = ${callExpr.trimStart()}`);
1111
- remaining = remaining.slice(0, start) + remaining.slice(i);
1134
+ const fullDecl = remaining.slice(declStart, j).trimEnd();
1135
+ hoistedDecls.push(fullDecl);
1136
+ remaining = remaining.slice(0, declStart) + remaining.slice(j);
1137
+ }
1138
+ const hoistedImports = [];
1139
+ const importRe = /^[ \t]*import\s[^\n]+from\s+['"](?:@bagelink\/blox|@bagelink\/vue)['"]\s*/gm;
1140
+ let importMatch;
1141
+ while ((importMatch = importRe.exec(remaining)) !== null) {
1142
+ hoistedImports.push(importMatch[0].trimEnd());
1112
1143
  }
1113
- if (hoisted.length === 0) return;
1114
1144
  const langMatch = attrs.match(/lang="([^"]+)"/);
1115
1145
  const lang = langMatch ? ` lang="${langMatch[1]}"` : "";
1116
- const newBlock = [
1146
+ const nonSetupBlock = [
1117
1147
  `<script${lang}>`,
1118
- hoisted.join("\n"),
1119
- `<\/script>`,
1120
- `${openTag}${remaining}${closeTag}`
1148
+ ...hoistedImports,
1149
+ ...hoistedDecls,
1150
+ `export const ${blockName} = ${callExpr.trimStart()}`,
1151
+ `<\/script>`
1121
1152
  ].join("\n");
1153
+ const newBlock = `${nonSetupBlock}
1154
+ ${openTag}${remaining}${closeTag}`;
1122
1155
  const s = new MagicString(code);
1123
1156
  const blockStart = code.indexOf(openTag);
1124
1157
  const blockEnd = blockStart + openTag.length + body.length + closeTag.length;
@@ -1,24 +1,23 @@
1
1
  import { Plugin } from 'vite';
2
2
  /**
3
- * Vite plugin that hoists `defineBlock({ name: '...', ... })` call statements
4
- * out of `<script setup>` into a plain `<script>` block as
5
- * `export const <name> = defineBlock({ ... })`.
3
+ * Vite plugin that hoists `defineBlock(...)` out of `<script setup>` into a
4
+ * plain `<script>` block. Also hoists any variables referenced by defineBlock
5
+ * (e.g. `const schema = defineSchema(...)`) and the relevant imports.
6
6
  *
7
- * Write a single clean `<script setup>` with no assignment or export:
7
+ * @example
8
8
  * ```vue
9
9
  * <script setup lang="ts">
10
- * defineBlock({ name: 'aboutBox', label: 'About Box', icon: 'info', schema })
11
- * defineProps<AboutBoxProps>()
12
- * </script>
13
- * ```
10
+ * import { defineBlock } from '@bagelink/blox'
11
+ * import { defineSchema, $ } from '@bagelink/vue'
14
12
  *
15
- * The plugin rewrites it before Vue's compiler sees it:
16
- * ```vue
17
- * <script lang="ts">
18
- * export const aboutBox = defineBlock({ name: 'aboutBox', label: 'About Box', icon: 'info', schema })
19
- * </script>
20
- * <script setup lang="ts">
21
- * defineProps<AboutBoxProps>()
13
+ * // Either inline:
14
+ * defineBlock({ name: 'hero', label: 'Hero', schema: defineSchema({ ... }) })
15
+ *
16
+ * // Or via variable (also hoisted automatically):
17
+ * const schema = defineSchema({ ... })
18
+ * defineBlock({ name: 'hero', label: 'Hero', schema })
19
+ *
20
+ * defineProps<HeroProps>()
22
21
  * </script>
23
22
  * ```
24
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAGlC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAiFnC"}
1
+ {"version":3,"file":"vite-plugin.d.ts","sourceRoot":"","sources":["../src/vite-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAGlC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA6HnC"}
@@ -1071,7 +1071,6 @@ function bloxPlugin() {
1071
1071
  return {
1072
1072
  name: "vite-plugin-blox",
1073
1073
  enforce: "pre",
1074
- // must run before @vitejs/plugin-vue
1075
1074
  transform(code, id) {
1076
1075
  if (!id.endsWith(".vue")) return;
1077
1076
  if (!code.includes("defineBlock")) return;
@@ -1082,41 +1081,75 @@ function bloxPlugin() {
1082
1081
  const attrs = setupMatch[2];
1083
1082
  const body = setupMatch[3];
1084
1083
  const closeTag = setupMatch[4];
1085
- const hoisted = [];
1086
1084
  let remaining = body;
1087
- while (true) {
1088
- const m = /^([ \t]*defineBlock\()/m.exec(remaining);
1089
- if (!m) break;
1090
- const start = m.index;
1091
- const parenStart = start + m[1].length - 1;
1092
- let depth = 1;
1093
- let i = parenStart + 1;
1094
- while (i < remaining.length && depth > 0) {
1095
- if (remaining[i] === "(") depth++;
1096
- else if (remaining[i] === ")") depth--;
1097
- i++;
1098
- }
1099
- if (remaining[i] === "\n") i++;
1100
- const fullCall = remaining.slice(start, i).trim();
1101
- const nameMatch = fullCall.match(/name\s*:\s*['"](\w+)['"]/);
1102
- if (!nameMatch) {
1103
- console.warn("[vite-plugin-blox] defineBlock() call missing `name` property — skipping");
1104
- break;
1085
+ const hoistedDecls = [];
1086
+ const blockCallMatch = /^[ \t]*defineBlock\(/m.exec(remaining);
1087
+ if (!blockCallMatch) return;
1088
+ const callStart = blockCallMatch.index;
1089
+ const parenStart = callStart + blockCallMatch[0].length - 1;
1090
+ let depth = 1;
1091
+ let i = parenStart + 1;
1092
+ while (i < remaining.length && depth > 0) {
1093
+ if (remaining[i] === "(") depth++;
1094
+ else if (remaining[i] === ")") depth--;
1095
+ i++;
1096
+ }
1097
+ if (remaining[i] === "\n") i++;
1098
+ const callExpr = remaining.slice(callStart, i).trimEnd();
1099
+ const nameMatch = callExpr.match(/name\s*:\s*['"](\w+)['"]/);
1100
+ if (!nameMatch) {
1101
+ console.warn("[vite-plugin-blox] defineBlock() missing `name` — skipping");
1102
+ return;
1103
+ }
1104
+ const blockName = nameMatch[1];
1105
+ remaining = remaining.slice(0, callStart) + remaining.slice(i);
1106
+ const identifiers = /* @__PURE__ */ new Set();
1107
+ const identRe = /\b([a-z_$][\w$]*)\b/gi;
1108
+ let identMatch;
1109
+ while ((identMatch = identRe.exec(callExpr)) !== null) {
1110
+ identifiers.add(identMatch[1]);
1111
+ }
1112
+ for (const ident of identifiers) {
1113
+ const declRe = new RegExp(`^([ \\t]*const\\s+${ident}\\s*=\\s*)`, "m");
1114
+ const declMatch = declRe.exec(remaining);
1115
+ if (!declMatch) continue;
1116
+ const declStart = declMatch.index;
1117
+ const exprStart = declStart + declMatch[0].length;
1118
+ let d = 0;
1119
+ let j = exprStart;
1120
+ while (j < remaining.length) {
1121
+ const ch = remaining[j];
1122
+ if (ch === "(" || ch === "[" || ch === "{") {
1123
+ d++;
1124
+ } else if (ch === ")" || ch === "]" || ch === "}") {
1125
+ d--;
1126
+ } else if (ch === "\n" && d === 0) {
1127
+ j++;
1128
+ break;
1129
+ }
1130
+ j++;
1105
1131
  }
1106
- const varName = nameMatch[1];
1107
- const callExpr = remaining.slice(start, i).trimEnd();
1108
- hoisted.push(`export const ${varName} = ${callExpr.trimStart()}`);
1109
- remaining = remaining.slice(0, start) + remaining.slice(i);
1132
+ const fullDecl = remaining.slice(declStart, j).trimEnd();
1133
+ hoistedDecls.push(fullDecl);
1134
+ remaining = remaining.slice(0, declStart) + remaining.slice(j);
1135
+ }
1136
+ const hoistedImports = [];
1137
+ const importRe = /^[ \t]*import\s[^\n]+from\s+['"](?:@bagelink\/blox|@bagelink\/vue)['"]\s*/gm;
1138
+ let importMatch;
1139
+ while ((importMatch = importRe.exec(remaining)) !== null) {
1140
+ hoistedImports.push(importMatch[0].trimEnd());
1110
1141
  }
1111
- if (hoisted.length === 0) return;
1112
1142
  const langMatch = attrs.match(/lang="([^"]+)"/);
1113
1143
  const lang = langMatch ? ` lang="${langMatch[1]}"` : "";
1114
- const newBlock = [
1144
+ const nonSetupBlock = [
1115
1145
  `<script${lang}>`,
1116
- hoisted.join("\n"),
1117
- `<\/script>`,
1118
- `${openTag}${remaining}${closeTag}`
1146
+ ...hoistedImports,
1147
+ ...hoistedDecls,
1148
+ `export const ${blockName} = ${callExpr.trimStart()}`,
1149
+ `<\/script>`
1119
1150
  ].join("\n");
1151
+ const newBlock = `${nonSetupBlock}
1152
+ ${openTag}${remaining}${closeTag}`;
1120
1153
  const s = new MagicString(code);
1121
1154
  const blockStart = code.indexOf(openTag);
1122
1155
  const blockEnd = blockStart + openTag.length + body.length + closeTag.length;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/blox",
3
3
  "type": "module",
4
- "version": "1.11.5",
4
+ "version": "1.11.9",
5
5
  "description": "Blox page builder library for drag-and-drop page building and static data management",
6
6
  "author": {
7
7
  "name": "Bagel Studio",