@flux-lang/cli-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/commands/add.d.ts +18 -0
  2. package/dist/commands/add.d.ts.map +1 -0
  3. package/dist/commands/add.js +49 -0
  4. package/dist/commands/add.js.map +1 -0
  5. package/dist/commands/check.d.ts +15 -0
  6. package/dist/commands/check.d.ts.map +1 -0
  7. package/dist/commands/check.js +40 -0
  8. package/dist/commands/check.js.map +1 -0
  9. package/dist/commands/common.d.ts +6 -0
  10. package/dist/commands/common.d.ts.map +1 -0
  11. package/dist/commands/common.js +35 -0
  12. package/dist/commands/common.js.map +1 -0
  13. package/dist/commands/config.d.ts +19 -0
  14. package/dist/commands/config.d.ts.map +1 -0
  15. package/dist/commands/config.js +21 -0
  16. package/dist/commands/config.js.map +1 -0
  17. package/dist/commands/format.d.ts +9 -0
  18. package/dist/commands/format.d.ts.map +1 -0
  19. package/dist/commands/format.js +23 -0
  20. package/dist/commands/format.js.map +1 -0
  21. package/dist/commands/new.d.ts +24 -0
  22. package/dist/commands/new.d.ts.map +1 -0
  23. package/dist/commands/new.js +93 -0
  24. package/dist/commands/new.js.map +1 -0
  25. package/dist/commands/parse.d.ts +20 -0
  26. package/dist/commands/parse.d.ts.map +1 -0
  27. package/dist/commands/parse.js +37 -0
  28. package/dist/commands/parse.js.map +1 -0
  29. package/dist/commands/pdf.d.ts +13 -0
  30. package/dist/commands/pdf.d.ts.map +1 -0
  31. package/dist/commands/pdf.js +53 -0
  32. package/dist/commands/pdf.js.map +1 -0
  33. package/dist/commands/render.d.ts +14 -0
  34. package/dist/commands/render.d.ts.map +1 -0
  35. package/dist/commands/render.js +40 -0
  36. package/dist/commands/render.js.map +1 -0
  37. package/dist/commands/step.d.ts +12 -0
  38. package/dist/commands/step.d.ts.map +1 -0
  39. package/dist/commands/step.js +29 -0
  40. package/dist/commands/step.js.map +1 -0
  41. package/dist/commands/tick.d.ts +12 -0
  42. package/dist/commands/tick.d.ts.map +1 -0
  43. package/dist/commands/tick.js +31 -0
  44. package/dist/commands/tick.js.map +1 -0
  45. package/dist/commands/view.d.ts +18 -0
  46. package/dist/commands/view.d.ts.map +1 -0
  47. package/dist/commands/view.js +28 -0
  48. package/dist/commands/view.js.map +1 -0
  49. package/dist/config.d.ts +37 -0
  50. package/dist/config.d.ts.map +1 -0
  51. package/dist/config.js +76 -0
  52. package/dist/config.js.map +1 -0
  53. package/dist/file-indexer.d.ts +29 -0
  54. package/dist/file-indexer.d.ts.map +1 -0
  55. package/dist/file-indexer.js +59 -0
  56. package/dist/file-indexer.js.map +1 -0
  57. package/dist/fs.d.ts +10 -0
  58. package/dist/fs.d.ts.map +1 -0
  59. package/dist/fs.js +57 -0
  60. package/dist/fs.js.map +1 -0
  61. package/dist/index.d.ts +19 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +19 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/last-used-dir.d.ts +9 -0
  66. package/dist/last-used-dir.d.ts.map +1 -0
  67. package/dist/last-used-dir.js +23 -0
  68. package/dist/last-used-dir.js.map +1 -0
  69. package/dist/new/templates.d.ts +28 -0
  70. package/dist/new/templates.d.ts.map +1 -0
  71. package/dist/new/templates.js +679 -0
  72. package/dist/new/templates.js.map +1 -0
  73. package/dist/pinned.d.ts +12 -0
  74. package/dist/pinned.d.ts.map +1 -0
  75. package/dist/pinned.js +45 -0
  76. package/dist/pinned.js.map +1 -0
  77. package/dist/recents.d.ts +13 -0
  78. package/dist/recents.d.ts.map +1 -0
  79. package/dist/recents.js +27 -0
  80. package/dist/recents.js.map +1 -0
  81. package/dist/types.d.ts +23 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/types.js +7 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/viewer/manager.d.ts +55 -0
  86. package/dist/viewer/manager.d.ts.map +1 -0
  87. package/dist/viewer/manager.js +182 -0
  88. package/dist/viewer/manager.js.map +1 -0
  89. package/package.json +34 -0
