wds-init-page.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // wds-init-page.js — WDS scaffold: initialize new page spec
  2. // Usage: node src/scripts/wds-init-page.js --page "01 Start" --scenario "01 Onboarding"
  3. 'use strict';
  4. const fs = require('node:fs');
  5. const path = require('node:path');
  6. function parseArgs(argv) {
  7. const args = {};
  8. for (let i = 0; i < argv.length; i++) {
  9. if (argv[i].startsWith('--')) {
  10. const key = argv[i].slice(2);
  11. const value = argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[i + 1] : true;
  12. args[key] = value;
  13. if (value !== true) i++;
  14. }
  15. }
  16. return args;
  17. }
  18. function toSlug(str) {
  19. return str.toLowerCase().replaceAll(/\s+/g, '-');
  20. }
  21. function printUsage() {
  22. process.stdout.write(
  23. [
  24. 'Usage: node src/scripts/wds-init-page.js --page "01 Start" --scenario "01 Onboarding" [options]',
  25. '',
  26. 'Required:',
  27. ' --page Page name with number, e.g. "01 Start"',
  28. ' --scenario Scenario name, e.g. "01 New User Onboarding"',
  29. '',
  30. 'Optional:',
  31. ' --platform Platform value (default: "Mobile web")',
  32. ' --visibility Visibility value (default: "Public")',
  33. ' --output Base path to write to (default: current directory)',
  34. '',
  35. ].join('\n'),
  36. );
  37. }
  38. function buildTemplate({ pageSlug, pageName, scenarioSlug, scenarioName, platform, visibility }) {
  39. const sketchFile = `sketches/${pageSlug}-concept.jpg`;
  40. const navEmpty = `← [Previous]() | [Next →]()`;
  41. const metaTable = [
  42. '| Property | Value |',
  43. '|----------|-------|',
  44. `| Scenario | ${scenarioName} |`,
  45. `| Page Number | ${pageName.split(' ')[0]} |`,
  46. `| Platform | ${platform} |`,
  47. `| Page Type | — |`,
  48. `| Viewport | — |`,
  49. `| Interaction | — |`,
  50. `| Visibility | ${visibility} |`,
  51. ].join('\n');
  52. const overviewSection = [
  53. '| Property | Value |',
  54. '|----------|-------|',
  55. '| Purpose | — |',
  56. '| User Situation | — |',
  57. '| Success Criteria | — |',
  58. '| Entry Points | — |',
  59. '| Exit Points | — |',
  60. ].join('\n');
  61. const spacingTable = [
  62. '| Token | Direction | Type | Size | Reason |',
  63. '|-------|-----------|------|------|--------|',
  64. `| \`${pageSlug}-v-space-md\` | Vertical | space | md | — |`,
  65. ].join('\n');
  66. const typographyTable = [
  67. '| Element | Semantic | Size | Weight | Typeface |',
  68. '|---------|----------|------|--------|----------|',
  69. '| Page title | H1 | — | — | — |',
  70. ].join('\n');
  71. const statesTable = [
  72. '| State | When | Appearance | Actions |',
  73. '|-------|------|------------|---------|',
  74. '| Default | On load | — | — |',
  75. ].join('\n');
  76. return [
  77. navEmpty,
  78. '',
  79. `![${pageName}](${sketchFile})`,
  80. '',
  81. navEmpty,
  82. '',
  83. '---',
  84. '',
  85. `# ${pageName}`,
  86. '',
  87. '## Page Metadata',
  88. '',
  89. metaTable,
  90. '',
  91. '---',
  92. '',
  93. '## Overview',
  94. '',
  95. overviewSection,
  96. '',
  97. '---',
  98. '',
  99. '## Reference Materials',
  100. '',
  101. '- —',
  102. '',
  103. '---',
  104. '',
  105. '## Layout Structure',
  106. '',
  107. '```',
  108. '+---------------------------+',
  109. '| Header |',
  110. '+---------------------------+',
  111. '| |',
  112. '| Content |',
  113. '| |',
  114. '+---------------------------+',
  115. '| Footer |',
  116. '+---------------------------+',
  117. '```',
  118. '',
  119. '---',
  120. '',
  121. '## Spacing',
  122. '',
  123. spacingTable,
  124. '',
  125. '---',
  126. '',
  127. '## Typography',
  128. '',
  129. typographyTable,
  130. '',
  131. '---',
  132. '',
  133. '## Page Sections',
  134. '',
  135. `### Section: Main`,
  136. '',
  137. `<!-- Objects go here. Use wds-add-object.js to append. -->`,
  138. '',
  139. '---',
  140. '',
  141. '## Page States',
  142. '',
  143. statesTable,
  144. '',
  145. '---',
  146. '',
  147. '## Open Questions',
  148. '',
  149. '- —',
  150. '',
  151. '---',
  152. '',
  153. '## Checklist',
  154. '',
  155. '- [ ] Navigation links updated',
  156. '- [ ] Sketch added',
  157. '- [ ] All objects have SE + EN content',
  158. '- [ ] All Object IDs use correct prefix',
  159. '- [ ] Page States defined',
  160. '- [ ] Spacing tokens defined',
  161. '',
  162. navEmpty,
  163. '',
  164. ].join('\n');
  165. }
  166. function main() {
  167. const args = parseArgs(process.argv.slice(2));
  168. if (args.help) {
  169. printUsage();
  170. process.exit(0);
  171. }
  172. if (!args.page || !args.scenario) {
  173. process.stderr.write('Error: --page and --scenario are required.\n\n');
  174. printUsage();
  175. process.exit(1);
  176. }
  177. const pageName = args.page;
  178. const scenarioName = args.scenario;
  179. const platform = args.platform || 'Mobile web';
  180. const visibility = args.visibility || 'Public';
  181. const outputBase = args.output || process.cwd();
  182. const pageSlug = toSlug(pageName);
  183. const scenarioSlug = toSlug(scenarioName);
  184. const pageDir = path.join(outputBase, 'C-UX-Scenarios', scenarioSlug, pageSlug);
  185. const sketchesDir = path.join(pageDir, 'sketches');
  186. const pageFile = path.join(pageDir, `${pageSlug}.md`);
  187. try {
  188. fs.mkdirSync(pageDir, { recursive: true });
  189. fs.mkdirSync(sketchesDir, { recursive: true });
  190. } catch (error) {
  191. process.stderr.write(`Error creating directories: ${error.message}\n`);
  192. process.exit(1);
  193. }
  194. const content = buildTemplate({ pageSlug, pageName, scenarioSlug, scenarioName, platform, visibility });
  195. try {
  196. fs.writeFileSync(pageFile, content, 'utf8');
  197. } catch (error) {
  198. process.stderr.write(`Error writing file: ${error.message}\n`);
  199. process.exit(1);
  200. }
  201. process.stdout.write(`✓ Created ${pageSlug}.md\n`);
  202. process.stdout.write(` Path: ${pageFile}\n`);
  203. process.stdout.write(` Run wds-nav.js to update navigation links.\n`);
  204. }
  205. main();