From 37cd2453508bb50e07ea0e2d43551e8fa27a7b8f Mon Sep 17 00:00:00 2001 From: Jason Walton Date: Tue, 20 Sep 2022 23:47:43 -0400 Subject: [PATCH] fix: Better rendering of flexible spaces in docs. --- docs/src/css/custom.css | 7 ++ docs/src/remark/kitschPromptPreview.ts | 77 ++++++++++++------- internal/kitsch/modules/context.go | 28 ++++--- internal/kitsch/modules/flexible_space.go | 7 +- .../kitsch/modules/flexible_space_test.go | 11 ++- internal/kitsch/modules/moduleWrapper.go | 2 +- 6 files changed, 90 insertions(+), 42 deletions(-) diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index ad85f32..c8770e0 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -31,3 +31,10 @@ html[data-theme='dark'] .docusaurus-highlight-code-line { background-color: rgba(0, 0, 0, 0.3); } + +.kitschPromptLine { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; +} \ No newline at end of file diff --git a/docs/src/remark/kitschPromptPreview.ts b/docs/src/remark/kitschPromptPreview.ts index 9547fa4..bc19fc6 100644 --- a/docs/src/remark/kitschPromptPreview.ts +++ b/docs/src/remark/kitschPromptPreview.ts @@ -1,14 +1,15 @@ import Convert from "ansi-to-html"; import { execSync } from "child_process"; +import escapeHtml from "escape-html"; import * as fs from "fs"; import { Code, Parent } from "mdast"; +import path from "path"; import tmp from "tmp"; import { Transformer } from "unified"; import visit from "unist-util-visit"; -import escapeHtml from "escape-html"; -import path from "path"; const KITSCH = process.env.KITSCH || "kitsch"; +const FLEX_SPACE = "--space--"; const convert = new Convert({ fg: "#cccccc", @@ -40,27 +41,33 @@ function execCombined( function runKitschPrompt(exmaple: string): string { const configParts = exmaple.split("---"); - let demo: string; - let config: string; + let demoContext: string; + let kitschConfig: string; + if (configParts.length === 2) { - demo = configParts[0]; - config = configParts[1]; + demoContext = configParts[0]; + kitschConfig = configParts[1]; } else { - demo = ""; - config = configParts[0]; + demoContext = ""; + kitschConfig = configParts[0]; } + demoContext += `\nflexibleSpaceReplacement: '${FLEX_SPACE}'`; + // Fix the CWD to be the root of the docs folder. - config = config.replace(/\${CWD}/g, path.join(__dirname, "..", "..")); + kitschConfig = kitschConfig.replace( + /\${CWD}/g, + path.join(__dirname, "..", "..") + ); // Copy the example to a temporary file const demoFile = tmp.fileSync({ postfix: ".yaml" }); - fs.writeFileSync(demoFile.name, demo); + fs.writeFileSync(demoFile.name, demoContext); let options = ""; - if (config.trim()) { + if (kitschConfig.trim()) { const configFile = tmp.fileSync({ postfix: ".yaml" }); - fs.writeFileSync(configFile.name, config); + fs.writeFileSync(configFile.name, kitschConfig); options += ` --config "${configFile.name}"`; } @@ -73,23 +80,20 @@ function runKitschPrompt(exmaple: string): string { let html = escapeMdx(output); - // Convert ANSI to HTML. - html = convert.toHtml(html); - - // Fix each style tag to be a JSX style tag. - html = html.replace(/style="([^"]*)"/g, (match, style) => { - const reactStyle = style - .split(";") - .map((s) => { - const [key, value] = s.split(":"); - return `"${key}": "${value}"`; - }) - .join(","); - - return `style={{${reactStyle}}}`; + // Split up lines at flexible spaces. + const lines = html.split("\n"); + const splitLines = lines.map((line) => { + const parts = line.split(FLEX_SPACE); + if (parts.length > 1) { + return `
${parts + .map(convertToHtml) + .join('')}
`; + } else { + return convertToHtml(line); + } }); - html = html.replace(/\n/g, "
"); + html = splitLines.join(""); return html; } catch (err) { @@ -97,6 +101,25 @@ function runKitschPrompt(exmaple: string): string { } } +export function convertToHtml(ansi: string) { + // Convert ANSI to HTML. + let html = convert.toHtml(ansi); + + // Fix each style tag to be a JSX style tag. + html = html.replace(/style="([^"]*)"/g, (match, style) => { + const reactStyle = style + .split(";") + .map((s) => { + const [key, value] = s.split(":"); + return `"${key}": "${value}"`; + }) + .join(","); + + return `style={{${reactStyle}}}`; + }); + return html; +} + export default function kitschPromptPreview(): Transformer { const transformer: Transformer = async (ast) => { // visit(ast, "jsx", (node: Literal, index: number, parent: Parent) => { diff --git a/internal/kitsch/modules/context.go b/internal/kitsch/modules/context.go index af004e1..37e37ab 100644 --- a/internal/kitsch/modules/context.go +++ b/internal/kitsch/modules/context.go @@ -128,6 +128,10 @@ type Context struct { Styles *styling.Registry // DefaultTimeout is the default module timeout. DefaultTimeout time.Duration + // FlexibleSpaceReplacement is a string to use to replace flexible spaces. + // If set, flexible spaces will be replaced with this sentinel value. + // See DemoConfig.FlexibleSpaceReplacement for details. + FlexibleSpaceReplacement string mutex sync.Mutex gitInitialized bool @@ -214,6 +218,11 @@ type DemoConfig struct { Git gitutils.DemoGit `yaml:"git"` // CWDIsReadOnly is true if the current working directory is read-only. CWDIsReadOnly bool `yaml:"cwdIsReadOnly"` + // FlexibleSpaceReplacement is a string to use to replace flexible spaces. + // This is only used when generating documentation - we replace flexible spaces + // with a sentinel value, and then in documentation generation we can use + // flexbox to make flexible spaces look good in the docs. + FlexibleSpaceReplacement string `yaml:"flexibleSpaceReplacement"` } // Load will load the demo configuration from the specified file. @@ -259,15 +268,16 @@ func NewDemoContext( } return Context{ - Globals: config.Globals, - Directory: fileutils.NewDirectoryTestFS(config.Globals.CWD, demoFsys), - Environment: env.DummyEnv{Env: config.Env}, - ProjectTypes: []projects.ProjectType{}, - ValueCache: cache.NewMemoryCache(), - Styles: styles, - gitInitialized: true, - git: config.Git, - DefaultTimeout: 1000 * time.Millisecond, + Globals: config.Globals, + Directory: fileutils.NewDirectoryTestFS(config.Globals.CWD, demoFsys), + Environment: env.DummyEnv{Env: config.Env}, + ProjectTypes: []projects.ProjectType{}, + ValueCache: cache.NewMemoryCache(), + Styles: styles, + gitInitialized: true, + git: config.Git, + DefaultTimeout: 1000 * time.Millisecond, + FlexibleSpaceReplacement: config.FlexibleSpaceReplacement, } } diff --git a/internal/kitsch/modules/flexible_space.go b/internal/kitsch/modules/flexible_space.go index 4380788..bd04230 100644 --- a/internal/kitsch/modules/flexible_space.go +++ b/internal/kitsch/modules/flexible_space.go @@ -59,9 +59,14 @@ func init() { } // processFlexibleSpaces replaces flexible space markers with spaces. -func processFlexibleSpaces(terminalWidth int, renderedPrompt string) string { +func processFlexibleSpaces(terminalWidth int, renderedPrompt string, replacement string) string { result := "" + if replacement != "" { + // Just replace all the flexible space markers with the provided sentinel value. + return strings.ReplaceAll(renderedPrompt, flexibleSpaceMarker, replacement) + } + // Split into lines. lines := strings.Split(renderedPrompt, "\n") for lineIndex, line := range lines { diff --git a/internal/kitsch/modules/flexible_space_test.go b/internal/kitsch/modules/flexible_space_test.go index d293895..b60b23e 100644 --- a/internal/kitsch/modules/flexible_space_test.go +++ b/internal/kitsch/modules/flexible_space_test.go @@ -7,15 +7,18 @@ import ( ) func TestProcessFlexibleSpaces(t *testing.T) { - result := processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b") + result := processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b", "") assert.Equal(t, "a b", result) - result = processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b\n$ ") + result = processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b\n$ ", "") assert.Equal(t, "a b\n$ ", result) - result = processFlexibleSpaces(10, "ab") + result = processFlexibleSpaces(10, "ab", "") assert.Equal(t, "ab", result) - result = processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b"+flexibleSpaceMarker+"c") + result = processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b"+flexibleSpaceMarker+"c", "") assert.Equal(t, "a b c", result) + + result = processFlexibleSpaces(10, "a"+flexibleSpaceMarker+"b"+flexibleSpaceMarker+"c", "foo") + assert.Equal(t, "afoobfooc", result) } diff --git a/internal/kitsch/modules/moduleWrapper.go b/internal/kitsch/modules/moduleWrapper.go index b9cb7a3..12ccf54 100644 --- a/internal/kitsch/modules/moduleWrapper.go +++ b/internal/kitsch/modules/moduleWrapper.go @@ -214,7 +214,7 @@ func processModuleResult( // RenderPrompt renders the top-level module in a prompt. func RenderPrompt(context *Context, root ModuleWrapper) (ModuleWrapperResult, string) { result := root.Execute(context) - return result, processFlexibleSpaces(context.Globals.TerminalWidth, result.Text) + return result, processFlexibleSpaces(context.Globals.TerminalWidth, result.Text, context.FlexibleSpaceReplacement) } // func testTemplate(context *Context, prefix string, template string, dataMap map[string]interface{}) {