@@ -0,0 +1,679 @@
1
+ const FONT_PRESETS = {
2
+ tech: {
3
+ body: { primary: "Inter", fallback: "Helvetica Neue, Arial, sans-serif" },
4
+ heading: { primary: "IBM Plex Sans", fallback: "Inter, Helvetica Neue, Arial, sans-serif" },
5
+ mono: { primary: "JetBrains Mono", fallback: "Source Code Pro, Menlo, monospace" },
6
+ },
7
+ bookish: {
8
+ body: { primary: "Iowan Old Style", fallback: "Palatino Linotype, Palatino, Times New Roman, serif" },
9
+ heading: { primary: "Iowan Old Style", fallback: "Palatino Linotype, Palatino, Times New Roman, serif" },
10
+ mono: { primary: "Source Code Pro", fallback: "Courier New, monospace" },
11
+ },
12
+ };
13
+ const PAGE_SIZES = {
14
+ Letter: { width: 8.5, height: 11, units: "in" },
15
+ A4: { width: 210, height: 297, units: "mm" },
16
+ };
17
+ export function getTemplate(name) {
18
+ const templates = [
19
+ {
20
+ name: "demo",
21
+ description: "Live slots + assets + annotations",
22
+ build: buildDemoTemplate,
23
+ },
24
+ {
25
+ name: "article",
26
+ description: "Narrative article starter",
27
+ build: buildArticleTemplate,
28
+ },
29
+ {
30
+ name: "spec",
31
+ description: "Technical spec layout",
32
+ build: buildSpecTemplate,
33
+ },
34
+ {
35
+ name: "zine",
36
+ description: "Visual zine layout",
37
+ build: buildZineTemplate,
38
+ },
39
+ {
40
+ name: "paper",
41
+ description: "Academic paper with abstract",
42
+ build: buildPaperTemplate,
43
+ },
44
+ {
45
+ name: "blank",
46
+ description: "Minimal blank document",
47
+ build: buildBlankTemplate,
48
+ },
49
+ ];
50
+ return templates.find((t) => t.name === name) ?? null;
51
+ }
52
+ function buildBaseDoc(options, bodyContent, extraBlocks = []) {
53
+ const size = PAGE_SIZES[options.page];
54
+ const fonts = FONT_PRESETS[options.fonts];
55
+ const fontBody = formatFontStack(fonts.body, options.fontFallback);
56
+ const fontHeading = formatFontStack(fonts.heading, options.fontFallback);
57
+ const fontMono = formatFontStack(fonts.mono, options.fontFallback);
58
+ const target = options.theme === "both" ? "screen" : options.theme;
59
+ const themeBlock = options.theme !== "screen"
60
+ ? [
61
+ " /// Optional print theme overrides for exports.",
62
+ " theme \"print\" {",
63
+ " tokens {",
64
+ " color.text = \"#1b1a17\";",
65
+ " color.muted = \"#6a6258\";",
66
+ " color.accent = \"#0c7f7a\";",
67
+ " }",
68
+ " }",
69
+ ].join("\n")
70
+ : "";
71
+ const assetsBlock = options.assets
72
+ ? [
73
+ " /// Asset banks let you reference local media by id.",
74
+ " assets {",
75
+ " // Asset bank for local images. Drop files into ./assets.",
76
+ " bank media {",
77
+ " kind = image;",
78
+ " root = \"assets\";",
79
+ " include = \"*.{png,jpg,jpeg,svg}\";",
80
+ " strategy = uniform;",
81
+ " }",
82
+ " }",
83
+ ].join("\n")
84
+ : "";
85
+ return [
86
+ "/// Flux document starter generated by `flux new`.",
87
+ "/// Edit meta.title, pageConfig, tokens, and the body sections below.",
88
+ "document {",
89
+ " meta {",
90
+ " /// Human-readable title for exports and viewer tabs.",
91
+ ` title = \"${escapeString(options.title)}\";`,
92
+ " version = \"0.3.0\";",
93
+ " /// Screen is the base target; print theme is optional.",
94
+ ` target = \"${target}\";`,
95
+ " }",
96
+ "",
97
+ " /// Page size and units for layout.",
98
+ " pageConfig {",
99
+ " size {",
100
+ ` width = ${size.width};`,
101
+ ` height = ${size.height};`,
102
+ ` units = \"${size.units}\";`,
103
+ " }",
104
+ " }",
105
+ "",
106
+ " /// Design tokens drive typography, color, and spacing.",
107
+ " tokens {",
108
+ " /// Font stacks include fallbacks unless disabled.",
109
+ ` font.body = \"${fontBody}\";`,
110
+ ` font.heading = \"${fontHeading}\";`,
111
+ ` font.mono = \"${fontMono}\";`,
112
+ " color.text = \"#1d1b17\";",
113
+ " color.muted = \"#6b645a\";",
114
+ " color.accent = \"#0ea5a4\";",
115
+ " color.link = \"#2b4c7e\";",
116
+ " color.calloutBg = \"#f6f1e8\";",
117
+ " color.calloutBorder = \"#d9d0c4\";",
118
+ " space.xs = 2;",
119
+ " space.s = 4;",
120
+ " space.m = 8;",
121
+ " space.l = 12;",
122
+ " space.xl = 18;",
123
+ " }",
124
+ "",
125
+ " /// Style presets referenced by text nodes.",
126
+ " styles {",
127
+ " Body {",
128
+ " font.family = @tokens.font.body;",
129
+ " font.size = 11;",
130
+ " line.height = 1.45;",
131
+ " color = @tokens.color.text;",
132
+ " space.after = @tokens.space.m;",
133
+ " }",
134
+ " H1 : Body {",
135
+ " font.family = @tokens.font.heading;",
136
+ " font.size = 18;",
137
+ " font.weight = 600;",
138
+ " space.before = @tokens.space.m;",
139
+ " space.after = @tokens.space.s;",
140
+ " }",
141
+ " H2 : Body {",
142
+ " font.family = @tokens.font.heading;",
143
+ " font.size = 14;",
144
+ " font.weight = 600;",
145
+ " space.before = @tokens.space.s;",
146
+ " space.after = @tokens.space.xs;",
147
+ " }",
148
+ " Title : H1 {",
149
+ " font.size = 26;",
150
+ " letter.spacing = \"0.02em\";",
151
+ " space.after = @tokens.space.s;",
152
+ " }",
153
+ " Subtitle : Body {",
154
+ " color = @tokens.color.muted;",
155
+ " font.size = 12;",
156
+ " space.after = @tokens.space.m;",
157
+ " }",
158
+ " Lead : Body {",
159
+ " font.size = 12;",
160
+ " line.height = 1.55;",
161
+ " space.after = @tokens.space.m;",
162
+ " }",
163
+ " Byline : Body {",
164
+ " font.size = 10;",
165
+ " color = @tokens.color.muted;",
166
+ " space.after = @tokens.space.s;",
167
+ " }",
168
+ " Abstract : Body {",
169
+ " font.size = 11;",
170
+ " font.style = \"italic\";",
171
+ " space.after = @tokens.space.m;",
172
+ " }",
173
+ " Keywords : Body {",
174
+ " font.size = 9.5;",
175
+ " color = @tokens.color.muted;",
176
+ " space.after = @tokens.space.s;",
177
+ " }",
178
+ " Caption : Body {",
179
+ " font.size = 9.5;",
180
+ " color = @tokens.color.muted;",
181
+ " }",
182
+ " Credit : Body {",
183
+ " font.size = 9;",
184
+ " color = @tokens.color.muted;",
185
+ " }",
186
+ " Quote : Body {",
187
+ " font.style = \"italic\";",
188
+ " background = @tokens.color.calloutBg;",
189
+ " border = \"1pt solid #d9d0c4\";",
190
+ " padding = @tokens.space.s;",
191
+ " space.before = @tokens.space.s;",
192
+ " space.after = @tokens.space.s;",
193
+ " }",
194
+ " Callout : Body {",
195
+ " background = @tokens.color.calloutBg;",
196
+ " border = \"1pt solid #d9d0c4\";",
197
+ " border.radius = 6;",
198
+ " padding = @tokens.space.s;",
199
+ " space.before = @tokens.space.s;",
200
+ " space.after = @tokens.space.s;",
201
+ " }",
202
+ " Code : Body {",
203
+ " font.family = @tokens.font.mono;",
204
+ " font.size = 9.5;",
205
+ " background = \"#f4f0e9\";",
206
+ " padding = @tokens.space.s;",
207
+ " border.radius = 6;",
208
+ " }",
209
+ " }",
210
+ themeBlock,
211
+ assetsBlock,
212
+ extraBlocks.join("\n"),
213
+ "",
214
+ " /// Pages, sections, and content blocks.",
215
+ " body {",
216
+ indent(bodyContent, 2),
217
+ " }",
218
+ "}",
219
+ "",
220
+ ]
221
+ .filter((line) => line !== undefined)
222
+ .join("\n");
223
+ }
224
+ function buildBlankTemplate(options) {
225
+ const body = [
226
+ " body {",
227
+ " // Start building your document.",
228
+ " text \"Title\" {",
229
+ " style = Title;",
230
+ " value = @meta.title;",
231
+ " }",
232
+ " }",
233
+ ].join("\n");
234
+ return {
235
+ mainFlux: buildBaseDoc(options, body, []),
236
+ readme: [
237
+ "# Flux Blank Document",
238
+ "",
239
+ "This is a minimal Flux document starter.",
240
+ "",
241
+ "Next steps:",
242
+ "- Update meta.title and tokens in the .flux file.",
243
+ "- Add sections, figures, and callouts as needed.",
244
+ "- Run `flux view` to open the live viewer.",
245
+ "",
246
+ ].join("\n"),
247
+ chapters: [],
248
+ assetsDir: options.assets ? "assets" : undefined,
249
+ };
250
+ }
251
+ function buildDemoTemplate(options) {
252
+ const liveContent = options.live
253
+ ? [
254
+ "text liveLabel { style = \"H2\"; content = \"Live slots\"; }",
255
+ "text liveBody {",
256
+ " content = \"Docstep: \";",
257
+ " inline_slot liveStep {",
258
+ " reserve = fixedWidth(6, ch);",
259
+ " fit = ellipsis;",
260
+ " refresh = docstep;",
261
+ " text liveValue { content = @docstep; }",
262
+ " }",
263
+ " text liveTail { content = \" - time \"; }",
264
+ " inline_slot liveTime {",
265
+ " reserve = fixedWidth(6, ch);",
266
+ " fit = ellipsis;",
267
+ " refresh = docstep;",
268
+ " text liveTimeValue { content = @time; }",
269
+ " }",
270
+ " text liveTail2 { content = \"s\"; }",
271
+ "}",
272
+ ].join("\n")
273
+ : [
274
+ "text liveLabel { style = \"H2\"; content = \"Static snapshot\"; }",
275
+ "text liveBody { content = \"Live slots disabled. Flip the setting to enable.\"; }",
276
+ ].join("\n");
277
+ const liveSection = [
278
+ " section liveSlots {",
279
+ indent(liveContent, 4),
280
+ " }",
281
+ ].join("\n");
282
+ const assetsContent = options.assets
283
+ ? [
284
+ "figure demoFigure {",
285
+ " label = \"fig:assets\";",
286
+ " slot demoSlot {",
287
+ " reserve = fixed(340, 200, px);",
288
+ " fit = scaleDown;",
289
+ " refresh = docstep;",
290
+ " image demoImage { asset = @assets.pick(noRepeatSteps=2); }",
291
+ " }",
292
+ " text demoCaption { role = \"caption\"; content = \"Figure pulls from ./assets using assets.pick.\"; }",
293
+ " text demoCredit { role = \"credit\"; content = \"Drop images into ./assets to swap.\"; }",
294
+ "}",
295
+ ].join("\n")
296
+ : [
297
+ "slot demoSlot {",
298
+ " reserve = fixed(340, 200, px);",
299
+ " fit = scaleDown;",
300
+ " text demoSlotText { content = \"Enable assets to drop images here.\"; }",
301
+ "}",
302
+ "text demoNote { style = \"Caption\"; content = \"Assets are disabled for this scaffold.\"; }",
303
+ ].join("\n");
304
+ const assetsSection = [
305
+ " section assetsDemo {",
306
+ " text assetsHeading { style = \"H1\"; content = \"Assets + slots\"; }",
307
+ indent(assetsContent, 4),
308
+ " }",
309
+ ].join("\n");
310
+ const body = [
311
+ "page cover {",
312
+ " /// Update the title + subtitle below.",
313
+ " section hero {",
314
+ ` text title { role = \"title\"; style = \"Title\"; content = \"${escapeString(options.title)}\"; }`,
315
+ " text subtitle { role = \"subtitle\"; style = \"Subtitle\"; content = \"A 2026 demo for Flux\"; }",
316
+ " text byline { role = \"byline\"; content = \"Prepared with flux new\"; }",
317
+ " }",
318
+ " section summary {",
319
+ " text summaryHeading { style = \"H1\"; content = \"What to edit next\"; }",
320
+ " text summaryBody { content = \"Replace these paragraphs, tweak styles, and wire assets.\"; }",
321
+ " ul summaryList {",
322
+ " li step1 { text step1Text { content = \"Update meta.title and pageConfig.\"; } }",
323
+ " li step2 { text step2Text { content = \"Swap fonts and colors in tokens.\"; } }",
324
+ " li step3 { text step3Text { content = \"Drop imagery into assets and re-run flux view.\"; } }",
325
+ " }",
326
+ " }",
327
+ "}",
328
+ "page toolkit {",
329
+ " section layout {",
330
+ " text layoutHeading { style = \"H1\"; content = \"Layout primitives\"; }",
331
+ " row layoutRow {",
332
+ " column layoutLeft {",
333
+ " text layoutBody { content = \"Compose pages with rows, columns, and sections. Use slots for live updates.\"; }",
334
+ " text layoutBody2 { content = \"Keep content deterministic while assets and data evolve.\"; }",
335
+ " }",
336
+ " column layoutRight {",
337
+ " callout layoutCallout {",
338
+ " tone = \"note\";",
339
+ " text calloutText { content = \"Sections are the main narrative blocks. Rows and columns help compose grids.\"; }",
340
+ " }",
341
+ " }",
342
+ " }",
343
+ " }",
344
+ liveSection,
345
+ assetsSection,
346
+ "}",
347
+ ...buildChapterIncludes(options.chapters),
348
+ ].join("\n");
349
+ return {
350
+ mainFlux: buildBaseDoc(options, body),
351
+ readme: buildReadme(options),
352
+ chapters: buildChapters(options.chapters),
353
+ assetsDir: options.assets ? "assets" : undefined,
354
+ };
355
+ }
356
+ function buildArticleTemplate(options) {
357
+ const body = [
358
+ "page cover {",
359
+ " section hero {",
360
+ ` text title { role = \"title\"; style = \"Title\"; content = \"${escapeString(options.title)}\"; }`,
361
+ " text subtitle { role = \"subtitle\"; style = \"Subtitle\"; content = \"A narrative article starter\"; }",
362
+ " text byline { role = \"byline\"; content = \"By Your Name\"; }",
363
+ " text deck { style = \"Lead\"; content = \"Write a crisp, curiosity-driven lead that frames the story.\"; }",
364
+ " }",
365
+ " section opener {",
366
+ " text openerHeading { style = \"H1\"; content = \"Opening\"; }",
367
+ " text openerBody { content = \"Set the scene with a concrete moment, then broaden to the stakes.\"; }",
368
+ " }",
369
+ "}",
370
+ "page story {",
371
+ " section context {",
372
+ " text contextHeading { style = \"H1\"; content = \"Context\"; }",
373
+ " text contextBody { content = \"Add background, quotes, and data points that anchor the reader.\"; }",
374
+ " }",
375
+ " section pullQuote {",
376
+ " blockquote quoteBlock { text quoteText { content = \"A single resonant line can carry the chapter.\"; } }",
377
+ " }",
378
+ " section keyPoints {",
379
+ " text keyHeading { style = \"H2\"; content = \"Key points\"; }",
380
+ " ul keyList {",
381
+ " li key1 { text key1Text { content = \"Introduce the main character or idea.\"; } }",
382
+ " li key2 { text key2Text { content = \"Add one surprising detail.\"; } }",
383
+ " li key3 { text key3Text { content = \"Close with the forward-looking question.\"; } }",
384
+ " }",
385
+ " }",
386
+ " callout sidebar {",
387
+ " tone = \"info\";",
388
+ " text sidebarText { content = \"Use callouts for sidebars, stats, or editor notes.\"; }",
389
+ " }",
390
+ "}",
391
+ ...buildChapterIncludes(options.chapters),
392
+ ].join("\n");
393
+ return {
394
+ mainFlux: buildBaseDoc(options, body),
395
+ readme: buildReadme(options),
396
+ chapters: buildChapters(options.chapters),
397
+ assetsDir: options.assets ? "assets" : undefined,
398
+ };
399
+ }
400
+ function buildSpecTemplate(options) {
401
+ const body = [
402
+ "page overview {",
403
+ " section header {",
404
+ ` text title { role = \"title\"; style = \"Title\"; content = \"${escapeString(options.title)}\"; }`,
405
+ " text subtitle { role = \"subtitle\"; style = \"Subtitle\"; content = \"Specification draft\"; }",
406
+ " text byline { role = \"byline\"; content = \"Owner: Team Flux\"; }",
407
+ " }",
408
+ " section summary {",
409
+ " text summaryHeading { style = \"H1\"; content = \"Summary\"; }",
410
+ " text summaryBody { content = \"Describe the problem, the proposed solution, and the intended outcomes.\"; }",
411
+ " }",
412
+ " section goals {",
413
+ " text goalsHeading { style = \"H2\"; content = \"Goals\"; }",
414
+ " ul goalsList {",
415
+ " li goal1 { text goal1Text { content = \"Clarify scope and success criteria.\"; } }",
416
+ " li goal2 { text goal2Text { content = \"Define the primary user experience.\"; } }",
417
+ " li goal3 { text goal3Text { content = \"Document tradeoffs and constraints.\"; } }",
418
+ " }",
419
+ " }",
420
+ "}",
421
+ "page requirements {",
422
+ " section requirements {",
423
+ " text reqHeading { style = \"H1\"; content = \"Requirements\"; }",
424
+ " text reqBody { content = \"List functional and non-functional requirements.\"; }",
425
+ " table reqTable {",
426
+ " rows = [",
427
+ " [\"ID\", \"Requirement\", \"Priority\"],",
428
+ " [\"REQ-1\", \"Describe the core behavior\", \"P0\"],",
429
+ " [\"REQ-2\", \"Define error handling\", \"P1\"],",
430
+ " [\"REQ-3\", \"Document limits and scale\", \"P1\"],",
431
+ " ];",
432
+ " header = true;",
433
+ " }",
434
+ " }",
435
+ " callout constraints {",
436
+ " tone = \"note\";",
437
+ " text constraintsText { content = \"Capture constraints: latency, size, and security expectations.\"; }",
438
+ " }",
439
+ "}",
440
+ "page api {",
441
+ " section api {",
442
+ " text apiHeading { style = \"H1\"; content = \"API sketch\"; }",
443
+ " codeblock apiBlock { content = \"GET /api/status\\nPOST /api/update\"; }",
444
+ " }",
445
+ " section rollout {",
446
+ " text rolloutHeading { style = \"H2\"; content = \"Rollout\"; }",
447
+ " ol rolloutList {",
448
+ " li r1 { text r1Text { content = \"Prototype and verify behavior.\"; } }",
449
+ " li r2 { text r2Text { content = \"Ship behind a flag to pilot users.\"; } }",
450
+ " li r3 { text r3Text { content = \"Measure adoption and iterate.\"; } }",
451
+ " }",
452
+ " }",
453
+ "}",
454
+ ...buildChapterIncludes(options.chapters),
455
+ ].join("\n");
456
+ return {
457
+ mainFlux: buildBaseDoc(options, body),
458
+ readme: buildReadme(options),
459
+ chapters: buildChapters(options.chapters),
460
+ assetsDir: options.assets ? "assets" : undefined,
461
+ };
462
+ }
463
+ function buildZineTemplate(options) {
464
+ const body = [
465
+ "page splash {",
466
+ " section masthead {",
467
+ ` text title { role = \"title\"; style = \"Title\"; content = \"${escapeString(options.title)}\"; }`,
468
+ " text subtitle { role = \"subtitle\"; style = \"Subtitle\"; content = \"Visual zine layout\"; }",
469
+ " text byline { role = \"byline\"; content = \"Issue 01\"; }",
470
+ " }",
471
+ " section opener {",
472
+ " text openerHeading { style = \"H1\"; content = \"Theme\"; }",
473
+ " text openerBody { content = \"Set the mood with a short manifesto or editor note.\"; }",
474
+ " }",
475
+ "}",
476
+ "page collage {",
477
+ " section spread {",
478
+ " text spreadHeading { style = \"H1\"; content = \"Collage spread\"; }",
479
+ " row highlights {",
480
+ " column left {",
481
+ " text leftHeading { style = \"H2\"; content = \"Left column\"; }",
482
+ " text leftBody { content = \"Short bites, captions, and pull quotes.\"; }",
483
+ " slot leftSlot {",
484
+ " reserve = fixed(220, 140, px);",
485
+ " fit = scaleDown;",
486
+ " text leftSlotText { content = \"Drop art here.\"; }",
487
+ " }",
488
+ " }",
489
+ " column right {",
490
+ " text rightHeading { style = \"H2\"; content = \"Right column\"; }",
491
+ " text rightBody { content = \"Add illustration or collage notes.\"; }",
492
+ " callout zineCallout {",
493
+ " tone = \"note\";",
494
+ " text calloutText { content = \"Use callouts for side notes or credits.\"; }",
495
+ " }",
496
+ " }",
497
+ " }",
498
+ " }",
499
+ "}",
500
+ "page backcover {",
501
+ " section notes {",
502
+ " text notesHeading { style = \"H1\"; content = \"Back cover\"; }",
503
+ " text notesBody { content = \"Add credits, links, or closing remarks.\"; }",
504
+ " ul notesList {",
505
+ " li note1 { text note1Text { content = \"Credits and contributors\"; } }",
506
+ " li note2 { text note2Text { content = \"Release notes or version info\"; } }",
507
+ " li note3 { text note3Text { content = \"Contact and next issue\"; } }",
508
+ " }",
509
+ " }",
510
+ "}",
511
+ ...buildChapterIncludes(options.chapters),
512
+ ].join("\n");
513
+ return {
514
+ mainFlux: buildBaseDoc(options, body),
515
+ readme: buildReadme(options),
516
+ chapters: buildChapters(options.chapters),
517
+ assetsDir: options.assets ? "assets" : undefined,
518
+ };
519
+ }
520
+ function buildPaperTemplate(options) {
521
+ const body = [
522
+ "page title {",
523
+ " section titleBlock {",
524
+ ` text title { role = \"title\"; style = \"Title\"; content = \"${escapeString(options.title)}\"; }`,
525
+ " text subtitle { role = \"subtitle\"; style = \"Subtitle\"; content = \"Abstract + references\"; }",
526
+ " text byline { role = \"byline\"; content = \"Author Name, Affiliation\"; }",
527
+ " }",
528
+ " section abstract {",
529
+ " text abstractHeading { style = \"H2\"; content = \"Abstract\"; }",
530
+ " text abstractBody { role = \"abstract\"; content = \"Summarize the contribution in 3-4 sentences.\"; }",
531
+ " text keywords { role = \"keywords\"; content = \"Keywords: flux, layout, rendering\"; }",
532
+ " }",
533
+ "}",
534
+ "page methods {",
535
+ " section methodsBlock {",
536
+ " text methodsHeading { style = \"H1\"; content = \"Methods\"; }",
537
+ " text methodsBody { content = \"Describe the experimental setup or methodology.\"; }",
538
+ " table methodsTable {",
539
+ " rows = [",
540
+ " [\"Step\", \"Description\"],",
541
+ " [\"1\", \"Collect input data\"],",
542
+ " [\"2\", \"Run the core algorithm\"],",
543
+ " [\"3\", \"Evaluate outcomes\"],",
544
+ " ];",
545
+ " header = true;",
546
+ " }",
547
+ " }",
548
+ "}",
549
+ "page results {",
550
+ " section resultsBlock {",
551
+ " text resultsHeading { style = \"H1\"; content = \"Results\"; }",
552
+ " text resultsBody { content = \"Summarize findings and highlight key metrics.\"; }",
553
+ " figure resultsFigure {",
554
+ " label = \"fig:results\";",
555
+ " slot resultsSlot {",
556
+ " reserve = fixed(320, 200, px);",
557
+ " fit = scaleDown;",
558
+ " text resultsSlotText { content = \"Add a chart or diagram.\"; }",
559
+ " }",
560
+ " text resultsCaption { role = \"caption\"; content = \"Figure 1. Primary results.\"; }",
561
+ " }",
562
+ " }",
563
+ "}",
564
+ "page references {",
565
+ " section referencesBlock {",
566
+ " text refHeading { style = \"H1\"; content = \"References\"; }",
567
+ " ol refList {",
568
+ " li ref1 { text ref1Text { content = \"Author, Title, Year\"; } }",
569
+ " li ref2 { text ref2Text { content = \"Author, Title, Year\"; } }",
570
+ " li ref3 { text ref3Text { content = \"Author, Title, Year\"; } }",
571
+ " }",
572
+ " }",
573
+ "}",
574
+ ...buildChapterIncludes(options.chapters),
575
+ ].join("\n");
576
+ return {
577
+ mainFlux: buildBaseDoc(options, body),
578
+ readme: buildReadme(options),
579
+ chapters: buildChapters(options.chapters),
580
+ assetsDir: options.assets ? "assets" : undefined,
581
+ };
582
+ }
583
+ function buildReadme(options) {
584
+ return [
585
+ "# Flux Document",
586
+ "",
587
+ "This folder was generated by `flux new`.",
588
+ "Use it as a starting point for a Flux document or layout experiment.",
589
+ "",
590
+ "## Files",
591
+ "- `<doc>.flux` is the main document source.",
592
+ "- `README.md` (this file) explains the scaffold.",
593
+ options.assets ? "- `assets/` is ready for local images." : "- `assets/` was not created.",
594
+ options.chapters > 0
595
+ ? "- `chapters/` contains chapter fragments included by the main document."
596
+ : "- `chapters/` was not created.",
597
+ "",
598
+ "## Editing basics",
599
+ "- Update `meta.title` for the document name.",
600
+ "- Tweak `pageConfig` for size and units.",
601
+ "- Adjust `tokens` to change fonts, colors, and spacing.",
602
+ "- Update `styles` to restyle headings, captions, and body text.",
603
+ "- Add or reorder content inside the `body` block.",
604
+ options.chapters > 0
605
+ ? "- Chapter fragments are included via `page chapterX` blocks in the main document."
606
+ : "",
607
+ "",
608
+ "## Preview and export",
609
+ "- Run `flux view <doc>.flux` to launch the viewer.",
610
+ "- Run `flux check <doc>.flux` for static checks.",
611
+ "- Run `flux pdf <doc>.flux --out output.pdf` for a snapshot.",
612
+ "",
613
+ "## Options used",
614
+ `Title: ${options.title}`,
615
+ `Page size: ${options.page}`,
616
+ `Theme: ${options.theme}`,
617
+ `Fonts: ${options.fonts}`,
618
+ `Font fallback: ${options.fontFallback === "none" ? "primary only" : "system stack"}`,
619
+ `Assets: ${options.assets ? "enabled" : "disabled"}`,
620
+ `Chapters: ${options.chapters > 0 ? options.chapters : "none"}`,
621
+ `Live slots: ${options.live ? "enabled" : "disabled"}`,
622
+ "",
623
+ ].join("\n");
624
+ }
625
+ function buildChapters(count) {
626
+ const chapters = [];
627
+ for (let i = 1; i <= count; i += 1) {
628
+ const name = `chapter-${i}.flux`;
629
+ const content = [
630
+ "/// Chapter fragment generated by `flux new`.",
631
+ "/// This file is included by the main document.",
632
+ "document {",
633
+ " meta {",
634
+ " version = \"0.3.0\";",
635
+ " }",
636
+ " body {",
637
+ ` section chapter${i} {`,
638
+ ` text heading { style = \"H2\"; content = \"Chapter ${i}\"; }`,
639
+ " text body { content = \"Edit this chapter fragment to build the section.\"; }",
640
+ " callout chapterNote {",
641
+ " tone = \"note\";",
642
+ " text noteBody { content = \"Keep chapter sections modular and focused.\"; }",
643
+ " }",
644
+ " }",
645
+ " }",
646
+ "}",
647
+ "",
648
+ ].join("\n");
649
+ chapters.push({ path: name, content });
650
+ }
651
+ return chapters;
652
+ }
653
+ function buildChapterIncludes(count) {
654
+ if (count <= 0)
655
+ return [];
656
+ const lines = ["", "/// Chapter pages (includes fragments from ./chapters)"];
657
+ for (let i = 1; i <= count; i += 1) {
658
+ lines.push(`page chapter${i} {`);
659
+ lines.push(` include chapter${i} { path = \"chapters/chapter-${i}.flux\"; }`);
660
+ lines.push("}");
661
+ }
662
+ return lines;
663
+ }
664
+ function formatFontStack(font, fallback) {
665
+ if (fallback === "none")
666
+ return font.primary;
667
+ return `${font.primary}, ${font.fallback}`;
668
+ }
669
+ function indent(text, level) {
670
+ const prefix = " ".repeat(level);
671
+ return text
672
+ .split("\n")
673
+ .map((line) => (line.length ? prefix + line : ""))
674
+ .join("\n");
675
+ }
676
+ function escapeString(value) {
677
+ return value.replace(/\\/g, "\\\\").replace(/\"/g, "\\\"");
678
+ }
679
+ //# sourceMappingURL=templates.js.map