forgebook 0.3.3 → 0.4.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/README.md +914 -72
- package/dist/bin/forgebook/agentClient.d.ts +2 -1
- package/dist/bin/forgebook/agentClient.js +13 -6
- package/dist/bin/forgebook/agentGuide.d.ts +59 -0
- package/dist/bin/forgebook/agentGuide.js +203 -0
- package/dist/bin/forgebook/agentLoopCommands.mjs +22 -42
- package/dist/bin/forgebook/agentSetup/agentFiles.d.ts +55 -0
- package/dist/bin/forgebook/agentSetup/agentFiles.js +319 -0
- package/dist/bin/forgebook/agentSetup/assistantHooks.d.ts +71 -0
- package/dist/bin/forgebook/agentSetup/assistantHooks.js +125 -0
- package/dist/bin/forgebook/agentSetup/ciWorkflow.d.ts +23 -0
- package/dist/bin/forgebook/agentSetup/ciWorkflow.js +55 -0
- package/dist/bin/forgebook/agentSetup/drawCandidates.d.ts +25 -0
- package/dist/bin/forgebook/agentSetup/drawCandidates.js +116 -0
- package/dist/bin/forgebook/agentSetup/drawDiagnosis.d.ts +28 -0
- package/dist/bin/forgebook/agentSetup/drawDiagnosis.js +134 -0
- package/dist/bin/forgebook/agentSetup/drawRun.d.ts +91 -0
- package/dist/bin/forgebook/agentSetup/drawRun.js +353 -0
- package/dist/bin/forgebook/agentSetup/hookNames.d.ts +7 -0
- package/dist/bin/forgebook/agentSetup/hookNames.js +7 -0
- package/dist/bin/forgebook/agentSetup/initAgentSteps.d.ts +48 -0
- package/dist/bin/forgebook/agentSetup/initAgentSteps.js +104 -0
- package/dist/bin/forgebook/agentSetup/liftedProviders.d.ts +17 -0
- package/dist/bin/forgebook/agentSetup/liftedProviders.js +186 -0
- package/dist/bin/forgebook/agentSetup/projectRunner.d.ts +46 -0
- package/dist/bin/forgebook/agentSetup/projectRunner.js +85 -0
- package/dist/bin/forgebook/agentSetup/stopHook.d.ts +65 -0
- package/dist/bin/forgebook/agentSetup/stopHook.js +202 -0
- package/dist/bin/forgebook/agentSetup/uniformPicture.d.ts +7 -0
- package/dist/bin/forgebook/agentSetup/uniformPicture.js +98 -0
- package/dist/bin/forgebook/agentSetupCommands.d.mts +14 -0
- package/dist/bin/forgebook/agentSetupCommands.mjs +98 -0
- package/dist/bin/forgebook/agentText.d.ts +23 -3
- package/dist/bin/forgebook/agentText.js +175 -28
- package/dist/bin/forgebook/agents.md +20 -191
- package/dist/bin/forgebook/agentsText.js +2 -1
- package/dist/bin/forgebook/appBuild/appBuild.d.ts +59 -0
- package/dist/bin/forgebook/appBuild/appBuild.js +213 -0
- package/dist/bin/forgebook/appBuild/appViteConfig.d.ts +96 -0
- package/dist/bin/forgebook/appBuild/appViteConfig.js +320 -0
- package/dist/bin/forgebook/appBuild/tsconfigPaths.d.ts +14 -0
- package/dist/bin/forgebook/appBuild/tsconfigPaths.js +80 -0
- package/dist/bin/forgebook/auditCommand.d.mts +8 -0
- package/dist/bin/forgebook/auditCommand.mjs +75 -0
- package/dist/bin/forgebook/auditRun.d.ts +95 -0
- package/dist/bin/forgebook/auditRun.js +270 -0
- package/dist/bin/forgebook/browserRun.d.ts +21 -0
- package/dist/bin/forgebook/browserRun.js +57 -0
- package/dist/bin/forgebook/buildFailure.d.ts +7 -0
- package/dist/bin/forgebook/buildFailure.js +47 -0
- package/dist/bin/forgebook/buildWatch.d.ts +52 -0
- package/dist/bin/forgebook/buildWatch.js +137 -0
- package/dist/bin/forgebook/builtCatalogue.js +9 -5
- package/dist/bin/forgebook/catalogueCommands.d.ts +9 -0
- package/dist/bin/forgebook/catalogueCommands.js +23 -0
- package/dist/bin/forgebook/catalogueVite.d.ts +5 -1
- package/dist/bin/forgebook/catalogueVite.js +14 -6
- package/dist/bin/forgebook/commandCacheClaim.d.ts +18 -0
- package/dist/bin/forgebook/commandCacheClaim.js +170 -0
- package/dist/bin/forgebook/commandServer.d.ts +8 -0
- package/dist/bin/forgebook/commandServer.js +61 -13
- package/dist/bin/forgebook/forgebookCommands.mjs +105 -28
- package/dist/bin/forgebook/graphCommand.d.mts +8 -0
- package/dist/bin/forgebook/graphCommand.mjs +84 -0
- package/dist/bin/forgebook/guide/commands.md +57 -0
- package/dist/bin/forgebook/guide/devices.md +17 -0
- package/dist/bin/forgebook/guide/docs-pages.md +13 -0
- package/dist/bin/forgebook/guide/frameworks/angular.md +22 -0
- package/dist/bin/forgebook/guide/frameworks/html.md +22 -0
- package/dist/bin/forgebook/guide/frameworks/nextjs.md +23 -0
- package/dist/bin/forgebook/guide/frameworks/nuxt.md +22 -0
- package/dist/bin/forgebook/guide/frameworks/preact.md +16 -0
- package/dist/bin/forgebook/guide/frameworks/react-native-web.md +21 -0
- package/dist/bin/forgebook/guide/frameworks/react.md +16 -0
- package/dist/bin/forgebook/guide/frameworks/solid.md +18 -0
- package/dist/bin/forgebook/guide/frameworks/svelte.md +18 -0
- package/dist/bin/forgebook/guide/frameworks/sveltekit.md +23 -0
- package/dist/bin/forgebook/guide/frameworks/vue.md +18 -0
- package/dist/bin/forgebook/guide/frameworks/web-components.md +21 -0
- package/dist/bin/forgebook/guide/links.md +29 -0
- package/dist/bin/forgebook/guide/setup.md +23 -0
- package/dist/bin/forgebook/guide/stories.md +90 -0
- package/dist/bin/forgebook/guide/switches.md +43 -0
- package/dist/bin/forgebook/guideCommand.d.mts +13 -0
- package/dist/bin/forgebook/guideCommand.mjs +37 -0
- package/dist/bin/forgebook/importers/storybook.d.ts +21 -0
- package/dist/bin/forgebook/importers/storybook.js +11 -5
- package/dist/bin/forgebook/importers/storybookFrameworks.js +1 -1
- package/dist/bin/forgebook/initCommands.d.mts +11 -0
- package/dist/bin/forgebook/initCommands.mjs +51 -78
- package/dist/bin/forgebook/initConfig.d.ts +5 -3
- package/dist/bin/forgebook/initConfig.js +6 -3
- package/dist/bin/forgebook/initInstall.d.ts +15 -0
- package/dist/bin/forgebook/initInstall.js +77 -0
- package/dist/bin/forgebook/initPrint.d.ts +9 -0
- package/dist/bin/forgebook/initPrint.js +60 -0
- package/dist/bin/forgebook/initRefusals.d.ts +45 -0
- package/dist/bin/forgebook/initRefusals.js +91 -0
- package/dist/bin/forgebook/initRun.d.ts +28 -0
- package/dist/bin/forgebook/initRun.js +311 -0
- package/dist/bin/forgebook/mcpCommand.mjs +38 -4
- package/dist/bin/forgebook/mcpGraph.d.ts +13 -0
- package/dist/bin/forgebook/mcpGraph.js +24 -0
- package/dist/bin/forgebook/mcpTokens.d.ts +14 -0
- package/dist/bin/forgebook/mcpTokens.js +58 -0
- package/dist/bin/forgebook/mcpToolParts.d.ts +7 -0
- package/dist/bin/forgebook/mcpToolParts.js +10 -0
- package/dist/bin/forgebook/mcpTools.d.ts +13 -6
- package/dist/bin/forgebook/mcpTools.js +57 -90
- package/dist/bin/forgebook/mcpVerify.d.ts +16 -0
- package/dist/bin/forgebook/mcpVerify.js +36 -0
- package/dist/bin/forgebook/migrate/codemods.d.ts +11 -0
- package/dist/bin/forgebook/migrate/codemods.js +61 -0
- package/dist/bin/forgebook/migrate/migrate.types.d.ts +117 -0
- package/dist/bin/forgebook/migrate/migrate.types.js +5 -0
- package/dist/bin/forgebook/migrate/migrateCommand.d.mts +8 -0
- package/dist/bin/forgebook/migrate/migrateCommand.mjs +76 -0
- package/dist/bin/forgebook/migrate/migrateRun.d.ts +61 -0
- package/dist/bin/forgebook/migrate/migrateRun.js +210 -0
- package/dist/bin/forgebook/migrate/migrateText.d.ts +12 -0
- package/dist/bin/forgebook/migrate/migrateText.js +30 -0
- package/dist/bin/forgebook/migrate/migrateWrite.d.ts +27 -0
- package/dist/bin/forgebook/migrate/migrateWrite.js +66 -0
- package/dist/bin/forgebook/migrate/objectEdits.d.ts +70 -0
- package/dist/bin/forgebook/migrate/objectEdits.js +241 -0
- package/dist/bin/forgebook/migrate/playOnInBuilds.d.ts +3 -0
- package/dist/bin/forgebook/migrate/playOnInBuilds.js +86 -0
- package/dist/bin/forgebook/migrate/propGroupStrings.d.ts +5 -0
- package/dist/bin/forgebook/migrate/propGroupStrings.js +81 -0
- package/dist/bin/forgebook/newProject/newProject.d.ts +39 -0
- package/dist/bin/forgebook/newProject/newProject.js +180 -0
- package/dist/bin/forgebook/newProject/newProject.types.d.ts +97 -0
- package/dist/bin/forgebook/newProject/newProject.types.js +6 -0
- package/dist/bin/forgebook/newProject/packageManagers.d.ts +51 -0
- package/dist/bin/forgebook/newProject/packageManagers.js +121 -0
- package/dist/bin/forgebook/newProject/projectEntries.d.ts +62 -0
- package/dist/bin/forgebook/newProject/projectEntries.js +191 -0
- package/dist/bin/forgebook/newProject/projectFrameworks.d.ts +57 -0
- package/dist/bin/forgebook/newProject/projectFrameworks.js +148 -0
- package/dist/bin/forgebook/newProject/projectLook.d.ts +23 -0
- package/dist/bin/forgebook/newProject/projectLook.js +293 -0
- package/dist/bin/forgebook/newProject/projectPackages.d.ts +66 -0
- package/dist/bin/forgebook/newProject/projectPackages.js +178 -0
- package/dist/bin/forgebook/newRepair.d.ts +45 -0
- package/dist/bin/forgebook/newRepair.js +157 -0
- package/dist/bin/forgebook/newRepairRun.d.ts +69 -0
- package/dist/bin/forgebook/newRepairRun.js +148 -0
- package/dist/bin/forgebook/newStories.d.ts +23 -1
- package/dist/bin/forgebook/newStories.js +101 -11
- package/dist/bin/forgebook/newStoriesFile.d.ts +20 -1
- package/dist/bin/forgebook/newStoriesFile.js +43 -4
- package/dist/bin/forgebook/prebundleRun.d.ts +3 -1
- package/dist/bin/forgebook/prebundleRun.js +28 -8
- package/dist/bin/forgebook/proofCommand.d.mts +15 -0
- package/dist/bin/forgebook/proofCommand.mjs +212 -0
- package/dist/bin/forgebook/proofRun.d.ts +63 -0
- package/dist/bin/forgebook/proofRun.js +412 -0
- package/dist/bin/forgebook/proofText.d.ts +36 -0
- package/dist/bin/forgebook/proofText.js +131 -0
- package/dist/bin/forgebook/proofWorkflow.d.ts +29 -0
- package/dist/bin/forgebook/proofWorkflow.js +205 -0
- package/dist/bin/forgebook/setArgsTool.d.ts +8 -0
- package/dist/bin/forgebook/setArgsTool.js +70 -0
- package/dist/bin/forgebook/storyCheckCommands.mjs +42 -3
- package/dist/bin/forgebook/storyCheckRun.d.ts +50 -0
- package/dist/bin/forgebook/storyCheckRun.js +83 -9
- package/dist/bin/forgebook/storyFileIds.d.ts +15 -0
- package/dist/bin/forgebook/storyFileIds.js +14 -0
- package/dist/bin/forgebook/stressCases.d.ts +31 -0
- package/dist/bin/forgebook/stressCases.js +79 -0
- package/dist/bin/forgebook/stressRun.d.ts +12 -0
- package/dist/bin/forgebook/stressRun.js +61 -0
- package/dist/bin/forgebook/stressText.d.ts +27 -0
- package/dist/bin/forgebook/stressText.js +46 -0
- package/dist/bin/forgebook/verifyBase.d.ts +45 -0
- package/dist/bin/forgebook/verifyBase.js +196 -0
- package/dist/bin/forgebook/verifyCommand.d.mts +13 -0
- package/dist/bin/forgebook/verifyCommand.mjs +125 -0
- package/dist/bin/forgebook/verifyRun.d.ts +63 -0
- package/dist/bin/forgebook/verifyRun.js +108 -0
- package/dist/bin/forgebook/verifyVerdict.d.ts +40 -0
- package/dist/bin/forgebook/verifyVerdict.js +297 -0
- package/dist/bin/forgebook/workflowActions.d.ts +23 -0
- package/dist/bin/forgebook/workflowActions.js +23 -0
- package/dist/bin/forgebook-docs/catalogueMarkdown.js +12 -1
- package/dist/src/addressArgs.d.ts +29 -5
- package/dist/src/addressArgs.js +58 -16
- package/dist/src/addressArgsParam.d.ts +54 -0
- package/dist/src/addressArgsParam.js +51 -0
- package/dist/src/addressTexts.d.ts +14 -0
- package/dist/src/addressTexts.js +28 -21
- package/dist/src/agentIndexFile.d.ts +11 -0
- package/dist/src/agentIndexFile.js +11 -0
- package/dist/src/argConditions.d.ts +52 -0
- package/dist/src/argConditions.js +80 -0
- package/dist/src/argControl.d.ts +100 -0
- package/dist/src/argControl.js +0 -0
- package/dist/src/argExpression.d.ts +21 -0
- package/dist/src/argExpression.js +30 -0
- package/dist/src/argTypes.d.ts +40 -51
- package/dist/src/argTypes.js +66 -184
- package/dist/src/argsProps.d.ts +3 -3
- package/dist/src/argsProps.js +11 -5
- package/dist/src/bundlerErrors.d.ts +29 -0
- package/dist/src/bundlerErrors.js +49 -0
- package/dist/src/catalogue.d.ts +31 -0
- package/dist/src/catalogue.js +13 -2
- package/dist/src/catalogueRefs.d.ts +75 -0
- package/dist/src/catalogueRefs.js +122 -0
- package/dist/src/componentDocs.d.ts +71 -0
- package/dist/src/componentDocs.js +15 -2
- package/dist/src/frame/callValues.d.ts +19 -0
- package/dist/src/frame/callValues.js +58 -0
- package/dist/src/frame/canvasScheme.d.ts +33 -0
- package/dist/src/frame/canvasScheme.js +67 -0
- package/dist/src/frame/frame.css +36 -3
- package/dist/src/frame/frameStatus.d.ts +16 -1
- package/dist/src/frame/frameStatus.js +16 -1
- package/dist/src/frame/frameView.js +4 -3
- package/dist/src/frame/mountFrame.d.ts +7 -1
- package/dist/src/frame/mountFrame.js +153 -46
- package/dist/src/frame/panelValues.d.ts +35 -0
- package/dist/src/frame/panelValues.js +127 -0
- package/dist/src/frame/playActions.d.ts +39 -0
- package/dist/src/frame/playActions.js +98 -0
- package/dist/src/frame/playStepper.d.ts +28 -0
- package/dist/src/frame/playStepper.js +38 -0
- package/dist/src/frame/playStory.d.ts +9 -1
- package/dist/src/frame/playStory.js +49 -3
- package/dist/src/frame/renderer.d.ts +34 -1
- package/dist/src/frame/renderer.js +24 -0
- package/dist/src/frame/shellChannel.d.ts +1 -1
- package/dist/src/frame/shellChannel.js +1 -1
- package/dist/src/frame/shellCheck.d.ts +17 -0
- package/dist/src/frame/shellCheck.js +25 -0
- package/dist/src/frame/shellMessageCheck.d.ts +7 -0
- package/dist/src/frame/shellMessageCheck.js +53 -0
- package/dist/src/frame/storyContent.d.ts +50 -0
- package/dist/src/frame/storyContent.js +73 -0
- package/dist/src/frame/storyModule.d.ts +9 -0
- package/dist/src/frame/storyModule.js +20 -2
- package/dist/src/frame/storyRun.d.ts +15 -7
- package/dist/src/frame/storyRun.js +64 -15
- package/dist/src/frame/valueSheets.d.ts +35 -0
- package/dist/src/frame/valueSheets.js +99 -0
- package/dist/src/hotModules.d.ts +20 -0
- package/dist/src/hotModules.js +23 -0
- package/dist/src/jsxCode.d.ts +1 -14
- package/dist/src/jsxCode.js +46 -10
- package/dist/src/liveErrors.d.ts +30 -4
- package/dist/src/liveErrors.js +18 -3
- package/dist/src/messages.d.ts +77 -27
- package/dist/src/messages.js +58 -100
- package/dist/src/namedValues.d.ts +2 -26
- package/dist/src/namedValues.js +0 -47
- package/dist/src/pageConfig.d.ts +2 -0
- package/dist/src/playTrace.d.ts +19 -2
- package/dist/src/playTrace.js +10 -5
- package/dist/src/plugin.d.ts +10 -3
- package/dist/src/previewRelay.js +9 -1
- package/dist/src/printable.d.ts +12 -0
- package/dist/src/printable.js +22 -0
- package/dist/src/propsSignature.d.ts +37 -0
- package/dist/src/propsSignature.js +40 -0
- package/dist/src/search.d.ts +41 -5
- package/dist/src/search.js +93 -23
- package/dist/src/searchMatch.d.ts +4 -1
- package/dist/src/searchMatch.js +26 -5
- package/dist/src/searchTypos.d.ts +88 -0
- package/dist/src/searchTypos.js +178 -0
- package/dist/src/shapeValues.d.ts +86 -0
- package/dist/src/shapeValues.js +295 -0
- package/dist/src/shell/ApiReference.js +6 -3
- package/dist/src/shell/ApiTableBox.d.ts +15 -0
- package/dist/src/shell/ApiTableBox.js +11 -0
- package/dist/src/shell/AppearanceMenu.d.ts +4 -1
- package/dist/src/shell/AppearanceMenu.js +9 -6
- package/dist/src/shell/CodeTab.d.ts +3 -2
- package/dist/src/shell/CodeTab.js +3 -2
- package/dist/src/shell/CodeText.d.ts +1 -1
- package/dist/src/shell/CodeText.js +2 -3
- package/dist/src/shell/CompareGrid.js +1 -1
- package/dist/src/shell/ComponentPage.d.ts +1 -1
- package/dist/src/shell/ComponentPage.js +5 -1
- package/dist/src/shell/CustomControl.d.ts +34 -0
- package/dist/src/shell/CustomControl.js +132 -0
- package/dist/src/shell/DocContainers.js +1 -1
- package/dist/src/shell/DocPage.js +2 -2
- package/dist/src/shell/DroppedArgsList.d.ts +2 -2
- package/dist/src/shell/DroppedArgsList.js +1 -1
- package/dist/src/shell/EmbedPage.js +30 -12
- package/dist/src/shell/Example.d.ts +5 -1
- package/dist/src/shell/Example.js +16 -8
- package/dist/src/shell/FrameView.d.ts +6 -3
- package/dist/src/shell/FrameView.js +2 -2
- package/dist/src/shell/HomePage.d.ts +3 -1
- package/dist/src/shell/HomePage.js +16 -6
- package/dist/src/shell/InfoTip.js +2 -2
- package/dist/src/shell/InteractionsTab.d.ts +11 -4
- package/dist/src/shell/InteractionsTab.js +18 -2
- package/dist/src/shell/LazyPage.js +1 -1
- package/dist/src/shell/PackageHtml.js +3 -1
- package/dist/src/shell/PinnedControl.js +14 -62
- package/dist/src/shell/PinnedControlMenu.d.ts +44 -0
- package/dist/src/shell/PinnedControlMenu.js +72 -0
- package/dist/src/shell/PropFields.d.ts +3 -1
- package/dist/src/shell/PropFields.js +9 -6
- package/dist/src/shell/PropRows.d.ts +23 -2
- package/dist/src/shell/PropRows.js +58 -19
- package/dist/src/shell/PropsTab.d.ts +12 -5
- package/dist/src/shell/PropsTab.js +9 -21
- package/dist/src/shell/RefStoryPage.d.ts +33 -0
- package/dist/src/shell/RefStoryPage.js +123 -0
- package/dist/src/shell/SearchPanel.js +51 -24
- package/dist/src/shell/Shell.d.ts +18 -0
- package/dist/src/shell/Shell.js +137 -22
- package/dist/src/shell/ShortcutHelp.d.ts +22 -0
- package/dist/src/shell/ShortcutHelp.js +66 -0
- package/dist/src/shell/Sidebar.d.ts +17 -4
- package/dist/src/shell/Sidebar.js +92 -41
- package/dist/src/shell/SidebarDocs.js +2 -2
- package/dist/src/shell/SidebarEntries.js +5 -3
- package/dist/src/shell/SidebarHandle.d.ts +3 -5
- package/dist/src/shell/SidebarHandle.js +4 -4
- package/dist/src/shell/SidebarRefs.d.ts +39 -0
- package/dist/src/shell/SidebarRefs.js +99 -0
- package/dist/src/shell/SidebarSearch.js +37 -9
- package/dist/src/shell/SignatureReference.js +3 -1
- package/dist/src/shell/Stage.d.ts +10 -2
- package/dist/src/shell/Stage.js +29 -49
- package/dist/src/shell/StatusBadges.d.ts +54 -0
- package/dist/src/shell/StatusBadges.js +77 -0
- package/dist/src/shell/StoryCodeBlock.d.ts +8 -19
- package/dist/src/shell/StoryCodeBlock.js +7 -6
- package/dist/src/shell/SwitchGallery.d.ts +36 -0
- package/dist/src/shell/SwitchGallery.js +17 -0
- package/dist/src/shell/SwitchGalleryPanel.d.ts +37 -0
- package/dist/src/shell/SwitchGalleryPanel.js +99 -0
- package/dist/src/shell/TagFilter.d.ts +24 -0
- package/dist/src/shell/TagFilter.js +45 -0
- package/dist/src/shell/TagViews.d.ts +39 -0
- package/dist/src/shell/TagViews.js +20 -0
- package/dist/src/shell/Toolbar.d.ts +4 -1
- package/dist/src/shell/Toolbar.js +17 -7
- package/dist/src/shell/ToolbarControl.d.ts +3 -0
- package/dist/src/shell/ToolbarControl.js +23 -6
- package/dist/src/shell/ViewMenuPanel.js +6 -1
- package/dist/src/shell/argChecks.d.ts +22 -0
- package/dist/src/shell/argChecks.js +20 -0
- package/dist/src/shell/asideStory.js +7 -2
- package/dist/src/shell/audienceSections.css +9 -9
- package/dist/src/shell/catalogueContext.d.ts +1 -1
- package/dist/src/shell/catalogueContext.js +6 -1
- package/dist/src/shell/codeSpans.d.ts +27 -0
- package/dist/src/shell/codeSpans.js +76 -0
- package/dist/src/shell/compareVariants.d.ts +4 -2
- package/dist/src/shell/compareVariants.js +16 -8
- package/dist/src/shell/composition.d.ts +23 -0
- package/dist/src/shell/composition.js +26 -0
- package/dist/src/shell/controlCycle.d.ts +1 -1
- package/dist/src/shell/controlCycle.js +3 -2
- package/dist/src/shell/customControls.d.ts +55 -0
- package/dist/src/shell/customControls.js +70 -0
- package/dist/src/shell/docPage.css +22 -22
- package/dist/src/shell/dockTabs.d.ts +19 -3
- package/dist/src/shell/dockTabs.js +28 -20
- package/dist/src/shell/embed.css +7 -7
- package/dist/src/shell/framesOrigin.d.ts +7 -0
- package/dist/src/shell/framesOrigin.js +1 -1
- package/dist/src/shell/galleryPlace.d.ts +20 -0
- package/dist/src/shell/galleryPlace.js +26 -0
- package/dist/src/shell/icons.d.ts +1 -0
- package/dist/src/shell/icons.js +1 -0
- package/dist/src/shell/keyboard.d.ts +14 -12
- package/dist/src/shell/keyboard.js +21 -6
- package/dist/src/shell/laterStrings.d.ts +29 -0
- package/dist/src/shell/laterStrings.js +42 -3
- package/dist/src/shell/mountShell.js +3 -0
- package/dist/src/shell/pageStrings.d.ts +4 -0
- package/dist/src/shell/pageStrings.js +4 -0
- package/dist/src/shell/pageTagView.d.ts +18 -0
- package/dist/src/shell/pageTagView.js +10 -0
- package/dist/src/shell/playMemory.d.ts +14 -0
- package/dist/src/shell/playMemory.js +8 -0
- package/dist/src/shell/propNotes.d.ts +23 -0
- package/dist/src/shell/propNotes.js +37 -0
- package/dist/src/shell/refIndexLoad.d.ts +17 -0
- package/dist/src/shell/refIndexLoad.js +38 -0
- package/dist/src/shell/refParts.d.ts +34 -0
- package/dist/src/shell/refParts.js +9 -0
- package/dist/src/shell/refStory.css +21 -0
- package/dist/src/shell/refStrings.d.ts +13 -0
- package/dist/src/shell/refStrings.js +21 -0
- package/dist/src/shell/search.css +11 -11
- package/dist/src/shell/shell.css +348 -168
- package/dist/src/shell/shellScheme.js +2 -2
- package/dist/src/shell/shortcutHelp.css +64 -0
- package/dist/src/shell/stageArgs.d.ts +53 -0
- package/dist/src/shell/stageArgs.js +64 -0
- package/dist/src/shell/statusBadges.css +51 -0
- package/dist/src/shell/strings.d.ts +7 -16
- package/dist/src/shell/strings.js +12 -17
- package/dist/src/shell/switchGallery.css +104 -0
- package/dist/src/shell/tagFilter.css +46 -0
- package/dist/src/shell/tagView.d.ts +20 -0
- package/dist/src/shell/tagView.js +10 -0
- package/dist/src/shell/useAddressArgs.d.ts +9 -0
- package/dist/src/shell/useAddressArgs.js +56 -11
- package/dist/src/shell/useControlKeys.js +2 -2
- package/dist/src/shell/useEditedProblems.d.ts +6 -0
- package/dist/src/shell/useEditedProblems.js +40 -0
- package/dist/src/shell/useFrameMessages.js +3 -0
- package/dist/src/shell/useListedTree.d.ts +13 -0
- package/dist/src/shell/useListedTree.js +32 -0
- package/dist/src/shell/usePageFrames.js +2 -2
- package/dist/src/shell/usePopover.d.ts +5 -0
- package/dist/src/shell/usePopover.js +7 -1
- package/dist/src/shell/useRefIndex.d.ts +22 -0
- package/dist/src/shell/useRefIndex.js +36 -0
- package/dist/src/shell/useScrollStops.d.ts +20 -0
- package/dist/src/shell/useScrollStops.js +41 -0
- package/dist/src/shell/useShortcutHelp.d.ts +18 -0
- package/dist/src/shell/useShortcutHelp.js +32 -0
- package/dist/src/shell/useSidebarOverlay.d.ts +2 -1
- package/dist/src/shell/useSidebarOverlay.js +12 -4
- package/dist/src/shell/useStoryCode.d.ts +2 -1
- package/dist/src/shell/useStoryCode.js +12 -7
- package/dist/src/shell/useToolbarLayout.d.ts +5 -1
- package/dist/src/shell/useToolbarLayout.js +2 -2
- package/dist/src/shell/useWorstCase.d.ts +8 -2
- package/dist/src/shell/useWorstCase.js +2 -2
- package/dist/src/shell/valueEditors/FileEditor.d.ts +28 -0
- package/dist/src/shell/valueEditors/FileEditor.js +66 -0
- package/dist/src/shell/valueEditors/JsonEditor.d.ts +14 -0
- package/dist/src/shell/valueEditors/JsonEditor.js +53 -0
- package/dist/src/shell/valueEditors/ListEditor.d.ts +24 -0
- package/dist/src/shell/valueEditors/ListEditor.js +82 -0
- package/dist/src/shell/valueEditors/ObjectEditor.d.ts +32 -0
- package/dist/src/shell/valueEditors/ObjectEditor.js +70 -0
- package/dist/src/shell/valueEditors/PropEditor.d.ts +37 -0
- package/dist/src/shell/valueEditors/PropEditor.js +53 -0
- package/dist/src/shell/valueEditors/RecordEditor.d.ts +20 -0
- package/dist/src/shell/valueEditors/RecordEditor.js +84 -0
- package/dist/src/shell/valueEditors/SearchSelect.d.ts +42 -0
- package/dist/src/shell/valueEditors/SearchSelect.js +80 -0
- package/dist/src/shell/valueEditors/TokenEditor.d.ts +49 -0
- package/dist/src/shell/valueEditors/TokenEditor.js +74 -0
- package/dist/src/shell/valueEditors/UnionEditor.d.ts +20 -0
- package/dist/src/shell/valueEditors/UnionEditor.js +64 -0
- package/dist/src/shell/valueEditors/ValueField.d.ts +15 -0
- package/dist/src/shell/valueEditors/ValueField.js +147 -0
- package/dist/src/shell/valueEditors/editorStrings.d.ts +56 -0
- package/dist/src/shell/valueEditors/editorStrings.js +66 -0
- package/dist/src/shell/valueEditors/fieldTypes.d.ts +31 -0
- package/dist/src/shell/valueEditors/fieldTypes.js +0 -0
- package/dist/src/shell/valueEditors/valueEditors.css +153 -0
- package/dist/src/shell/worstArgs.d.ts +8 -5
- package/dist/src/shell/worstArgs.js +14 -7
- package/dist/src/shellTheme.d.ts +1 -1
- package/dist/src/shellTheme.js +15 -1
- package/dist/src/shellTheme.types.d.ts +4 -0
- package/dist/src/shellWord.d.ts +12 -0
- package/dist/src/shellWord.js +15 -0
- package/dist/src/sourceFiles.js +2 -1
- package/dist/src/storyArgTypes.d.ts +57 -0
- package/dist/src/storyArgTypes.js +195 -0
- package/dist/src/storyBackground.js +14 -3
- package/dist/src/storyCheck.d.ts +85 -3
- package/dist/src/storyCheck.js +23 -1
- package/dist/src/storyCodeText.d.ts +46 -0
- package/dist/src/storyCodeText.js +27 -0
- package/dist/src/storyControls.d.ts +100 -0
- package/dist/src/storyControls.js +100 -0
- package/dist/src/storyStatuses.d.ts +55 -0
- package/dist/src/storyStatuses.js +104 -0
- package/dist/src/storyTagNames.d.ts +25 -0
- package/dist/src/storyTagNames.js +25 -0
- package/dist/src/storyTags.d.ts +29 -0
- package/dist/src/storyTags.js +85 -0
- package/dist/src/storyTree.d.ts +13 -0
- package/dist/src/storyTree.js +24 -4
- package/dist/src/storybookArgs.d.ts +24 -0
- package/dist/src/storybookArgs.js +185 -0
- package/dist/src/switches.d.ts +66 -3
- package/dist/src/switches.js +42 -1
- package/dist/src/valueSchema.d.ts +28 -0
- package/dist/src/valueSchema.js +196 -0
- package/dist/src/valueShape.d.ts +94 -0
- package/dist/src/valueShape.js +25 -0
- package/dist/src/viewState.d.ts +8 -3
- package/dist/src/viewState.js +27 -10
- package/dist/src/vite/adapter.d.ts +40 -2
- package/dist/src/vite/adapter.js +1 -0
- package/dist/src/vite/agent.types.d.ts +347 -7
- package/dist/src/vite/agentApi.d.ts +23 -0
- package/dist/src/vite/agentApi.js +90 -17
- package/dist/src/vite/agentIndex.d.ts +0 -2
- package/dist/src/vite/agentIndex.js +5 -6
- package/dist/src/vite/agentRoutes.d.ts +20 -1
- package/dist/src/vite/agentRoutes.js +106 -65
- package/dist/src/vite/agentStatuses.d.ts +42 -0
- package/dist/src/vite/agentStatuses.js +67 -0
- package/dist/src/vite/agentStoryCode.d.ts +48 -0
- package/dist/src/vite/agentStoryCode.js +38 -0
- package/dist/src/vite/agentVisibility.d.ts +47 -0
- package/dist/src/vite/agentVisibility.js +174 -0
- package/dist/src/vite/appAudit.d.ts +134 -0
- package/dist/src/vite/appAudit.js +333 -0
- package/dist/src/vite/appBuildOption.d.ts +53 -0
- package/dist/src/vite/appBuildOption.js +55 -0
- package/dist/src/vite/appTokenFiles.d.ts +92 -0
- package/dist/src/vite/appTokenFiles.js +433 -0
- package/dist/src/vite/appTokens.d.ts +23 -0
- package/dist/src/vite/appTokens.js +275 -0
- package/dist/src/vite/builtTexts.d.ts +10 -0
- package/dist/src/vite/builtTexts.js +59 -22
- package/dist/src/vite/catalogueConfig.d.ts +3 -1
- package/dist/src/vite/catalogueConfig.js +15 -3
- package/dist/src/vite/changeCoverage.d.ts +74 -0
- package/dist/src/vite/changeCoverage.js +120 -0
- package/dist/src/vite/changedRoute.d.ts +30 -0
- package/dist/src/vite/changedRoute.js +197 -0
- package/dist/src/vite/checkCode.d.ts +105 -3
- package/dist/src/vite/checkCode.js +323 -36
- package/dist/src/vite/checkoutWatch.d.ts +97 -0
- package/dist/src/vite/checkoutWatch.js +287 -0
- package/dist/src/vite/closeWatch.d.ts +8 -0
- package/dist/src/vite/closeWatch.js +1 -1
- package/dist/src/vite/componentCache.d.ts +8 -0
- package/dist/src/vite/componentCache.js +66 -0
- package/dist/src/vite/componentGraph.d.ts +71 -0
- package/dist/src/vite/componentGraph.js +133 -0
- package/dist/src/vite/componentRules.d.ts +33 -0
- package/dist/src/vite/componentRules.js +105 -0
- package/dist/src/vite/componentScan.d.ts +69 -0
- package/dist/src/vite/componentScan.js +418 -0
- package/dist/src/vite/compositionCheck.d.ts +15 -0
- package/dist/src/vite/compositionCheck.js +243 -0
- package/dist/src/vite/config.d.ts +32 -1
- package/dist/src/vite/configFile.d.ts +14 -2
- package/dist/src/vite/configFile.js +124 -40
- package/dist/src/vite/configKeys.d.ts +15 -0
- package/dist/src/vite/configKeys.js +171 -0
- package/dist/src/vite/configLoadError.d.ts +23 -0
- package/dist/src/vite/configLoadError.js +71 -0
- package/dist/src/vite/cssDeclarations.d.ts +71 -0
- package/dist/src/vite/cssDeclarations.js +290 -0
- package/dist/src/vite/cssImports.d.ts +14 -0
- package/dist/src/vite/cssImports.js +48 -0
- package/dist/src/vite/cssReferences.d.ts +54 -0
- package/dist/src/vite/cssReferences.js +157 -0
- package/dist/src/vite/cssTokenValues.d.ts +50 -0
- package/dist/src/vite/cssTokenValues.js +233 -0
- package/dist/src/vite/designTokens.d.ts +24 -0
- package/dist/src/vite/designTokens.js +5 -1
- package/dist/src/vite/docsExtractor.d.ts +9 -3
- package/dist/src/vite/docsExtractor.js +11 -3
- package/dist/src/vite/docsProgram.d.ts +17 -4
- package/dist/src/vite/docsProgram.js +52 -11
- package/dist/src/vite/docsWorker.js +7 -2
- package/dist/src/vite/emptyStoryGlobs.d.ts +41 -0
- package/dist/src/vite/emptyStoryGlobs.js +52 -0
- package/dist/src/vite/fileImports.d.ts +17 -0
- package/dist/src/vite/fileImports.js +57 -0
- package/dist/src/vite/findComponent.d.ts +10 -2
- package/dist/src/vite/findComponent.js +27 -22
- package/dist/src/vite/findRoute.js +3 -2
- package/dist/src/vite/forcedStates.d.ts +9 -2
- package/dist/src/vite/forcedStates.js +12 -3
- package/dist/src/vite/forgebookPlugin.d.ts +2 -0
- package/dist/src/vite/forgebookPlugin.js +52 -72
- package/dist/src/vite/frameErrors.d.ts +19 -0
- package/dist/src/vite/frameErrors.js +70 -0
- package/dist/src/vite/framesServer.d.ts +12 -0
- package/dist/src/vite/framesServer.js +21 -4
- package/dist/src/vite/functionComponentDocs.js +81 -12
- package/dist/src/vite/generatedModules.js +4 -2
- package/dist/src/vite/gitChange.d.ts +38 -5
- package/dist/src/vite/gitChange.js +71 -11
- package/dist/src/vite/hiddenStoryFiles.d.ts +23 -0
- package/dist/src/vite/hiddenStoryFiles.js +107 -0
- package/dist/src/vite/hotSnippets.d.ts +38 -14
- package/dist/src/vite/hotSnippets.js +137 -39
- package/dist/src/vite/importedNames.d.ts +37 -0
- package/dist/src/vite/importedNames.js +138 -0
- package/dist/src/vite/indexFields.d.ts +6 -0
- package/dist/src/vite/indexFields.js +21 -0
- package/dist/src/vite/indexStoryFile.d.ts +8 -1
- package/dist/src/vite/indexStoryFile.js +22 -157
- package/dist/src/vite/jsxCallSites.d.ts +33 -0
- package/dist/src/vite/jsxCallSites.js +200 -0
- package/dist/src/vite/jsxInScripts.d.ts +67 -0
- package/dist/src/vite/jsxInScripts.js +138 -0
- package/dist/src/vite/jsxTree.d.ts +20 -0
- package/dist/src/vite/jsxTree.js +163 -0
- package/dist/src/vite/lineAndColumn.d.ts +13 -0
- package/dist/src/vite/lineAndColumn.js +18 -0
- package/dist/src/vite/lookAlikes.d.ts +65 -0
- package/dist/src/vite/lookAlikes.js +228 -0
- package/dist/src/vite/nearestToken.d.ts +17 -0
- package/dist/src/vite/nearestToken.js +9 -2
- package/dist/src/vite/packageEntries.d.ts +42 -0
- package/dist/src/vite/packageEntries.js +127 -0
- package/dist/src/vite/pages.d.ts +9 -1
- package/dist/src/vite/pages.js +108 -4
- package/dist/src/vite/pluginConfig.js +4 -0
- package/dist/src/vite/pluginIds.d.ts +2 -0
- package/dist/src/vite/pluginIds.js +5 -1
- package/dist/src/vite/pluginModules.d.ts +81 -11
- package/dist/src/vite/pluginModules.js +109 -21
- package/dist/src/vite/prebundled.d.ts +57 -15
- package/dist/src/vite/prebundled.js +80 -0
- package/dist/src/vite/previewTags.d.ts +25 -0
- package/dist/src/vite/previewTags.js +56 -0
- package/dist/src/vite/projectFiles.d.ts +54 -0
- package/dist/src/vite/projectFiles.js +116 -0
- package/dist/src/vite/projectPostcss.d.ts +70 -0
- package/dist/src/vite/projectPostcss.js +250 -0
- package/dist/src/vite/propDocs.d.ts +12 -0
- package/dist/src/vite/propDocs.js +130 -58
- package/dist/src/vite/propKind.d.ts +40 -0
- package/dist/src/vite/propKind.js +71 -0
- package/dist/src/vite/propTypeNotes.d.ts +22 -0
- package/dist/src/vite/propTypeNotes.js +51 -0
- package/dist/src/vite/publishedExports.d.ts +27 -0
- package/dist/src/vite/publishedExports.js +298 -0
- package/dist/src/vite/realFolder.d.ts +6 -0
- package/dist/src/vite/realFolder.js +25 -0
- package/dist/src/vite/refsConfig.d.ts +39 -0
- package/dist/src/vite/refsConfig.js +54 -0
- package/dist/src/vite/reuseCheck.d.ts +45 -0
- package/dist/src/vite/reuseCheck.js +260 -0
- package/dist/src/vite/runningVersions.d.ts +33 -0
- package/dist/src/vite/runningVersions.js +25 -0
- package/dist/src/vite/scriptProblems.d.ts +60 -0
- package/dist/src/vite/scriptProblems.js +155 -0
- package/dist/src/vite/searchModule.js +3 -2
- package/dist/src/vite/searchRoute.js +4 -2
- package/dist/src/vite/shapeDocs.d.ts +36 -0
- package/dist/src/vite/shapeDocs.js +177 -0
- package/dist/src/vite/singleFileComponent.d.ts +17 -0
- package/dist/src/vite/singleFileComponent.js +83 -0
- package/dist/src/vite/sourceText.d.ts +34 -0
- package/dist/src/vite/sourceText.js +72 -0
- package/dist/src/vite/sourceTokens.d.ts +7 -0
- package/dist/src/vite/sourceTokens.js +7 -2
- package/dist/src/vite/stackLines.d.ts +49 -0
- package/dist/src/vite/stackLines.js +96 -0
- package/dist/src/vite/storyCode.d.ts +22 -7
- package/dist/src/vite/storyCode.js +263 -37
- package/dist/src/vite/storyCoverage.d.ts +48 -0
- package/dist/src/vite/storyCoverage.js +179 -0
- package/dist/src/vite/storyFilesModule.d.ts +48 -3
- package/dist/src/vite/storyFilesModule.js +105 -15
- package/dist/src/vite/storyPatterns.d.ts +31 -0
- package/dist/src/vite/storyPatterns.js +140 -5
- package/dist/src/vite/storyReach.d.ts +10 -2
- package/dist/src/vite/storyReach.js +15 -11
- package/dist/src/vite/storyTopLevel.d.ts +51 -0
- package/dist/src/vite/storyTopLevel.js +146 -0
- package/dist/src/vite/storylessRoutes.d.ts +4 -3
- package/dist/src/vite/storylessRoutes.js +210 -19
- package/dist/src/vite/switchValuesCheck.d.ts +19 -0
- package/dist/src/vite/switchValuesCheck.js +164 -0
- package/dist/src/vite/switchesDocument.d.ts +15 -0
- package/dist/src/vite/switchesDocument.js +47 -0
- package/dist/src/vite/tailwindConfigTokens.d.ts +41 -0
- package/dist/src/vite/tailwindConfigTokens.js +306 -0
- package/dist/src/vite/textImports.d.ts +15 -0
- package/dist/src/vite/textImports.js +58 -0
- package/dist/src/vite/textModules.d.ts +6 -5
- package/dist/src/vite/textModules.js +13 -8
- package/dist/src/vite/tokenAnswers.d.ts +6 -2
- package/dist/src/vite/tokenAnswers.js +11 -7
- package/dist/src/vite/typeParameters.d.ts +83 -0
- package/dist/src/vite/typeParameters.js +270 -0
- package/dist/src/vite/unionProps.d.ts +37 -0
- package/dist/src/vite/unionProps.js +121 -0
- package/dist/src/vite/unresolvedTokens.d.ts +20 -0
- package/dist/src/vite/unresolvedTokens.js +193 -0
- package/dist/src/vite/usageGraph.js +10 -52
- package/dist/src/vite/usageGuidance.d.ts +9 -2
- package/dist/src/vite/usageGuidance.js +36 -8
- package/dist/src/vite/usageImports.d.ts +35 -0
- package/dist/src/vite/usageImports.js +280 -0
- package/dist/src/vite/visibilityRoute.d.ts +16 -0
- package/dist/src/vite/visibilityRoute.js +320 -0
- package/dist/src/worstCase.d.ts +2 -0
- package/dist/src/worstCase.js +2 -0
- package/package.json +28 -8
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `forgebook proof` runs: where a change started and the change, each drawn in this run on this machine, and their
|
|
3
|
+
* pictures compared.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Nothing is stored between runs, so there is no baseline for anyone to approve: the "before" is drawn from the merge base
|
|
7
|
+
* here, in a checkout of its own with its own install and its own `forgebook dev`, and thrown away. The folder of baselines
|
|
8
|
+
* a project may keep is never read. Pictures from one machine in one job leave rendering out of the difference, and what
|
|
9
|
+
* still differs is pictured a second time from the same code: a state that differs then too is `unstable`, and proves
|
|
10
|
+
* nothing. The code under review runs in this job and could lie about all of this, so the answer names the files that make
|
|
11
|
+
* the proof whenever the change edits them, for a person to read.
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { execFile, spawn } from "node:child_process";
|
|
16
|
+
import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { createServer } from "node:net";
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import { basename, dirname, join, relative } from "node:path";
|
|
20
|
+
import { promisify } from "node:util";
|
|
21
|
+
import { isStoriesDocument } from "../../src/vite/agentApi.js";
|
|
22
|
+
import { AGENT_API } from "../../src/vite/agentRoutes.js";
|
|
23
|
+
import { findConfigFile } from "../../src/vite/configFile.js";
|
|
24
|
+
import { changeBase, gitOutput, noBaseReason } from "../../src/vite/gitChange.js";
|
|
25
|
+
import { installCommandOf } from "./proofWorkflow.js";
|
|
26
|
+
import { runStoriesDiff, runStoriesShot, testingFunction } from "./storyCheckRun.js";
|
|
27
|
+
const run = promisify(execFile);
|
|
28
|
+
/** How long the base's server may take to answer, in ms: a first start builds its programs and prebundles. */
|
|
29
|
+
const BASE_READY_MS = 300_000;
|
|
30
|
+
/** How much of what the base's server says is kept, in characters. */
|
|
31
|
+
const SERVER_WORDS = 1500;
|
|
32
|
+
/** How long an install may take, in ms. */
|
|
33
|
+
const INSTALL_MS = 900_000;
|
|
34
|
+
/** The files that make the proof, not what it shows: an edit to them is read by a person, whatever the pictures say. */
|
|
35
|
+
export const MAKES_THE_PROOF = /^(?:\.github\/|patches\/|.*(?:forgebook\.(?:config|preview)\.[^/]+|vite\.config\.[^/]+|package\.json|package-lock\.json|pnpm-lock\.yaml|pnpm-workspace\.yaml|yarn\.lock|bun\.lock|\.npmrc|\.yarnrc\.yml|\.pnpmfile\.c?js)$)/;
|
|
36
|
+
/**
|
|
37
|
+
* The listed stories' ids in a catalogue's answer.
|
|
38
|
+
*
|
|
39
|
+
* @param document - the answer.
|
|
40
|
+
*/
|
|
41
|
+
export const listedIds = (document) => document.components.flatMap((component) => component.stories.filter((story) => !story.isUnlisted).map((story) => story.id));
|
|
42
|
+
/**
|
|
43
|
+
* Every story's id in a catalogue's answer, those listed nowhere among them.
|
|
44
|
+
*
|
|
45
|
+
* @param document - the answer.
|
|
46
|
+
*/
|
|
47
|
+
export const allIds = (document) => document.components.flatMap((component) => component.stories.map((story) => story.id));
|
|
48
|
+
/** A port free right now. */
|
|
49
|
+
const freePort = () => new Promise((resolvePort, reject) => {
|
|
50
|
+
const probe = createServer();
|
|
51
|
+
probe.once("error", reject);
|
|
52
|
+
probe.listen(0, "127.0.0.1", () => {
|
|
53
|
+
const address = probe.address();
|
|
54
|
+
const port = typeof address === "object" && address !== null ? address.port : 0;
|
|
55
|
+
probe.close(() => resolvePort(port));
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
/** Waits until a server answers with its stories, or says why it will not. */
|
|
59
|
+
const serverStories = async (origin, server) => {
|
|
60
|
+
const deadline = Date.now() + BASE_READY_MS;
|
|
61
|
+
while (Date.now() < deadline) {
|
|
62
|
+
// a server stopped by a signal has no exit code, and would be waited for to the end
|
|
63
|
+
if (server.exitCode !== null || server.signalCode !== null)
|
|
64
|
+
return `A forgebook dev started for this run stopped (${server.exitCode ?? server.signalCode})`;
|
|
65
|
+
const body = await fetch(`${origin}${AGENT_API}stories`)
|
|
66
|
+
.then((response) => response.json())
|
|
67
|
+
.catch(() => undefined);
|
|
68
|
+
if (isStoriesDocument(body))
|
|
69
|
+
return body;
|
|
70
|
+
await new Promise((wake) => {
|
|
71
|
+
setTimeout(wake, 500);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return `A forgebook dev started for this run did not answer in ${BASE_READY_MS / 1000} s`;
|
|
75
|
+
};
|
|
76
|
+
/** The base's picture of a state, copied beside the others, and the marked one, moved: what a reviewer downloads. */
|
|
77
|
+
const stateOf = (result, out, isUnstable) => {
|
|
78
|
+
const pictures = join(out, "pictures");
|
|
79
|
+
const keep = (file, name) => {
|
|
80
|
+
if (file === undefined || !existsSync(file))
|
|
81
|
+
return undefined;
|
|
82
|
+
const kept = join(pictures, `${name}-${basename(file)}`);
|
|
83
|
+
copyFileSync(file, kept);
|
|
84
|
+
return relative(out, kept).replaceAll("\\", "/");
|
|
85
|
+
};
|
|
86
|
+
const before = result.status === "new" ? undefined : keep(result.baseline, "before");
|
|
87
|
+
const after = result.status === "removed" ? undefined : keep(result.current, "after");
|
|
88
|
+
const marked = keep(result.diff, "marked");
|
|
89
|
+
return {
|
|
90
|
+
storyId: result.storyId,
|
|
91
|
+
view: result.view,
|
|
92
|
+
status: isUnstable ? "unstable" : result.status,
|
|
93
|
+
percent: result.percent,
|
|
94
|
+
pictures: {
|
|
95
|
+
...(before === undefined ? {} : { before }),
|
|
96
|
+
...(after === undefined ? {} : { after }),
|
|
97
|
+
...(marked === undefined ? {} : { marked })
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
/** A state's key in a comparison. */
|
|
102
|
+
const keyOf = (result) => `${result.storyId}\n${result.view}`;
|
|
103
|
+
/** What the change edits of what makes the proof. */
|
|
104
|
+
const ownFilesOf = async (dir, base) => {
|
|
105
|
+
const listed = await gitOutput(dir, "diff", "--no-ext-diff", "--no-relative", "--name-only", "-z", base, "--");
|
|
106
|
+
return listed.split("\0").filter((file) => file !== "" && MAKES_THE_PROOF.test(file));
|
|
107
|
+
};
|
|
108
|
+
/** What was not checked, in words. */
|
|
109
|
+
const notCheckedOf = (verified, ownFiles, leftOut, states, isQuick) => {
|
|
110
|
+
const unstable = states.filter((state) => state.status === "unstable").length;
|
|
111
|
+
const broken = states.filter((state) => state.status === "broken").length;
|
|
112
|
+
return [
|
|
113
|
+
// first: a comment's cap cuts from the end, and this is what must not be lost
|
|
114
|
+
...(ownFiles.length === 0
|
|
115
|
+
? []
|
|
116
|
+
: [`this change edits what makes this proof, so read these yourself: ${ownFiles.join(", ")}`]),
|
|
117
|
+
...verified.skipped,
|
|
118
|
+
...verified.uiFiles.flatMap((file) => file.coverage === "none" ? [`${file.file}: ${file.reason ?? "no story reaches it"}`] : []),
|
|
119
|
+
...verified.notVerified.map((each) => `${each.storyId} (${each.view}): ${each.notVerified}`),
|
|
120
|
+
...(leftOut.length === 0
|
|
121
|
+
? []
|
|
122
|
+
: [`${leftOut.length} stories not pictured, past the limit: ${leftOut.slice(0, 20).join(", ")}`]),
|
|
123
|
+
...(unstable === 0
|
|
124
|
+
? []
|
|
125
|
+
: [`${unstable} states differ between two pictures of the same code: their difference proves nothing`]),
|
|
126
|
+
...(broken === 0 ? [] : [`${broken} states did not draw, so their pictures prove nothing`]),
|
|
127
|
+
...(isQuick ? ["only the default view pictured: --quick"] : []),
|
|
128
|
+
"real pages of the application, and anything no story shows"
|
|
129
|
+
];
|
|
130
|
+
};
|
|
131
|
+
/** The file a manifest's `forgebook` command starts. */
|
|
132
|
+
const binOf = (manifest) => {
|
|
133
|
+
const read = JSON.parse(readFileSync(manifest, "utf8"));
|
|
134
|
+
const bin = typeof read === "object" && read !== null && "bin" in read ? read.bin : undefined;
|
|
135
|
+
const file = typeof bin === "object" && bin !== null && "forgebook" in bin ? bin.forgebook : undefined;
|
|
136
|
+
return typeof file === "string" ? join(dirname(manifest), file) : undefined;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* The file that starts a checkout's own `forgebook`, looked for as Node looks for a package: its manifest is not among
|
|
140
|
+
* what it exports, so it cannot be asked for by name.
|
|
141
|
+
*
|
|
142
|
+
* @param dir - the catalogue's folder in the checkout.
|
|
143
|
+
* @returns the file; none when no Forgebook is installed there.
|
|
144
|
+
*/
|
|
145
|
+
const forgebookEntry = (dir) => {
|
|
146
|
+
let folder = dir;
|
|
147
|
+
while (dirname(folder) !== folder) {
|
|
148
|
+
const manifest = join(folder, "node_modules", "forgebook", "package.json");
|
|
149
|
+
if (existsSync(manifest))
|
|
150
|
+
return binOf(manifest);
|
|
151
|
+
folder = dirname(folder);
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Starts a checkout's own `forgebook dev`, and waits until it answers.
|
|
157
|
+
*
|
|
158
|
+
* @param dir - the catalogue's folder.
|
|
159
|
+
* @param entry - the file that starts its `forgebook`.
|
|
160
|
+
* @param configFile - the configuration file named on the command line, relative to the folder.
|
|
161
|
+
* @returns the server, or why it would not answer.
|
|
162
|
+
*/
|
|
163
|
+
const servedSide = async (dir, entry, configFile) => {
|
|
164
|
+
const port = await freePort();
|
|
165
|
+
const origin = `http://localhost:${port}`;
|
|
166
|
+
const named = configFile === undefined ? [] : ["--config", configFile];
|
|
167
|
+
const server = spawn(process.execPath, [entry, "dev", "--port", String(port), ...named], {
|
|
168
|
+
cwd: dir,
|
|
169
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
170
|
+
});
|
|
171
|
+
// the end of what it says is why it stopped, which a run in CI has no other way to tell
|
|
172
|
+
let said = "";
|
|
173
|
+
server.stderr?.on("data", (part) => {
|
|
174
|
+
said = `${said}${part.toString()}`.slice(-SERVER_WORDS);
|
|
175
|
+
});
|
|
176
|
+
const stories = await serverStories(origin, server);
|
|
177
|
+
if (typeof stories !== "string")
|
|
178
|
+
return {
|
|
179
|
+
origin,
|
|
180
|
+
stories,
|
|
181
|
+
// waited for: the checkout it serves is removed next
|
|
182
|
+
close: () => new Promise((done) => {
|
|
183
|
+
server.once("exit", () => done());
|
|
184
|
+
server.kill();
|
|
185
|
+
})
|
|
186
|
+
};
|
|
187
|
+
server.kill();
|
|
188
|
+
return `${stories}${said === "" ? "" : `: ${said.trim()}`}`;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Draws stories once and throws the pictures away. On a cold server the bundler finds a dependency mid-load and reloads the
|
|
192
|
+
* page, and a frame then pictured nearly empty (a page 19 px tall where the same commit draws 1,068) reads as a change that
|
|
193
|
+
* is not there.
|
|
194
|
+
*
|
|
195
|
+
* @param config - the side's configuration.
|
|
196
|
+
* @param origin - its server.
|
|
197
|
+
* @param input - the stories.
|
|
198
|
+
* @param folder - where to throw them.
|
|
199
|
+
*/
|
|
200
|
+
const warmed = async (config, origin, input, folder) => {
|
|
201
|
+
const shot = await runStoriesShot(config, origin, input, folder);
|
|
202
|
+
return typeof shot === "string" ? shot : undefined;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Pictures the base from its own checkout, install and server.
|
|
206
|
+
*
|
|
207
|
+
* @param reach - the change's catalogue.
|
|
208
|
+
* @param input - what is asked.
|
|
209
|
+
* @param commit - the commit to draw.
|
|
210
|
+
* @param ids - the stories wanted.
|
|
211
|
+
* @param headIds - every story the change has: one the base has and it does not was removed.
|
|
212
|
+
* @param folder - where its pictures go.
|
|
213
|
+
* @returns what it could draw, or why it could not run.
|
|
214
|
+
*/
|
|
215
|
+
const pictureBase = async (reach, input, commit, ids, headIds, folder) => {
|
|
216
|
+
const { config, say } = reach;
|
|
217
|
+
const root = (await gitOutput(config.dir, "rev-parse", "--show-toplevel")).trim();
|
|
218
|
+
const work = mkdtempSync(join(input.work ?? tmpdir(), "forgebook-proof-"));
|
|
219
|
+
const checkout = join(work, "base");
|
|
220
|
+
let served;
|
|
221
|
+
try {
|
|
222
|
+
await gitOutput(root, "worktree", "add", "--quiet", "--detach", checkout, commit);
|
|
223
|
+
const install = input.install ?? installCommandOf(checkout);
|
|
224
|
+
if (install !== undefined && install !== "") {
|
|
225
|
+
say(`Installing the base: ${install}`);
|
|
226
|
+
await run(install, { cwd: checkout, shell: true, timeout: INSTALL_MS, maxBuffer: 64 * 1024 * 1024 });
|
|
227
|
+
}
|
|
228
|
+
// as the server will name it, or the client would not know it for this catalogue: a temporary folder is often a link
|
|
229
|
+
const dir = join(realpathSync(checkout), relative(realpathSync(root), realpathSync(config.dir)));
|
|
230
|
+
const entry = existsSync(dir) && findConfigFile(dir) !== undefined ? forgebookEntry(dir) : undefined;
|
|
231
|
+
if (entry === undefined)
|
|
232
|
+
return { undrawn: [], removed: [], isWithoutCatalogue: true };
|
|
233
|
+
const side = await servedSide(dir, entry, reach.configFile);
|
|
234
|
+
if (typeof side === "string")
|
|
235
|
+
return side;
|
|
236
|
+
served = side;
|
|
237
|
+
const all = new Set(allIds(side.stories));
|
|
238
|
+
const known = ids.filter((id) => all.has(id));
|
|
239
|
+
const gone = listedIds(side.stories).filter((id) => !headIds.has(id));
|
|
240
|
+
const wanted = [...known, ...gone];
|
|
241
|
+
if (wanted.length === 0)
|
|
242
|
+
return { undrawn: [], removed: [] };
|
|
243
|
+
// the change's testing package and browser for both, or two versions would differ by themselves
|
|
244
|
+
const stories = { ids: wanted, isAllVariants: !input.isQuick };
|
|
245
|
+
say("Picturing the base");
|
|
246
|
+
const cold = await warmed(config, side.origin, stories, join(work, "warm"));
|
|
247
|
+
if (cold !== undefined)
|
|
248
|
+
return cold;
|
|
249
|
+
const shot = await runStoriesShot(config, side.origin, stories, folder);
|
|
250
|
+
if (typeof shot === "string")
|
|
251
|
+
return shot;
|
|
252
|
+
const isGone = new Set(gone);
|
|
253
|
+
return {
|
|
254
|
+
undrawn: [
|
|
255
|
+
...new Set(shot.shots.filter((each) => each.status !== undefined).map((each) => each.storyId))
|
|
256
|
+
],
|
|
257
|
+
removed: shot.shots.filter((each) => isGone.has(each.storyId))
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
finally {
|
|
261
|
+
await served?.close();
|
|
262
|
+
await gitOutput(root, "worktree", "remove", "--force", checkout).catch(() => "");
|
|
263
|
+
rmSync(work, { recursive: true, force: true, maxRetries: 3 });
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* Pictures both sides of the stories wanted, then what differs a second time. The change is served as the base is, by its
|
|
268
|
+
* own `forgebook dev` and warmed the same way, so the two pictures differ by the change and not by how they were made.
|
|
269
|
+
*
|
|
270
|
+
* @param reach - the change's catalogue.
|
|
271
|
+
* @param input - what is asked.
|
|
272
|
+
* @param base - the commit the change started from.
|
|
273
|
+
* @param ids - the stories.
|
|
274
|
+
* @param headIds - every story the change has.
|
|
275
|
+
* @param work - a folder to keep the pictures in while this runs.
|
|
276
|
+
*/
|
|
277
|
+
const comparedSides = async (reach, input, base, ids, headIds, work) => {
|
|
278
|
+
const { say } = reach;
|
|
279
|
+
const isAllVariants = !input.isQuick;
|
|
280
|
+
const before = join(work, "before");
|
|
281
|
+
const after = join(work, "after");
|
|
282
|
+
mkdirSync(before);
|
|
283
|
+
const pictured = await pictureBase(reach, input, base, ids, headIds, before);
|
|
284
|
+
if (typeof pictured === "string")
|
|
285
|
+
return pictured;
|
|
286
|
+
const dir = realpathSync(reach.config.dir);
|
|
287
|
+
const config = { ...reach.config, dir };
|
|
288
|
+
const entry = forgebookEntry(dir);
|
|
289
|
+
if (entry === undefined)
|
|
290
|
+
return "This catalogue's folder has no Forgebook installed";
|
|
291
|
+
const side = await servedSide(dir, entry, reach.configFile);
|
|
292
|
+
if (typeof side === "string")
|
|
293
|
+
return side;
|
|
294
|
+
try {
|
|
295
|
+
const stories = { ids, isAllVariants };
|
|
296
|
+
say(`Picturing ${ids.length} stories with the change`);
|
|
297
|
+
const cold = await warmed(config, side.origin, stories, join(work, "warm"));
|
|
298
|
+
if (cold !== undefined)
|
|
299
|
+
return cold;
|
|
300
|
+
const report = await runStoriesDiff(config, side.origin, stories, { baselines: before, outDir: after });
|
|
301
|
+
if (typeof report === "string")
|
|
302
|
+
return report;
|
|
303
|
+
const differing = report.results.filter((each) => each.status === "changed" || each.status === "resized");
|
|
304
|
+
if (differing.length === 0)
|
|
305
|
+
return { report, unstable: new Set(), side: pictured };
|
|
306
|
+
// the same code again: what moves now is noise, and says nothing of the change
|
|
307
|
+
say(`Picturing ${differing.length} differing states a second time`);
|
|
308
|
+
const again = await runStoriesDiff(config, side.origin, { ids: [...new Set(differing.map((each) => each.storyId))], isAllVariants }, { baselines: after, outDir: join(work, "control") });
|
|
309
|
+
if (typeof again === "string")
|
|
310
|
+
return again;
|
|
311
|
+
const unstable = new Set(again.results.filter((each) => each.status !== "same").map(keyOf));
|
|
312
|
+
return { report, unstable, side: pictured };
|
|
313
|
+
}
|
|
314
|
+
finally {
|
|
315
|
+
await side.close();
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
/**
|
|
319
|
+
* Compares a change with where it started, and writes the proof.
|
|
320
|
+
*
|
|
321
|
+
* @param reach - the change's catalogue.
|
|
322
|
+
* @param input - what is asked.
|
|
323
|
+
* @returns the proof, or why there can be none.
|
|
324
|
+
*/
|
|
325
|
+
export const runProof = async (reach, input) => {
|
|
326
|
+
const { config, say } = reach;
|
|
327
|
+
const testing = await testingFunction(config.dir, "@forgebook/testing/diff", "diffStories");
|
|
328
|
+
if (typeof testing === "string")
|
|
329
|
+
return testing;
|
|
330
|
+
const base = await changeBase(config.dir, input.base);
|
|
331
|
+
if (base === undefined)
|
|
332
|
+
return noBaseReason(config.dir, input.base);
|
|
333
|
+
const head = (await gitOutput(config.dir, "rev-parse", "HEAD")).trim();
|
|
334
|
+
say("Verifying the change");
|
|
335
|
+
const verified = await reach.verify(input.base);
|
|
336
|
+
if (typeof verified === "string")
|
|
337
|
+
return verified;
|
|
338
|
+
const stories = await reach.stories();
|
|
339
|
+
if (typeof stories === "string")
|
|
340
|
+
return stories;
|
|
341
|
+
const reached = input.isAll ? listedIds(stories) : await reach.changedIds(input.base);
|
|
342
|
+
if (typeof reached === "string")
|
|
343
|
+
return reached;
|
|
344
|
+
const ids = reached.slice(0, input.maxStories);
|
|
345
|
+
const leftOut = reached.slice(input.maxStories);
|
|
346
|
+
const headIds = new Set(allIds(stories));
|
|
347
|
+
const work = mkdtempSync(join(input.work ?? tmpdir(), "forgebook-pictures-"));
|
|
348
|
+
mkdirSync(join(input.out, "pictures"), { recursive: true });
|
|
349
|
+
try {
|
|
350
|
+
const compared = ids.length === 0
|
|
351
|
+
? {
|
|
352
|
+
report: { schema: 1, results: [] },
|
|
353
|
+
unstable: new Set(),
|
|
354
|
+
side: { undrawn: [], removed: [] }
|
|
355
|
+
}
|
|
356
|
+
: await comparedSides(reach, input, base, ids, headIds, work);
|
|
357
|
+
if (typeof compared === "string")
|
|
358
|
+
return compared;
|
|
359
|
+
const { report, unstable, side } = compared;
|
|
360
|
+
const states = [
|
|
361
|
+
...report.results.flatMap((each) => each.status === "same"
|
|
362
|
+
? []
|
|
363
|
+
: [stateOf({ ...each, status: each.status }, input.out, unstable.has(keyOf(each)))]),
|
|
364
|
+
...side.removed.map((shot) => stateOf({
|
|
365
|
+
storyId: shot.storyId,
|
|
366
|
+
view: shot.view,
|
|
367
|
+
status: "removed",
|
|
368
|
+
changedPixels: 0,
|
|
369
|
+
percent: 100,
|
|
370
|
+
baseline: shot.file,
|
|
371
|
+
current: ""
|
|
372
|
+
}, input.out, false))
|
|
373
|
+
];
|
|
374
|
+
return {
|
|
375
|
+
schema: 1,
|
|
376
|
+
base,
|
|
377
|
+
head,
|
|
378
|
+
verdict: verified.verdict,
|
|
379
|
+
summary: verified.summary,
|
|
380
|
+
states,
|
|
381
|
+
same: report.results.filter((each) => each.status === "same").length,
|
|
382
|
+
checked: [
|
|
383
|
+
`pictures of ${ids.length} stories, ${input.isQuick ? "default view" : "every variant"}, from two builds in this run`,
|
|
384
|
+
`check-code: ${verified.code.checked.join(", ") || "nothing"}`,
|
|
385
|
+
`${verified.ran} story and view pairs through the checks (accessibility, spills, overlays, page errors)`
|
|
386
|
+
],
|
|
387
|
+
notChecked: [
|
|
388
|
+
...notCheckedOf(verified, await ownFilesOf(config.dir, base), leftOut, states, input.isQuick),
|
|
389
|
+
...(side.undrawn.length === 0
|
|
390
|
+
? []
|
|
391
|
+
: [`did not draw at the base, so their "before" proves nothing: ${side.undrawn.join(", ")}`]),
|
|
392
|
+
...(side.isWithoutCatalogue === true
|
|
393
|
+
? ["the base has no catalogue to draw, or no Forgebook installed: every state reads as new"]
|
|
394
|
+
: [])
|
|
395
|
+
]
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
rmSync(work, { recursive: true, force: true, maxRetries: 3 });
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Writes a proof's files.
|
|
404
|
+
*
|
|
405
|
+
* @param out - the folder.
|
|
406
|
+
* @param files - each file's name and text.
|
|
407
|
+
*/
|
|
408
|
+
export const writeProofFiles = (out, files) => {
|
|
409
|
+
mkdirSync(out, { recursive: true });
|
|
410
|
+
for (const [name, text] of Object.entries(files))
|
|
411
|
+
writeFileSync(join(out, name), text);
|
|
412
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `forgebook proof` writes for a person: the pull request's comment and a page of pictures.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Pure. Everything here comes from the branch under review, whose author may be an agent or a stranger: a file or a story
|
|
6
|
+
* can be named anything. This is what the command prints and the run's summary shows; the pull request's comment is written
|
|
7
|
+
* by a job that trusts none of it (`proofWorkflow.ts`). A name only ever appears in a code span or a fenced block, where Markdown does not make a link,
|
|
8
|
+
* an image or a mention of it, and in the page it is escaped. The comment's size is held under what GitHub accepts, cutting
|
|
9
|
+
* whole lines and saying so. A comment that showed only what differs would read as all clear, so what was not checked
|
|
10
|
+
* has a section of its own, always there.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { ProofDocument } from "../../src/vite/agent.types.ts";
|
|
15
|
+
/** What the workflow replaces with the address of the run's pictures, known only once they are uploaded. */
|
|
16
|
+
export declare const ARTIFACT_PLACEHOLDER = "__FORGEBOOK_PROOF_ARTIFACT__";
|
|
17
|
+
/**
|
|
18
|
+
* A name as a Markdown code span, whatever it holds: no line break, a fence longer than any run of backticks in it, and
|
|
19
|
+
* nothing a table reads as a new cell.
|
|
20
|
+
*
|
|
21
|
+
* @param text - the name.
|
|
22
|
+
*/
|
|
23
|
+
export declare const codeSpan: (text: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* The pull request's comment.
|
|
26
|
+
*
|
|
27
|
+
* @param document - the proof.
|
|
28
|
+
* @returns its Markdown, with `ARTIFACT_PLACEHOLDER` where the pictures' address goes.
|
|
29
|
+
*/
|
|
30
|
+
export declare const proofComment: (document: ProofDocument) => string;
|
|
31
|
+
/**
|
|
32
|
+
* The page a reviewer opens from the run's pictures: every state side by side, what was not checked above them.
|
|
33
|
+
*
|
|
34
|
+
* @param document - the proof.
|
|
35
|
+
*/
|
|
36
|
+
export declare const proofPage: (document: ProofDocument) => string;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/** What the workflow replaces with the address of the run's pictures, known only once they are uploaded. */
|
|
2
|
+
export const ARTIFACT_PLACEHOLDER = "__FORGEBOOK_PROOF_ARTIFACT__";
|
|
3
|
+
/** The longest comment written, in characters: GitHub refuses over 65,536. */
|
|
4
|
+
const MAX_COMMENT = 60_000;
|
|
5
|
+
/** What ends a comment that had to be cut. */
|
|
6
|
+
const CUT_ENDING = "\n\nCut here to fit a comment: the rest is in the pictures' `proof.json`.\n";
|
|
7
|
+
/** The most states a comment lists: the rest are in the page. */
|
|
8
|
+
const MAX_LISTED = 40;
|
|
9
|
+
/** The longest name kept in a code span. */
|
|
10
|
+
const MAX_NAME = 120;
|
|
11
|
+
/** A status in the words of a person reading a review. */
|
|
12
|
+
const STATUS_WORDS = {
|
|
13
|
+
changed: "changed",
|
|
14
|
+
resized: "changed size",
|
|
15
|
+
new: "new",
|
|
16
|
+
broken: "did not draw",
|
|
17
|
+
removed: "removed",
|
|
18
|
+
unstable: "unstable: differs between two pictures of the same code"
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* A name as a Markdown code span, whatever it holds: no line break, a fence longer than any run of backticks in it, and
|
|
22
|
+
* nothing a table reads as a new cell.
|
|
23
|
+
*
|
|
24
|
+
* @param text - the name.
|
|
25
|
+
*/
|
|
26
|
+
export const codeSpan = (text) => {
|
|
27
|
+
const flat = text.replace(/[\r\n\t|]+/g, " ").slice(0, MAX_NAME);
|
|
28
|
+
const longest = Math.max(0, ...(flat.match(/`+/g) ?? []).map((run) => run.length));
|
|
29
|
+
const fence = "`".repeat(longest + 1);
|
|
30
|
+
return `${fence} ${flat} ${fence}`;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Lines as a fenced block, whatever they hold: the fence is longer than any run of backticks in them.
|
|
34
|
+
*
|
|
35
|
+
* @param lines - the lines.
|
|
36
|
+
*/
|
|
37
|
+
const fenced = (lines) => {
|
|
38
|
+
const text = lines.join("\n");
|
|
39
|
+
const longest = Math.max(2, ...(text.match(/`+/g) ?? []).map((run) => run.length));
|
|
40
|
+
const fence = "`".repeat(longest + 1);
|
|
41
|
+
return `${fence}text\n${text}\n${fence}`;
|
|
42
|
+
};
|
|
43
|
+
/** One state as a table's row. */
|
|
44
|
+
const stateRow = (state) => `| ${codeSpan(state.storyId)} | ${codeSpan(state.view || "default")} | ${STATUS_WORDS[state.status]} | ${state.percent.toFixed(2)} % |`;
|
|
45
|
+
/** The section listing the states the change touched. */
|
|
46
|
+
const statesSection = (document) => {
|
|
47
|
+
const { states, same } = document;
|
|
48
|
+
if (states.length === 0)
|
|
49
|
+
return [`No picture differs: ${same} compared and the same.`];
|
|
50
|
+
const listed = states.slice(0, MAX_LISTED);
|
|
51
|
+
return [
|
|
52
|
+
`${states.length} differ, ${same} the same.`,
|
|
53
|
+
"",
|
|
54
|
+
"| Story | View | Compared with the base | Pixels |",
|
|
55
|
+
"|---|---|---|---|",
|
|
56
|
+
...listed.map(stateRow),
|
|
57
|
+
...(states.length > listed.length
|
|
58
|
+
? ["", `And ${states.length - listed.length} more, in the pictures.`]
|
|
59
|
+
: [])
|
|
60
|
+
];
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The pull request's comment.
|
|
64
|
+
*
|
|
65
|
+
* @param document - the proof.
|
|
66
|
+
* @returns its Markdown, with `ARTIFACT_PLACEHOLDER` where the pictures' address goes.
|
|
67
|
+
*/
|
|
68
|
+
export const proofComment = (document) => {
|
|
69
|
+
const text = [
|
|
70
|
+
"### Forgebook proof",
|
|
71
|
+
"",
|
|
72
|
+
`Built in this run from ${codeSpan(document.base.slice(0, 12))} and ${codeSpan(document.head.slice(0, 12))}, with no stored picture. [Before and after pictures](${ARTIFACT_PLACEHOLDER}) (open \`index.html\` in the download).`,
|
|
73
|
+
"",
|
|
74
|
+
"#### States touched",
|
|
75
|
+
"",
|
|
76
|
+
...statesSection(document),
|
|
77
|
+
"",
|
|
78
|
+
"#### Checked",
|
|
79
|
+
"",
|
|
80
|
+
fenced([`verdict: ${document.verdict}`, document.summary, ...document.checked]),
|
|
81
|
+
"",
|
|
82
|
+
"#### Not checked",
|
|
83
|
+
"",
|
|
84
|
+
document.notChecked.length === 0 ? "Nothing this run knows of." : fenced(document.notChecked),
|
|
85
|
+
""
|
|
86
|
+
].join("\n");
|
|
87
|
+
if (text.length <= MAX_COMMENT)
|
|
88
|
+
return text;
|
|
89
|
+
const cut = text.slice(0, MAX_COMMENT);
|
|
90
|
+
const whole = cut.slice(0, cut.lastIndexOf("\n"));
|
|
91
|
+
const fences = whole.match(/^`{3,}/gm) ?? [];
|
|
92
|
+
// an unclosed fence would swallow the ending
|
|
93
|
+
return `${whole}${fences.length % 2 === 1 ? `\n${fences.at(-1) ?? "```"}` : ""}${CUT_ENDING}`;
|
|
94
|
+
};
|
|
95
|
+
/** Text as HTML. */
|
|
96
|
+
const escaped = (text) => text
|
|
97
|
+
.replaceAll("&", "&")
|
|
98
|
+
.replaceAll("<", "<")
|
|
99
|
+
.replaceAll(">", ">")
|
|
100
|
+
.replaceAll('"', """)
|
|
101
|
+
.replaceAll("'", "'");
|
|
102
|
+
/** One picture of a state in the page, when it has it and it is one of the run's own: `pictures/…`. */
|
|
103
|
+
const pictureCell = (label, file) => file === undefined || !/^pictures\/[^/]+\.png$/.test(file)
|
|
104
|
+
? ""
|
|
105
|
+
: `<figure><figcaption>${label}</figcaption><a href="${escaped(file)}"><img loading="lazy" alt="${label}" src="${escaped(file)}"></a></figure>`;
|
|
106
|
+
/** One state in the page. */
|
|
107
|
+
const stateBlock = (state) => [
|
|
108
|
+
`<section><h2>${escaped(state.storyId)} <small>${escaped(state.view || "default")}: ${STATUS_WORDS[state.status]}, ${state.percent.toFixed(2)} %</small></h2><div>`,
|
|
109
|
+
pictureCell("Before", state.pictures.before),
|
|
110
|
+
pictureCell("After", state.pictures.after),
|
|
111
|
+
pictureCell("Marked", state.pictures.marked),
|
|
112
|
+
"</div></section>"
|
|
113
|
+
].join("");
|
|
114
|
+
/**
|
|
115
|
+
* The page a reviewer opens from the run's pictures: every state side by side, what was not checked above them.
|
|
116
|
+
*
|
|
117
|
+
* @param document - the proof.
|
|
118
|
+
*/
|
|
119
|
+
export const proofPage = (document) => [
|
|
120
|
+
'<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Forgebook proof</title>',
|
|
121
|
+
// no script runs here, whatever a branch's run wrote in the names of its files
|
|
122
|
+
`<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self'; style-src 'unsafe-inline'">`,
|
|
123
|
+
'<meta name="viewport" content="width=device-width">',
|
|
124
|
+
"<style>:root{color-scheme:light dark;font:14px system-ui}section div{display:flex;flex-wrap:wrap;gap:12px}figure{margin:0;max-width:32%;min-width:240px}img{max-width:100%;border:1px solid #8888}small{font-weight:400}</style>",
|
|
125
|
+
`</head><body><h1>Forgebook proof</h1><p>${escaped(document.base.slice(0, 12))} to ${escaped(document.head.slice(0, 12))}: ${escaped(document.summary)}</p>`,
|
|
126
|
+
"<h2>Not checked</h2><ul>",
|
|
127
|
+
...document.notChecked.map((each) => `<li>${escaped(each)}</li>`),
|
|
128
|
+
"</ul>",
|
|
129
|
+
...document.states.map(stateBlock),
|
|
130
|
+
`<p>${document.same} more compared and the same.</p></body></html>\n`
|
|
131
|
+
].join("");
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Where the workflow is written, from the repository's folder. */
|
|
2
|
+
export declare const WORKFLOW_FILE = ".github/workflows/forgebook-proof.yml";
|
|
3
|
+
/** What finds the comment again, so a new push replaces it. */
|
|
4
|
+
export declare const COMMENT_MARKER = "<!-- forgebook-proof -->";
|
|
5
|
+
/**
|
|
6
|
+
* The command that installs what a checkout locks; none when no lockfile says.
|
|
7
|
+
*
|
|
8
|
+
* @param root - the checkout's folder.
|
|
9
|
+
*/
|
|
10
|
+
export declare const installCommandOf: (root: string) => string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The comment, written from the proof by a job that trusts none of it, as jq reads it: `$files` are the edits GitHub names,
|
|
13
|
+
* `$run` the run's address, `$pictures` the pictures' address once checked. Backticks are written `\u0060` so this stays
|
|
14
|
+
* one template literal.
|
|
15
|
+
*/
|
|
16
|
+
export declare const COMMENT_FILTER: string;
|
|
17
|
+
/**
|
|
18
|
+
* The job that posts, the same for every project.
|
|
19
|
+
*
|
|
20
|
+
* @param download - the action that fetches the proof, as `uses` writes it.
|
|
21
|
+
*/
|
|
22
|
+
export declare const commentJob: (download: string) => string;
|
|
23
|
+
/**
|
|
24
|
+
* The workflow's text.
|
|
25
|
+
*
|
|
26
|
+
* @param root - the repository's folder, whose lockfile names the package manager.
|
|
27
|
+
* @param catalogue - the catalogue's folder, relative to it; empty when it is the repository's.
|
|
28
|
+
*/
|
|
29
|
+
export declare const proofWorkflow: (root: string, catalogue: string) => string;
|