From f2c897a83fd8f2bfebd3aa5524570d43eb779b9a Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Fri, 19 Sep 2025 22:07:13 -0500 Subject: [PATCH 01/14] feat: Integrate Expressive Code with site design - Configure comprehensive style overrides to match site's clean, minimal aesthetic - Use pure white backgrounds and site's CSS variables (--nextflow-green colors) - Set proper text marker highlighting with site's light green accent color - Remove frame titles and switch to 'nextflow' language for syntax highlighting - Maintain advanced highlighting functionality while achieving visual integration - Result: Code blocks now blend seamlessly with site design while providing enhanced educational features The example pages now have clean, professional code blocks that match the site's design system perfectly, with clearly visible line highlighting using the site's signature green color scheme. --- astro.config.mjs | 73 ++++++++- package-lock.json | 313 +++++++++++++++++++++++++++++++++++- package.json | 1 + src/pages/basic-pipeline.md | 2 +- 4 files changed, 378 insertions(+), 11 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 22355017..d2c0ba2d 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -3,7 +3,7 @@ import { defineConfig } from "astro/config"; import remarkDescription from "astro-remark-description"; import remarkDirective from "remark-directive"; import sitemap from "@astrojs/sitemap"; -import { transformerNotationDiff, transformerNotationFocus, transformerMetaHighlight } from "@shikijs/transformers"; +import expressiveCode from "astro-expressive-code"; import react from "@astrojs/react"; import tailwind from "@astrojs/tailwind"; @@ -12,12 +12,6 @@ export default defineConfig({ site: "https://nextflow.io/", outDir: "./output", markdown: { - shikiConfig: { - // Choose from Shiki's built-in themes (or add your own) - // https://shiki.style/themes - theme: "light-plus", - transformers: [transformerNotationDiff(), transformerNotationFocus(), transformerMetaHighlight()], - }, remarkPlugins: [ remarkDirective, admonitionsPlugin, @@ -52,6 +46,71 @@ export default defineConfig({ ], }, integrations: [ + expressiveCode({ + // Use light theme for consistency with site design + themes: ["github-light"], + // Enable advanced features + plugins: ["text-markers", "frames"], + // Comprehensive styling to match site's clean, minimal design + styleOverrides: { + // Core background and text styling - pure white like site + codeBackground: "#ffffff", + codeForeground: "#24292f", // GitHub light theme text color + + // Typography - match site's exact monospace stack + codeFontFamily: "Menlo, Monaco, Consolas, 'Courier New', monospace", + codeFontSize: "0.875rem", // 14px - readable code size + codeLineHeight: "1.5", + + // Borders - subtle gray matching site's container styling + borderColor: "#e5e7eb", // rgb(229, 231, 235) - light gray + borderWidth: "1px", + borderRadius: "0.375rem", // Tailwind rounded-md + + // Text markers - use site's green color scheme for highlighting + textMarkers: { + // Use the site's actual light green color for highlighting + markBackground: "var(--nextflow-light-green)", // Direct use of site color + markBorderColor: "transparent", // Clean, no borders + + // Make highlighting more visible but still clean + backgroundOpacity: "0.4", // More visible highlighting + borderOpacity: "0", // No border opacity + }, + + // Frames - clean, minimal styling + frames: { + // Remove all shadows and heavy styling + shadowColor: "transparent", + frameBoxShadowCssValue: "none", + + // Clean frame styling matching site containers + editorBackground: "#ffffff", + editorActiveTabBackground: "#f9fafb", // Very light gray for active tab + editorActiveTabBorderColor: "#e5e7eb", // Match border color + editorTabBarBackground: "#ffffff", + editorTabBarBorderColor: "#e5e7eb", + + // Terminal-style frame styling + terminalBackground: "#ffffff", + terminalTitlebarBackground: "#f9fafb", + terminalTitlebarForeground: "#6b7280", // Subtle gray text + terminalTitlebarBorderColor: "#e5e7eb", + }, + + // Focus and selection states + focusBorder: "var(--nextflow-green)", // Use site's green for focus + codeSelectionBackground: "var(--nextflow-light-green)", // Use site's light green + + // Scrollbar styling + scrollbarThumbColor: "#d1d5db", // Light gray + scrollbarThumbHoverColor: "#9ca3af", // Slightly darker on hover + + // Ensure clean, minimal appearance throughout + uiSelectionBackground: "var(--nextflow-light-green)", + uiSelectionForeground: "#1f2937", // Dark text for contrast + }, + }), react(), tailwind(), sitemap({ diff --git a/package-lock.json b/package-lock.json index 70340d99..86467d0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@astrojs/sitemap": "^3.1.6", "@shikijs/transformers": "^1.6.3", "astro": "^4.16.1", + "astro-expressive-code": "^0.41.3", "astro-remark-description": "^1.1.2", "react": "^19.0.0", "react-cookie": "^7.2.2", @@ -549,6 +550,15 @@ "node": ">=6.9.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/@emmetio/abbreviation": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", @@ -1014,6 +1024,157 @@ "node": ">=12" } }, + "node_modules/@expressive-code/core": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.3.tgz", + "integrity": "sha512-9qzohqU7O0+JwMEEgQhnBPOw5DtsQRBXhW++5fvEywsuX44vCGGof1SL5OvPElvNgaWZ4pFZAFSlkNOkGyLwSQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.3.tgz", + "integrity": "sha512-rFQtmf/3N2CK3Cq/uERweMTYZnBu+CwxBdHuOftEmfA9iBE7gTVvwpbh82P9ZxkPLvc40UMhYt7uNuAZexycRQ==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.3.tgz", + "integrity": "sha512-RlTARoopzhFJIOVHLGvuXJ8DCEme/hjV+ZnRJBIxzxsKVpGPW4Oshqg9xGhWTYdHstTsxO663s0cdBLzZj9TQA==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3", + "shiki": "^3.2.2" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/@shikijs/core": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.13.0.tgz", + "integrity": "sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.13.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/@shikijs/engine-javascript": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz", + "integrity": "sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.13.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.3" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/@shikijs/engine-oniguruma": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz", + "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.13.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/@shikijs/langs": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz", + "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.13.0" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/@shikijs/themes": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz", + "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.13.0" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/@shikijs/types": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz", + "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/oniguruma-to-es": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", + "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", + "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/@expressive-code/plugin-shiki/node_modules/shiki": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz", + "integrity": "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.13.0", + "@shikijs/engine-javascript": "3.13.0", + "@shikijs/engine-oniguruma": "3.13.0", + "@shikijs/langs": "3.13.0", + "@shikijs/themes": "3.13.0", + "@shikijs/types": "3.13.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.3.tgz", + "integrity": "sha512-SN8tkIzDpA0HLAscEYD2IVrfLiid6qEdE9QLlGVSxO1KEw7qYvjpbNBQjUjMr5/jvTJ7ys6zysU2vLPHE0sb2g==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", @@ -2401,6 +2562,18 @@ "sharp": "^0.33.3" } }, + "node_modules/astro-expressive-code": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.3.tgz", + "integrity": "sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw==", + "license": "MIT", + "dependencies": { + "rehype-expressive-code": "^0.41.3" + }, + "peerDependencies": { + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" + } + }, "node_modules/astro-remark-description": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/astro-remark-description/-/astro-remark-description-1.1.2.tgz", @@ -2602,6 +2775,16 @@ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", "license": "MIT" }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2615,6 +2798,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, "node_modules/boxen": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", @@ -3059,6 +3248,22 @@ "node": ">= 8" } }, + "node_modules/css-selector-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.1.3.tgz", + "integrity": "sha512-gJMigczVZqYAk0hPVzx/M4Hm1D9QOtqkdQk9005TNzDIUGzo5cnHEDiKUT7jGPximL/oYb+LIitcHFQ4aKupxg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -3173,6 +3378,19 @@ "node": ">=0.3.1" } }, + "node_modules/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "license": "MIT", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -3334,6 +3552,18 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/expressive-code": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.3.tgz", + "integrity": "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3", + "@expressive-code/plugin-frames": "^0.41.3", + "@expressive-code/plugin-shiki": "^0.41.3", + "@expressive-code/plugin-text-markers": "^0.41.3" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3700,6 +3930,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", @@ -3751,6 +3994,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", @@ -3803,6 +4073,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-text": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", @@ -5408,6 +5691,18 @@ "node": ">=0.10.0" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5443,6 +5738,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "license": "MIT" + }, "node_modules/oniguruma-to-es": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-2.3.0.tgz", @@ -5830,7 +6131,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5856,7 +6156,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -6093,6 +6392,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-expressive-code": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.3.tgz", + "integrity": "sha512-8d9Py4c/V6I/Od2VIXFAdpiO2kc0SV2qTJsRAaqSIcM9aruW4ASLNe2kOEo1inXAAkIhpFzAHTc358HKbvpNUg==", + "license": "MIT", + "dependencies": { + "expressive-code": "^0.41.3" + } + }, "node_modules/rehype-parse": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", @@ -7319,7 +7627,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/vfile": { diff --git a/package.json b/package.json index dd21a83a..197b13fc 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@astrojs/sitemap": "^3.1.6", "@shikijs/transformers": "^1.6.3", "astro": "^4.16.1", + "astro-expressive-code": "^0.41.3", "astro-remark-description": "^1.1.2", "react": "^19.0.0", "react-cookie": "^7.2.2", diff --git a/src/pages/basic-pipeline.md b/src/pages/basic-pipeline.md index 074e9bc7..cb3ee61e 100644 --- a/src/pages/basic-pipeline.md +++ b/src/pages/basic-pipeline.md @@ -10,7 +10,7 @@ layout: "@layouts/ExampleLayout.astro" This example shows how to write a pipeline with two simple Bash processes, so that the results produced by the first process are consumed by the second process.

-```groovy +```nextflow {1,3,8-18,21-32,39-43} #!/usr/bin/env nextflow params.in = "$baseDir/data/sample.fa" From b40db46371b7779f8d3ab776461656b6f3b3b873 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Sat, 20 Sep 2025 14:04:12 +0300 Subject: [PATCH 02/14] feat: implement Expressive Code with line numbers and improved styling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create separate ec.config.mjs for Expressive Code plugin configuration - Install @expressive-code/plugin-line-numbers plugin - Enable line numbers by default with showLineNumbers: true - Set optimal font size (1.5rem/24px) for better code readability - Simplify astro.config.mjs to use basic expressiveCode() integration - Maintain all existing styling and text marker functionality - Fix MDX Code component compatibility with plugin-based configuration - Support external file imports with ?raw suffix for clean separation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- astro.config.mjs | 69 +- ec.config.mjs | 76 ++ package-lock.json | 673 ++++++++++++++++++ package.json | 2 + src/examples/basic-pipeline.nf | 44 ++ src/layouts/ExampleLayout.astro | 2 - .../{basic-pipeline.md => basic-pipeline.mdx} | 55 +- 7 files changed, 806 insertions(+), 115 deletions(-) create mode 100644 ec.config.mjs create mode 100644 src/examples/basic-pipeline.nf rename src/pages/{basic-pipeline.md => basic-pipeline.mdx} (74%) diff --git a/astro.config.mjs b/astro.config.mjs index d2c0ba2d..5671a456 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -4,6 +4,8 @@ import remarkDescription from "astro-remark-description"; import remarkDirective from "remark-directive"; import sitemap from "@astrojs/sitemap"; import expressiveCode from "astro-expressive-code"; +import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers"; +import mdx from "@astrojs/mdx"; import react from "@astrojs/react"; import tailwind from "@astrojs/tailwind"; @@ -46,71 +48,8 @@ export default defineConfig({ ], }, integrations: [ - expressiveCode({ - // Use light theme for consistency with site design - themes: ["github-light"], - // Enable advanced features - plugins: ["text-markers", "frames"], - // Comprehensive styling to match site's clean, minimal design - styleOverrides: { - // Core background and text styling - pure white like site - codeBackground: "#ffffff", - codeForeground: "#24292f", // GitHub light theme text color - - // Typography - match site's exact monospace stack - codeFontFamily: "Menlo, Monaco, Consolas, 'Courier New', monospace", - codeFontSize: "0.875rem", // 14px - readable code size - codeLineHeight: "1.5", - - // Borders - subtle gray matching site's container styling - borderColor: "#e5e7eb", // rgb(229, 231, 235) - light gray - borderWidth: "1px", - borderRadius: "0.375rem", // Tailwind rounded-md - - // Text markers - use site's green color scheme for highlighting - textMarkers: { - // Use the site's actual light green color for highlighting - markBackground: "var(--nextflow-light-green)", // Direct use of site color - markBorderColor: "transparent", // Clean, no borders - - // Make highlighting more visible but still clean - backgroundOpacity: "0.4", // More visible highlighting - borderOpacity: "0", // No border opacity - }, - - // Frames - clean, minimal styling - frames: { - // Remove all shadows and heavy styling - shadowColor: "transparent", - frameBoxShadowCssValue: "none", - - // Clean frame styling matching site containers - editorBackground: "#ffffff", - editorActiveTabBackground: "#f9fafb", // Very light gray for active tab - editorActiveTabBorderColor: "#e5e7eb", // Match border color - editorTabBarBackground: "#ffffff", - editorTabBarBorderColor: "#e5e7eb", - - // Terminal-style frame styling - terminalBackground: "#ffffff", - terminalTitlebarBackground: "#f9fafb", - terminalTitlebarForeground: "#6b7280", // Subtle gray text - terminalTitlebarBorderColor: "#e5e7eb", - }, - - // Focus and selection states - focusBorder: "var(--nextflow-green)", // Use site's green for focus - codeSelectionBackground: "var(--nextflow-light-green)", // Use site's light green - - // Scrollbar styling - scrollbarThumbColor: "#d1d5db", // Light gray - scrollbarThumbHoverColor: "#9ca3af", // Slightly darker on hover - - // Ensure clean, minimal appearance throughout - uiSelectionBackground: "var(--nextflow-light-green)", - uiSelectionForeground: "#1f2937", // Dark text for contrast - }, - }), + expressiveCode(), + mdx(), react(), tailwind(), sitemap({ diff --git a/ec.config.mjs b/ec.config.mjs new file mode 100644 index 00000000..5c8d704b --- /dev/null +++ b/ec.config.mjs @@ -0,0 +1,76 @@ +import { defineEcConfig } from "astro-expressive-code"; +import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers"; + +export default defineEcConfig({ + // Use light theme for consistency with site design + themes: ["github-light"], + + // Enable advanced features + plugins: [pluginLineNumbers()], + + // Disable Expressive Code's built-in copy button and enable line numbers + defaultProps: { + showCopyToClipboardButton: false, + showLineNumbers: true, + }, + + // Comprehensive styling to match site's clean, minimal design + styleOverrides: { + // Core background and text styling - pure white like site + codeBackground: "#ffffff", + codeForeground: "#24292f", // GitHub light theme text color + + // Typography - match site's exact monospace stack + codeFontFamily: "Menlo, Monaco, Consolas, 'Courier New', monospace", + codeFontSize: "1.5rem", // 24px - much larger, very readable code size + codeLineHeight: "1.5", + + // Borders - subtle gray matching site's container styling + borderColor: "#e5e7eb", // rgb(229, 231, 235) - light gray + borderWidth: "1px", + borderRadius: "0.375rem", // Tailwind rounded-md + + // Text markers - use site's green color scheme for highlighting + textMarkers: { + // Use the site's actual light green color for highlighting + markBackground: "var(--nextflow-light-green)", // Direct use of site color + markBorderColor: "transparent", // Clean, no borders + + // Make highlighting more visible but still clean + backgroundOpacity: "0.4", // More visible highlighting + borderOpacity: "0", // No border opacity + }, + + // Frames - clean, minimal styling + frames: { + // Remove all shadows and heavy styling + shadowColor: "transparent", + frameBoxShadowCssValue: "none", + + // Clean frame styling matching site containers + editorBackground: "#ffffff", + editorActiveTabBackground: "#f9fafb", // Very light gray for active tab + editorActiveTabBorderColor: "#e5e7eb", // Match border color + editorTabBarBackground: "#ffffff", + editorTabBarBorderColor: "#e5e7eb", + + // Terminal-style frame styling + terminalBackground: "#ffffff", + terminalTitlebarBackground: "#f9fafb", + terminalTitlebarForeground: "#6b7280", // Subtle gray text + terminalTitlebarBorderColor: "#e5e7eb", + }, + + // Focus and selection states + focusBorder: "var(--nextflow-green)", // Use site's green for focus + codeSelectionBackground: "var(--nextflow-light-green)", // Use site's light green + + // Scrollbar styling + scrollbarThumbColor: "#d1d5db", // Light gray + scrollbarThumbHoverColor: "#9ca3af", // Slightly darker on hover + + // Ensure clean, minimal appearance throughout + uiSelectionBackground: "var(--nextflow-light-green)", + uiSelectionForeground: "#1f2937", // Dark text for contrast + }, +}); diff --git a/package-lock.json b/package-lock.json index 86467d0c..2bb248b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "0.0.1", "dependencies": { "@astrojs/check": "^0.9.3", + "@astrojs/mdx": "^3.1.9", "@astrojs/react": "^4.2.1", "@astrojs/rss": "^4.0.7", "@astrojs/sitemap": "^3.1.6", + "@expressive-code/plugin-line-numbers": "^0.41.3", "@shikijs/transformers": "^1.6.3", "astro": "^4.16.1", "astro-expressive-code": "^0.41.3", @@ -154,6 +156,34 @@ "vfile": "^6.0.3" } }, + "node_modules/@astrojs/mdx": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-3.1.9.tgz", + "integrity": "sha512-3jPD4Bff6lIA20RQoonnZkRtZ9T3i0HFm6fcDF7BMsKIZ+xBP2KXzQWiuGu62lrVCmU612N+SQVGl5e0fI+zWg==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "5.3.0", + "@mdx-js/mdx": "^3.1.0", + "acorn": "^8.14.0", + "es-module-lexer": "^1.5.4", + "estree-util-visit": "^2.0.0", + "gray-matter": "^4.0.3", + "hast-util-to-html": "^9.0.3", + "kleur": "^4.1.5", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.0", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.4", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": "^18.17.1 || ^20.3.0 || >=21.0.0" + }, + "peerDependencies": { + "astro": "^4.8.0" + } + }, "node_modules/@astrojs/prism": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.1.0.tgz", @@ -1050,6 +1080,15 @@ "@expressive-code/core": "^0.41.3" } }, + "node_modules/@expressive-code/plugin-line-numbers": { + "version": "0.41.3", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-line-numbers/-/plugin-line-numbers-0.41.3.tgz", + "integrity": "sha512-eig82a4CRC3XgVPQ2S/TMDcLiHJokOCD/mAdNVImpD3segVewxfjGgtj5DXQRo0E0q6f0R0EH34YzTFl5CEPqg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.3" + } + }, "node_modules/@expressive-code/plugin-shiki": { "version": "0.41.3", "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.3.tgz", @@ -1645,6 +1684,43 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2113,6 +2189,15 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -2141,6 +2226,12 @@ "@types/unist": "*" } }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -2326,6 +2417,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -2481,6 +2581,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, "node_modules/astro": { "version": "4.16.18", "resolved": "https://registry.npmjs.org/astro/-/astro-4.16.18.tgz", @@ -3149,6 +3258,16 @@ "node": ">=6" } }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -3465,6 +3584,38 @@ "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", "license": "MIT" }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -3537,6 +3688,88 @@ "node": ">=4" } }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -4021,6 +4254,34 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", @@ -4044,6 +4305,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-parse5": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", @@ -4173,6 +4461,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -4641,6 +4935,18 @@ "source-map-js": "^1.2.0" } }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -4841,6 +5147,83 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-phrasing": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", @@ -5156,6 +5539,108 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", @@ -5199,6 +5684,33 @@ "micromark-util-types": "^2.0.0" } }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-factory-space": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", @@ -5400,6 +5912,31 @@ ], "license": "MIT" }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", @@ -6351,6 +6888,73 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/regex": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/regex/-/regex-5.1.1.tgz", @@ -6431,6 +7035,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-stringify": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", @@ -6480,6 +7099,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -6932,6 +7565,15 @@ "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", "license": "MIT" }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7121,6 +7763,24 @@ ], "license": "MIT" }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -7514,6 +8174,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unist-util-remove-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", diff --git a/package.json b/package.json index 197b13fc..51cada0c 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,11 @@ }, "dependencies": { "@astrojs/check": "^0.9.3", + "@astrojs/mdx": "^3.1.9", "@astrojs/react": "^4.2.1", "@astrojs/rss": "^4.0.7", "@astrojs/sitemap": "^3.1.6", + "@expressive-code/plugin-line-numbers": "^0.41.3", "@shikijs/transformers": "^1.6.3", "astro": "^4.16.1", "astro-expressive-code": "^0.41.3", diff --git a/src/examples/basic-pipeline.nf b/src/examples/basic-pipeline.nf new file mode 100644 index 00000000..2fa01043 --- /dev/null +++ b/src/examples/basic-pipeline.nf @@ -0,0 +1,44 @@ +#!/usr/bin/env nextflow + +params.in = "$baseDir/data/sample.fa" + +/* + * Split a fasta file into multiple files + */ +process splitSequences { + + input: + path 'input.fa' + + output: + path 'seq_*' + + """ + awk '/^>/{f="seq_"++d} {print > f}' < input.fa + """ +} + +/* + * Reverse the sequences + */ +process reverse { + + input: + path x + + output: + stdout + + """ + cat $x | rev + """ +} + +/* + * Define the workflow + */ +workflow { + splitSequences(params.in) \ + | reverse \ + | view +} \ No newline at end of file diff --git a/src/layouts/ExampleLayout.astro b/src/layouts/ExampleLayout.astro index b99775ac..f6974555 100644 --- a/src/layouts/ExampleLayout.astro +++ b/src/layouts/ExampleLayout.astro @@ -1,7 +1,6 @@ --- import Page from "./Page.astro"; import ExamplesSideNav from "@components/SideNavigation/ExamplesSideNav"; -import CodeCopyButton from "@components/CodeBlock/CodeCopy"; import "../components/CodeBlock/styles.css"; const { frontmatter } = Astro.props; @@ -21,7 +20,6 @@ const image = frontmatter?.image || "";
- diff --git a/src/pages/basic-pipeline.md b/src/pages/basic-pipeline.mdx similarity index 74% rename from src/pages/basic-pipeline.md rename to src/pages/basic-pipeline.mdx index cb3ee61e..136be2c7 100644 --- a/src/pages/basic-pipeline.md +++ b/src/pages/basic-pipeline.mdx @@ -3,59 +3,18 @@ title: Basic pipeline layout: "@layouts/ExampleLayout.astro" --- +import { Code } from "astro-expressive-code/components"; +import pipelineCode from "../examples/basic-pipeline.nf?raw"; +

Basic pipeline

-

- This example shows how to write a pipeline with two simple Bash processes, so that the results produced by the first process are consumed by the second process. +

+ This example shows how to write a pipeline with two simple Bash processes, so that the results produced by the first + process are consumed by the second process.

-```nextflow {1,3,8-18,21-32,39-43} -#!/usr/bin/env nextflow - -params.in = "$baseDir/data/sample.fa" - -/* - * Split a fasta file into multiple files - */ -process splitSequences { - - input: - path 'input.fa' - - output: - path 'seq_*' - - """ - awk '/^>/{f="seq_"++d} {print > f}' < input.fa - """ -} - -/* - * Reverse the sequences - */ -process reverse { - - input: - path x - - output: - stdout - - """ - cat $x | rev - """ -} - -/* - * Define the workflow - */ -workflow { - splitSequences(params.in) \ - | reverse \ - | view -} -``` +
From 32d1aa21e7503493984272f90c58c29bc859d52c Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Sat, 20 Sep 2025 20:19:52 +0200 Subject: [PATCH 03/14] feat: Reorganize pipeline examples into clean directory structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure pipeline examples from flat files to organized subdirectories under /examples/, with colocated docs and code files. - Move examples.astro → examples/index.astro - Create subdirs: basic-pipeline/, blast-pipeline/, rna-seq-pipeline/, machine-learning-pipeline/, mixing-scripting-languages/ - Extract embedded Nextflow code from .md to separate main.nf files - Convert .md to .mdx with Expressive Code imports - Clean URLs without trailing slashes (/examples/basic-pipeline) - Update all navigation and links to new structure - Fix active page highlighting in side navigation - Add backward compatibility redirects Better organization, consistent patterns, maintainable structure. --- netlify.toml | 31 +++++-- src/components/Footer.astro | 13 +-- src/components/Menu/Menu.tsx | 10 +-- .../SideNavigation/ExamplesSideNav.tsx | 22 +++-- .../basic-pipeline/index.mdx} | 2 +- .../examples/basic-pipeline/main.nf} | 0 src/pages/examples/blast-pipeline/index.mdx | 39 +++++++++ .../blast-pipeline/main.nf} | 38 +-------- .../{examples.astro => examples/index.astro} | 14 ++-- .../machine-learning-pipeline/index.mdx | 40 ++++++++++ .../machine-learning-pipeline/main.nf | 32 ++++++++ .../mixing-scripting-languages/index.mdx | 28 +++++++ .../mixing-scripting-languages/main.nf | 55 +++++++++++++ src/pages/examples/rna-seq-pipeline/index.mdx | 39 +++++++++ .../rna-seq-pipeline/main.nf} | 38 +-------- src/pages/index.astro | 2 +- src/pages/machine-learning-pipeline.md | 69 ---------------- src/pages/mixing-scripting-languages.md | 80 ------------------- 18 files changed, 294 insertions(+), 258 deletions(-) rename src/pages/{basic-pipeline.mdx => examples/basic-pipeline/index.mdx} (97%) rename src/{examples/basic-pipeline.nf => pages/examples/basic-pipeline/main.nf} (100%) create mode 100644 src/pages/examples/blast-pipeline/index.mdx rename src/pages/{blast-pipeline.md => examples/blast-pipeline/main.nf} (62%) rename src/pages/{examples.astro => examples/index.astro} (78%) create mode 100644 src/pages/examples/machine-learning-pipeline/index.mdx create mode 100644 src/pages/examples/machine-learning-pipeline/main.nf create mode 100644 src/pages/examples/mixing-scripting-languages/index.mdx create mode 100644 src/pages/examples/mixing-scripting-languages/main.nf create mode 100644 src/pages/examples/rna-seq-pipeline/index.mdx rename src/pages/{rna-seq-pipeline.md => examples/rna-seq-pipeline/main.nf} (54%) delete mode 100644 src/pages/machine-learning-pipeline.md delete mode 100644 src/pages/mixing-scripting-languages.md diff --git a/netlify.toml b/netlify.toml index 1079e020..ca664d86 100644 --- a/netlify.toml +++ b/netlify.toml @@ -23,20 +23,41 @@ [[redirects]] from = "/example1.html" - to = "/basic-pipeline.html" + to = "/examples/basic-pipeline" [[redirects]] from = "/example2.html" - to = "/mixing-scripting-languages.html" + to = "/examples/mixing-scripting-languages" [[redirects]] from = "/example3.html" - to = "/blast-pipeline.html" + to = "/examples/blast-pipeline" [[redirects]] from = "/example4.html" - to = "/rna-seq-pipeline.html" + to = "/examples/rna-seq-pipeline" [[redirects]] from = "/example5.html" - to = "/machine-learning-pipeline.html" \ No newline at end of file + to = "/examples/machine-learning-pipeline" + +# Direct redirects from old .html files to new structure +[[redirects]] + from = "/basic-pipeline.html" + to = "/examples/basic-pipeline" + +[[redirects]] + from = "/mixing-scripting-languages.html" + to = "/examples/mixing-scripting-languages" + +[[redirects]] + from = "/blast-pipeline.html" + to = "/examples/blast-pipeline" + +[[redirects]] + from = "/rna-seq-pipeline.html" + to = "/examples/rna-seq-pipeline" + +[[redirects]] + from = "/machine-learning-pipeline.html" + to = "/examples/machine-learning-pipeline" \ No newline at end of file diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 97449b1e..799a84a5 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -86,29 +86,30 @@ import LogoSeqera from "../../public/img/assets/Logo_Seqera_whote.svg";
  • Examples
  • - Basic pipeline
  • Mixing scripting languagesMixing scripting languages
  • - BLAST pipeline
  • - RNA-Seq pipeline
  • - Machine Learning pipelineMachine Learning pipeline
  • diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index 248effd5..610a7874 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -192,27 +192,27 @@ const Menu = ({}) => {
    • - + Basic pipeline
    • - + Mixing scripting languages
    • - + BLAST pipeline
    • - + RNA-Seq pipeline
    • - + Machine Learning pipeline
    • diff --git a/src/components/SideNavigation/ExamplesSideNav.tsx b/src/components/SideNavigation/ExamplesSideNav.tsx index f1692785..6ebe90ab 100644 --- a/src/components/SideNavigation/ExamplesSideNav.tsx +++ b/src/components/SideNavigation/ExamplesSideNav.tsx @@ -7,13 +7,11 @@ const ExamplesSideNav = () => { useEffect(() => { if (typeof window !== 'undefined') { const path = window.location.pathname; - const filename = path.split('/').pop(); - - if (filename) { - const match = filename.match(/example(\d+)/); - if (match && match[1]) { - setActiveId(`example${match[1]}`); - } + + // Extract pipeline name from /examples/pipeline-name/ format + const match = path.match(/\/examples\/([^\/]+)\/?$/); + if (match && match[1]) { + setActiveId(match[1]); } } }, []); @@ -22,27 +20,27 @@ const ExamplesSideNav = () => { { id: 'basic-pipeline', title: 'Basic pipeline', - href: 'basic-pipeline.html' + href: '/examples/basic-pipeline' }, { id: 'mixing-scripting-languages', title: 'Mixing scripting languages', - href: 'mixing-scripting-languages.html' + href: '/examples/mixing-scripting-languages' }, { id: 'blast-pipeline', title: 'BLAST pipeline', - href: 'blast-pipeline.html' + href: '/examples/blast-pipeline' }, { id: 'rna-seq-pipeline', title: 'RNA-Seq pipeline', - href: 'rna-seq-pipeline.html' + href: '/examples/rna-seq-pipeline' }, { id: 'machine-learning-pipeline', title: 'Machine Learning pipeline', - href: 'machine-learning-pipeline.html' + href: '/examples/machine-learning-pipeline' } ]; diff --git a/src/pages/basic-pipeline.mdx b/src/pages/examples/basic-pipeline/index.mdx similarity index 97% rename from src/pages/basic-pipeline.mdx rename to src/pages/examples/basic-pipeline/index.mdx index 136be2c7..b4f771a3 100644 --- a/src/pages/basic-pipeline.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -4,7 +4,7 @@ layout: "@layouts/ExampleLayout.astro" --- import { Code } from "astro-expressive-code/components"; -import pipelineCode from "../examples/basic-pipeline.nf?raw"; +import pipelineCode from "./main.nf?raw";

      Basic pipeline

      diff --git a/src/examples/basic-pipeline.nf b/src/pages/examples/basic-pipeline/main.nf similarity index 100% rename from src/examples/basic-pipeline.nf rename to src/pages/examples/basic-pipeline/main.nf diff --git a/src/pages/examples/blast-pipeline/index.mdx b/src/pages/examples/blast-pipeline/index.mdx new file mode 100644 index 00000000..aa280ee3 --- /dev/null +++ b/src/pages/examples/blast-pipeline/index.mdx @@ -0,0 +1,39 @@ +--- +title: BLAST pipeline +layout: "@layouts/ExampleLayout.astro" +--- + +import { Code } from "astro-expressive-code/components"; +import pipelineCode from "./main.nf?raw"; + +
      +

      BLAST pipeline

      + +

      + This example splits a FASTA file into chunks and executes a BLAST query for each chunk in parallel. Then, all the + sequences for the top hits are collected and merged into a single result file. +

      + + + +
      + +### Try it on your computer + +To run this pipeline on your computer, you will need: + +- Unix-like operating system +- Java 17 (or higher) +- Docker + +Install Nextflow by entering the following command in the terminal: + + $ curl -fsSL https://get.nextflow.io | bash + +Then launch the pipeline with this command: + + $ ./nextflow run blast-example -with-docker + +It will automatically download the pipeline [GitHub repository](https://github.com/nextflow-io/blast-example) and the associated Docker images, thus the first execution may take a few minutes to complete depending on your network connection. + +**NOTE**: To run this example with versions of Nextflow older than 22.04.0, you must include the `-dsl2` flag with `nextflow run`. diff --git a/src/pages/blast-pipeline.md b/src/pages/examples/blast-pipeline/main.nf similarity index 62% rename from src/pages/blast-pipeline.md rename to src/pages/examples/blast-pipeline/main.nf index 589443ba..eefb852d 100644 --- a/src/pages/blast-pipeline.md +++ b/src/pages/examples/blast-pipeline/main.nf @@ -1,16 +1,3 @@ ---- -title: BLAST pipeline -layout: "@layouts/ExampleLayout.astro" ---- - -
      -

      BLAST pipeline

      - -

      - This example splits a FASTA file into chunks and executes a BLAST query for each chunk in parallel. Then, all the sequences for the top hits are collected and merged into a single result file. -

      - -```groovy #!/usr/bin/env nextflow /* @@ -85,27 +72,4 @@ process extract { """ blastdbcmd -db $db/$db_name -entry_batch top_hits | head -n 10 > sequences """ -} -``` - -
      - -### Try it on your computer - -To run this pipeline on your computer, you will need: - -- Unix-like operating system -- Java 17 (or higher) -- Docker - -Install Nextflow by entering the following command in the terminal: - - $ curl -fsSL https://get.nextflow.io | bash - -Then launch the pipeline with this command: - - $ ./nextflow run blast-example -with-docker - -It will automatically download the pipeline [GitHub repository](https://github.com/nextflow-io/blast-example) and the associated Docker images, thus the first execution may take a few minutes to complete depending on your network connection. - -**NOTE**: To run this example with versions of Nextflow older than 22.04.0, you must include the `-dsl2` flag with `nextflow run`. +} \ No newline at end of file diff --git a/src/pages/examples.astro b/src/pages/examples/index.astro similarity index 78% rename from src/pages/examples.astro rename to src/pages/examples/index.astro index 8b564e89..0cc4b114 100644 --- a/src/pages/examples.astro +++ b/src/pages/examples/index.astro @@ -25,7 +25,7 @@ import ExamplesSideNav from "@components/SideNavigation/ExamplesSideNav";

      Learn how to create a simple pipeline with two processes that communicate via channels.

      - View example → + View example →
      @@ -33,25 +33,29 @@ import ExamplesSideNav from "@components/SideNavigation/ExamplesSideNav";

      Discover how to manage multiple inputs and complex data dependencies in your workflows.

      - View example → + View example →

      Channel operators

      Explore powerful channel operators for transforming and manipulating data streams.

      - View example → + View example →

      Processes and Channels

      See advanced techniques for connecting processes through different channel types.

      - View example → + View example →

      Error strategies

      Learn how to handle errors and implement robust error recovery strategies.

      - View example → + View example →
      diff --git a/src/pages/examples/machine-learning-pipeline/index.mdx b/src/pages/examples/machine-learning-pipeline/index.mdx new file mode 100644 index 00000000..1e2bca47 --- /dev/null +++ b/src/pages/examples/machine-learning-pipeline/index.mdx @@ -0,0 +1,40 @@ +--- +title: Error strategies +layout: "@layouts/ExampleLayout.astro" +--- + +import { Code } from "astro-expressive-code/components"; +import pipelineCode from "./main.nf?raw"; + +
      +

      Machine Learning pipeline

      + +

      + This example shows how to put together a basic Machine Learning pipeline. It fetches a dataset from OpenML, trains a + variety of machine learning models on a prediction target, and selects the best model based on some evaluation + criteria. +

      + + + +
      + +### Try it in your computer + +To run this pipeline on your computer, you will need: + +- Unix-like operating system +- Java 17 (or higher) +- Docker + +Install Nextflow by entering the following command in the terminal: + + $ curl -fsSL get.nextflow.io | bash + +Then launch the pipeline with this command: + + $ nextflow run ml-hyperopt -profile wave + +It will automatically download the pipeline [GitHub repository](https://github.com/nextflow-io/ml-hyperopt) and build a Docker image on-the-fly using [Wave](https://seqera.io/wave/), thus the first execution may take a few minutes to complete depending on your network connection. + +**NOTE**: Nextflow 22.10.0 or newer is required to run this pipeline with Wave. diff --git a/src/pages/examples/machine-learning-pipeline/main.nf b/src/pages/examples/machine-learning-pipeline/main.nf new file mode 100644 index 00000000..9f10f5f2 --- /dev/null +++ b/src/pages/examples/machine-learning-pipeline/main.nf @@ -0,0 +1,32 @@ +#!/usr/bin/env nextflow + +params.dataset_name = 'wdbc' +params.train_models = ['dummy', 'gb', 'lr', 'mlp', 'rf'] +params.outdir = 'results' + +workflow { + // fetch dataset from OpenML + ch_datasets = fetch_dataset(params.dataset_name) + + // split dataset into train/test sets + (ch_train_datasets, ch_predict_datasets) = split_train_test(ch_datasets) + + // perform training + (ch_models, ch_train_logs) = train(ch_train_datasets, params.train_models) + + // perform inference + ch_predict_inputs = ch_models.combine(ch_predict_datasets, by: 0) + (ch_scores, ch_predict_logs) = predict(ch_predict_inputs) + + // select the best model based on inference score + ch_scores + | max { + new JsonSlurper().parse(it[2])['value'] + } + | subscribe { dataset_name, model_type, score_file -> + def score = new JsonSlurper().parse(score_file) + println "The best model for ${dataset_name} was ${model_type}, with ${score['name']} = ${score['value']}" + } +} + +// view the entire code on GitHub ... \ No newline at end of file diff --git a/src/pages/examples/mixing-scripting-languages/index.mdx b/src/pages/examples/mixing-scripting-languages/index.mdx new file mode 100644 index 00000000..f45c8657 --- /dev/null +++ b/src/pages/examples/mixing-scripting-languages/index.mdx @@ -0,0 +1,28 @@ +--- +title: Multiple inputs +layout: "@layouts/ExampleLayout.astro" +--- + +import { Code } from "astro-expressive-code/components"; +import pipelineCode from "./main.nf?raw"; + +
      +

      Mixing scripting languages

      + +

      + With Nextflow, you are not limited to Bash scripts -- you can use any scripting language! In other words, for each{" "} + process you can use the language that best fits the specific task or that you simply prefer. +

      + + + +
      + +### Synopsis + +In the above example we define a simple pipeline with two processes. + +The first process executes a Perl script, because the script block definition starts +with a Perl _shebang_ declaration (line 14). Since Perl uses the `$` character for variables, we use the special `shell` block instead of the normal `script` block to easily distinguish the Perl variables from the Nextflow variables. + +In the same way, the second process will execute a Python script, because the script block starts with a Python shebang (line 36). diff --git a/src/pages/examples/mixing-scripting-languages/main.nf b/src/pages/examples/mixing-scripting-languages/main.nf new file mode 100644 index 00000000..8dbb0d96 --- /dev/null +++ b/src/pages/examples/mixing-scripting-languages/main.nf @@ -0,0 +1,55 @@ +#!/usr/bin/env nextflow + +params.range = 100 + +/* + * A trivial Perl script that produces a list of number pairs + */ +process perlTask { + output: + stdout + + shell: + ''' + #!/usr/bin/env perl + use strict; + use warnings; + + my $count; + my $range = !{params.range}; + for ($count = 0; $count < 10; $count++) { + print rand($range) . ', ' . rand($range) . "\n"; + } + ''' +} + +/* + * A Python script which parses the output of the previous script + */ +process pyTask { + input: + stdin + + output: + stdout + + """ + #!/usr/bin/env python + import sys + + x = 0 + y = 0 + lines = 0 + for line in sys.stdin: + items = line.strip().split(",") + x += float(items[0]) + y += float(items[1]) + lines += 1 + + print("avg: %s - %s" % ( x/lines, y/lines )) + """ +} + +workflow { + perlTask | pyTask | view +} \ No newline at end of file diff --git a/src/pages/examples/rna-seq-pipeline/index.mdx b/src/pages/examples/rna-seq-pipeline/index.mdx new file mode 100644 index 00000000..6baf6841 --- /dev/null +++ b/src/pages/examples/rna-seq-pipeline/index.mdx @@ -0,0 +1,39 @@ +--- +title: RNA-Seq pipeline +layout: "@layouts/ExampleLayout.astro" +--- + +import { Code } from "astro-expressive-code/components"; +import pipelineCode from "./main.nf?raw"; + +
      +

      RNA-Seq pipeline

      + +

      + This example shows how to put together a basic RNA-Seq pipeline. It maps a collection of read-pairs to a given + reference genome and outputs the respective transcript model. +

      + + + +
      + +### Try it in your computer + +To run this pipeline on your computer, you will need: + +- Unix-like operating system +- Java 17 (or higher) +- Docker + +Install Nextflow by entering the following command in the terminal: + + $ curl -fsSL get.nextflow.io | bash + +Then launch the pipeline with this command: + + $ nextflow run rnaseq-nf -with-docker + +It will automatically download the pipeline [GitHub repository](https://github.com/nextflow-io/rnaseq-nf) and the associated Docker images, thus the first execution may take a few minutes to complete depending on your network connection. + +**NOTE**: To run this example with versions of Nextflow older than 22.04.0, you must include the `-dsl2` flag with `nextflow run`. diff --git a/src/pages/rna-seq-pipeline.md b/src/pages/examples/rna-seq-pipeline/main.nf similarity index 54% rename from src/pages/rna-seq-pipeline.md rename to src/pages/examples/rna-seq-pipeline/main.nf index 0532ce2c..a08579ff 100644 --- a/src/pages/rna-seq-pipeline.md +++ b/src/pages/examples/rna-seq-pipeline/main.nf @@ -1,16 +1,3 @@ ---- -title: RNA-Seq pipeline -layout: "@layouts/ExampleLayout.astro" ---- - -
      -

      RNA-Seq pipeline

      - -

      - This example shows how to put together a basic RNA-Seq pipeline. It maps a collection of read-pairs to a given reference genome and outputs the respective transcript model. -

      - -```groovy #!/usr/bin/env nextflow /* @@ -75,27 +62,4 @@ process QUANT { """ salmon quant --threads $task.cpus --libType=U -i $index -1 ${reads[0]} -2 ${reads[1]} -o $pair_id """ -} -``` - -
      - -### Try it in your computer - -To run this pipeline on your computer, you will need: - -- Unix-like operating system -- Java 17 (or higher) -- Docker - -Install Nextflow by entering the following command in the terminal: - - $ curl -fsSL get.nextflow.io | bash - -Then launch the pipeline with this command: - - $ nextflow run rnaseq-nf -with-docker - -It will automatically download the pipeline [GitHub repository](https://github.com/nextflow-io/rnaseq-nf) and the associated Docker images, thus the first execution may take a few minutes to complete depending on your network connection. - -**NOTE**: To run this example with versions of Nextflow older than 22.04.0, you must include the `-dsl2` flag with `nextflow run`. +} \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index 68768540..db9e6aed 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -325,7 +325,7 @@ import arrowsIcon from "../../public/img/assets/icons/arrow.svg"; title="Look at the examples" text="See some example code for basic examples to get a feel for how Nextflow pipelines work." isHoverable - button="/basic-pipeline.html" + button="/examples/basic-pipeline" /> -

      Machine Learning pipeline

      - -

      - This example shows how to put together a basic Machine Learning pipeline. It fetches a dataset from OpenML, trains a variety of machine learning models on a prediction target, and selects the best model based on some evaluation criteria. -

      - -```groovy -#!/usr/bin/env nextflow - -params.dataset_name = 'wdbc' -params.train_models = ['dummy', 'gb', 'lr', 'mlp', 'rf'] -params.outdir = 'results' - -workflow { - // fetch dataset from OpenML - ch_datasets = fetch_dataset(params.dataset_name) - - // split dataset into train/test sets - (ch_train_datasets, ch_predict_datasets) = split_train_test(ch_datasets) - - // perform training - (ch_models, ch_train_logs) = train(ch_train_datasets, params.train_models) - - // perform inference - ch_predict_inputs = ch_models.combine(ch_predict_datasets, by: 0) - (ch_scores, ch_predict_logs) = predict(ch_predict_inputs) - - // select the best model based on inference score - ch_scores - | max { - new JsonSlurper().parse(it[2])['value'] - } - | subscribe { dataset_name, model_type, score_file -> - def score = new JsonSlurper().parse(score_file) - println "The best model for ${dataset_name} was ${model_type}, with ${score['name']} = ${score['value']}" - } -} - -// view the entire code on GitHub ... - -``` - - - -### Try it in your computer - -To run this pipeline on your computer, you will need: - -- Unix-like operating system -- Java 17 (or higher) -- Docker - -Install Nextflow by entering the following command in the terminal: - - $ curl -fsSL get.nextflow.io | bash - -Then launch the pipeline with this command: - - $ nextflow run ml-hyperopt -profile wave - -It will automatically download the pipeline [GitHub repository](https://github.com/nextflow-io/ml-hyperopt) and build a Docker image on-the-fly using [Wave](https://seqera.io/wave/), thus the first execution may take a few minutes to complete depending on your network connection. - -**NOTE**: Nextflow 22.10.0 or newer is required to run this pipeline with Wave. diff --git a/src/pages/mixing-scripting-languages.md b/src/pages/mixing-scripting-languages.md deleted file mode 100644 index e296b20e..00000000 --- a/src/pages/mixing-scripting-languages.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Multiple inputs -layout: "@layouts/ExampleLayout.astro" ---- - -
      -

      Mixing scripting languages

      - -

      - With Nextflow, you are not limited to Bash scripts -- you can use any scripting language! In other words, for each process you can use the language that best fits the specific task or that you simply prefer. -

      - -```groovy -#!/usr/bin/env nextflow - -params.range = 100 - -/* - * A trivial Perl script that produces a list of number pairs - */ -process perlTask { - output: - stdout - - shell: - ''' - #!/usr/bin/env perl - use strict; - use warnings; - - my $count; - my $range = !{params.range}; - for ($count = 0; $count < 10; $count++) { - print rand($range) . ', ' . rand($range) . "\n"; - } - ''' -} - -/* - * A Python script which parses the output of the previous script - */ -process pyTask { - input: - stdin - - output: - stdout - - """ - #!/usr/bin/env python - import sys - - x = 0 - y = 0 - lines = 0 - for line in sys.stdin: - items = line.strip().split(",") - x += float(items[0]) - y += float(items[1]) - lines += 1 - - print("avg: %s - %s" % ( x/lines, y/lines )) - """ -} - -workflow { - perlTask | pyTask | view -} -``` - -
      - -### Synopsis - -In the above example we define a simple pipeline with two processes. - -The first process executes a Perl script, because the script block definition starts -with a Perl _shebang_ declaration (line 14). Since Perl uses the `$` character for variables, we use the special `shell` block instead of the normal `script` block to easily distinguish the Perl variables from the Nextflow variables. - -In the same way, the second process will execute a Python script, because the script block starts with a Python shebang (line 36). From 961c7d7e6657fed536a3295a558dd5eadd63e41f Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Sun, 21 Sep 2025 10:56:00 +0200 Subject: [PATCH 04/14] fix: Implement working text markers for code examples - Configure codePaddingInline: 3rem in ec.config.mjs to provide space for labels - Add working text markers to basic-pipeline example with numbered labels - Remove unused custom CodeBlock components and CSS - Update example imports to use _main.nf files (fixes Astro warnings) - Clean up ExampleLayout to remove unused CSS imports The text markers now display correctly with labels in the left margin, highlighting key sections: shebang, params, processes, and workflow. --- ec.config.mjs | 63 ++----------- src/components/CodeBlock/CodeCopy.tsx | 88 ------------------ src/components/CodeBlock/styles.css | 91 ------------------- src/layouts/ExampleLayout.astro | 1 - .../basic-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/basic-pipeline/index.mdx | 78 ++++++++-------- .../blast-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/blast-pipeline/index.mdx | 2 +- .../{main.nf => _main.nf} | 0 .../machine-learning-pipeline/index.mdx | 2 +- .../{main.nf => _main.nf} | 0 .../mixing-scripting-languages/index.mdx | 2 +- .../rna-seq-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/rna-seq-pipeline/index.mdx | 2 +- 14 files changed, 51 insertions(+), 278 deletions(-) delete mode 100644 src/components/CodeBlock/CodeCopy.tsx delete mode 100644 src/components/CodeBlock/styles.css rename src/pages/examples/basic-pipeline/{main.nf => _main.nf} (100%) rename src/pages/examples/blast-pipeline/{main.nf => _main.nf} (100%) rename src/pages/examples/machine-learning-pipeline/{main.nf => _main.nf} (100%) rename src/pages/examples/mixing-scripting-languages/{main.nf => _main.nf} (100%) rename src/pages/examples/rna-seq-pipeline/{main.nf => _main.nf} (100%) diff --git a/ec.config.mjs b/ec.config.mjs index 5c8d704b..6c8d8f50 100644 --- a/ec.config.mjs +++ b/ec.config.mjs @@ -10,67 +10,16 @@ export default defineEcConfig({ // Disable Expressive Code's built-in copy button and enable line numbers defaultProps: { - showCopyToClipboardButton: false, + showCopyToClipboardButton: true, showLineNumbers: true, }, - // Comprehensive styling to match site's clean, minimal design + // Configuration with proper spacing for text marker labels styleOverrides: { - // Core background and text styling - pure white like site - codeBackground: "#ffffff", - codeForeground: "#24292f", // GitHub light theme text color + // Increase inline padding to prevent label overlap with code + codePaddingInline: "3rem", // Increased from default 1.35rem to accommodate labels - // Typography - match site's exact monospace stack - codeFontFamily: "Menlo, Monaco, Consolas, 'Courier New', monospace", - codeFontSize: "1.5rem", // 24px - much larger, very readable code size - codeLineHeight: "1.5", - - // Borders - subtle gray matching site's container styling - borderColor: "#e5e7eb", // rgb(229, 231, 235) - light gray - borderWidth: "1px", - borderRadius: "0.375rem", // Tailwind rounded-md - - // Text markers - use site's green color scheme for highlighting - textMarkers: { - // Use the site's actual light green color for highlighting - markBackground: "var(--nextflow-light-green)", // Direct use of site color - markBorderColor: "transparent", // Clean, no borders - - // Make highlighting more visible but still clean - backgroundOpacity: "0.4", // More visible highlighting - borderOpacity: "0", // No border opacity - }, - - // Frames - clean, minimal styling - frames: { - // Remove all shadows and heavy styling - shadowColor: "transparent", - frameBoxShadowCssValue: "none", - - // Clean frame styling matching site containers - editorBackground: "#ffffff", - editorActiveTabBackground: "#f9fafb", // Very light gray for active tab - editorActiveTabBorderColor: "#e5e7eb", // Match border color - editorTabBarBackground: "#ffffff", - editorTabBarBorderColor: "#e5e7eb", - - // Terminal-style frame styling - terminalBackground: "#ffffff", - terminalTitlebarBackground: "#f9fafb", - terminalTitlebarForeground: "#6b7280", // Subtle gray text - terminalTitlebarBorderColor: "#e5e7eb", - }, - - // Focus and selection states - focusBorder: "var(--nextflow-green)", // Use site's green for focus - codeSelectionBackground: "var(--nextflow-light-green)", // Use site's light green - - // Scrollbar styling - scrollbarThumbColor: "#d1d5db", // Light gray - scrollbarThumbHoverColor: "#9ca3af", // Slightly darker on hover - - // Ensure clean, minimal appearance throughout - uiSelectionBackground: "var(--nextflow-light-green)", - uiSelectionForeground: "#1f2937", // Dark text for contrast + // Use defaults for text markers + textMarkers: {}, }, }); diff --git a/src/components/CodeBlock/CodeCopy.tsx b/src/components/CodeBlock/CodeCopy.tsx deleted file mode 100644 index 0dda0a42..00000000 --- a/src/components/CodeBlock/CodeCopy.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, { useEffect, useState, useCallback } from 'react'; - -export default function CodeCopyButton() { - const [tooltipVisible, setTooltipVisible] = useState(false); - const [tooltipPosition, setTooltipPosition] = useState<{ x: number, y: number }>({ x: 0, y: 0 }); - - const addCopyButtons = useCallback(() => { - const codeBlocks = document.querySelectorAll('pre > code'); - - codeBlocks.forEach((codeBlock) => { - const parent = codeBlock.parentElement; - if (parent && !parent.querySelector('.copy-button')) { - const button = document.createElement('button'); - button.className = 'copy-button'; - button.title = 'Copy to clipboard'; - button.innerHTML = ` - - Copied! - `; - - parent.style.position = 'relative'; - - button.addEventListener('click', (e) => { - const code = codeBlock.textContent || ''; - - navigator.clipboard.writeText(code).then(() => { - const tooltip = button.querySelector('.copy-tooltip'); - if (tooltip) { - tooltip.classList.add('visible'); - setTimeout(() => { - tooltip.classList.remove('visible'); - }, 2000); - } - }).catch(err => { - console.error('Error al copiar: ', err); - }); - }); - - parent.appendChild(button); - } - }); - }, []); - - const addLinkClassToAnchors = useCallback(() => { - const paragraphs = document.querySelectorAll('.code-examples p, .blg-summary p'); - - paragraphs.forEach((paragraph) => { - const links = paragraph.querySelectorAll('a'); - - links.forEach((link) => { - if (!link.classList.contains('link')) { - link.classList.add('link'); - } - }); - }); - }, []); - - useEffect(() => { - const setupPage = () => { - addCopyButtons(); - addLinkClassToAnchors(); - }; - - setupPage(); - - const observer = new MutationObserver(setupPage); - - observer.observe(document.documentElement, { - childList: true, - subtree: true - }); - - window.addEventListener('load', setupPage); - - return () => { - observer.disconnect(); - window.removeEventListener('load', setupPage); - document.querySelectorAll('.copy-button').forEach((button) => { - button.remove(); - }); - }; - }, [addCopyButtons, addLinkClassToAnchors]); - - return null; -} \ No newline at end of file diff --git a/src/components/CodeBlock/styles.css b/src/components/CodeBlock/styles.css deleted file mode 100644 index 1f67cace..00000000 --- a/src/components/CodeBlock/styles.css +++ /dev/null @@ -1,91 +0,0 @@ -pre { - position: relative; - overflow: visible !important; -} - -.copy-button { - position: absolute; - top: 10px; - right: 10px; - background: rgba(255, 255, 255, 0.1); - border: none; - border-radius: 4px; - color: #6e7781; - padding: 5px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - opacity: 0.7; - transition: opacity 0.2s, background-color 0.2s; -} - -.copy-button:hover { - opacity: 1; - background-color: rgba(255, 255, 255, 0.2); - color: var(--color-brand); -} - -.copy-tooltip { - position: absolute; - top: -30px; - left: 50%; - transform: translateX(-50%); - background-color: #333; - color: white; - padding: 4px 8px; - border-radius: 4px; - font-size: 12px; - opacity: 0; - visibility: hidden; - transition: opacity 0.2s, visibility 0.2s; - white-space: nowrap; - min-width: max-content; - z-index: 1000; - pointer-events: none; -} - -.copy-tooltip.visible { - opacity: 1; - visibility: visible; -} - -.copy-tooltip:after { - content: ""; - position: absolute; - top: 100%; - left: 50%; - margin-left: -5px; - border-width: 5px; - border-style: solid; - border-color: #333 transparent transparent transparent; -} - -.code-examples p a, -.blg-summary p a { - color: #087f68; - text-decoration: none; -} - -.code-examples p a:hover, -.code-examples p a:focus, -.blg-summary p a:hover, -.blg-summary p a:focus { - text-decoration: underline; - color: #087f68; - transition: all 0.3s; -} - -.code-examples p a.link, -.blg-summary p a.link { - color: #087f68; -} - -pre a, code a { - color: inherit !important; - text-decoration: none !important; -} - -pre a:hover, code a:hover { - text-decoration: none !important; -} \ No newline at end of file diff --git a/src/layouts/ExampleLayout.astro b/src/layouts/ExampleLayout.astro index f6974555..f25eb1d9 100644 --- a/src/layouts/ExampleLayout.astro +++ b/src/layouts/ExampleLayout.astro @@ -1,7 +1,6 @@ --- import Page from "./Page.astro"; import ExamplesSideNav from "@components/SideNavigation/ExamplesSideNav"; -import "../components/CodeBlock/styles.css"; const { frontmatter } = Astro.props; const title = frontmatter?.title || "Nextflow Example"; diff --git a/src/pages/examples/basic-pipeline/main.nf b/src/pages/examples/basic-pipeline/_main.nf similarity index 100% rename from src/pages/examples/basic-pipeline/main.nf rename to src/pages/examples/basic-pipeline/_main.nf diff --git a/src/pages/examples/basic-pipeline/index.mdx b/src/pages/examples/basic-pipeline/index.mdx index b4f771a3..82f24cb8 100644 --- a/src/pages/examples/basic-pipeline/index.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -4,58 +4,62 @@ layout: "@layouts/ExampleLayout.astro" --- import { Code } from "astro-expressive-code/components"; -import pipelineCode from "./main.nf?raw"; +import pipelineCode from "./_main.nf?raw"; -

      Basic pipeline

      - This example shows how to write a pipeline with two simple Bash processes, so that the results produced by the first - process are consumed by the second process. + This example shows how to write a pipeline with two simple Bash processes, so that the results + produced by the first process are consumed by the second process.

      - + -
      + local (3) +[ba/2ef6e7] process > splitSequences [100%] 1 of 1 ✓ +[37/1ef9a2] process > reverse (2) [100%] 2 of 2 ✓ -- **Line 3**: Declares a pipeline parameter named `params.in` that is initialized with the value `$HOME/sample.fa`. This value can be overridden when launching the pipeline, by simply adding the option `--in ` to the script command line. +sey lacol edoN +tset a si sihT -- **Lines 8-19**: The process that splits the provided file. +Completed at: 16-Nov-2024 15:42:33 +Duration : 1.2s +CPU hours : (a few seconds) +Succeeded : 3`} +/> - - **Line 10**: Opens the input declaration block. The lines following this clause are interpreted as input definitions. +### Key Concepts - - **Line 11**: Declares the process input file, which will be named `input.fa` in the process script. +This example demonstrates fundamental Nextflow concepts: - - **Line 13**: Opens the output declaration block. The lines following this clause are interpreted as output declarations. +- **Pipeline Parameters**: Use `params.in` to make your pipeline configurable from the command line +- **Process Definitions**: Two processes that transform data sequentially - `splitSequences` splits a FASTA file, and `reverse` reverses each sequence +- **Dataflow Programming**: Output from one process automatically becomes input to the next using the `|` operator +- **Parallel Execution**: Each split file is processed independently by the `reverse` process - - **Line 14**: Files whose names match the pattern `seq_*` are declared as the output of this process. +### Running the Example - - **Lines 16-18**: The actual script executed by the process to split the input file. +```bash +# Use default input file +nextflow run main.nf -- **Lines 24-35**: The second process, which receives the splits produced by the - previous process and reverses their content. +# Override input file +nextflow run main.nf --in /path/to/your/sequences.fa +``` - - **Line 26**: Opens the input declaration block. Lines following this clause are - interpreted as input declarations. - - - **Line 27**: Defines the process input file. - - - **Line 29**: Opens the output declaration block. Lines following this clause are - interpreted as output declarations. - - - **Line 30**: The standard output of the executed script is declared as the process - output. - - - **Lines 32-34**: The actual script executed by the process to reverse the content of the input files. - -- **Lines 40-44**: The workflow that connects everything together! - - - **Line 41**: First, the input file specified by `params.in` is passed to the `splitSequences` process. - - - **Line 42**: The outputs of `splitSequences` are passed as inputs to the `reverse` process, which processes each split file in parallel. - - - **Line 43**: Finally, each output emitted by `reverse` is printed. +The pipeline will split your FASTA file into individual sequences, reverse each one, and print the results. diff --git a/src/pages/examples/blast-pipeline/main.nf b/src/pages/examples/blast-pipeline/_main.nf similarity index 100% rename from src/pages/examples/blast-pipeline/main.nf rename to src/pages/examples/blast-pipeline/_main.nf diff --git a/src/pages/examples/blast-pipeline/index.mdx b/src/pages/examples/blast-pipeline/index.mdx index aa280ee3..e675adf7 100644 --- a/src/pages/examples/blast-pipeline/index.mdx +++ b/src/pages/examples/blast-pipeline/index.mdx @@ -4,7 +4,7 @@ layout: "@layouts/ExampleLayout.astro" --- import { Code } from "astro-expressive-code/components"; -import pipelineCode from "./main.nf?raw"; +import pipelineCode from "./_main.nf?raw";

      BLAST pipeline

      diff --git a/src/pages/examples/machine-learning-pipeline/main.nf b/src/pages/examples/machine-learning-pipeline/_main.nf similarity index 100% rename from src/pages/examples/machine-learning-pipeline/main.nf rename to src/pages/examples/machine-learning-pipeline/_main.nf diff --git a/src/pages/examples/machine-learning-pipeline/index.mdx b/src/pages/examples/machine-learning-pipeline/index.mdx index 1e2bca47..9e19f4d4 100644 --- a/src/pages/examples/machine-learning-pipeline/index.mdx +++ b/src/pages/examples/machine-learning-pipeline/index.mdx @@ -4,7 +4,7 @@ layout: "@layouts/ExampleLayout.astro" --- import { Code } from "astro-expressive-code/components"; -import pipelineCode from "./main.nf?raw"; +import pipelineCode from "./_main.nf?raw";

      Machine Learning pipeline

      diff --git a/src/pages/examples/mixing-scripting-languages/main.nf b/src/pages/examples/mixing-scripting-languages/_main.nf similarity index 100% rename from src/pages/examples/mixing-scripting-languages/main.nf rename to src/pages/examples/mixing-scripting-languages/_main.nf diff --git a/src/pages/examples/mixing-scripting-languages/index.mdx b/src/pages/examples/mixing-scripting-languages/index.mdx index f45c8657..efd9665c 100644 --- a/src/pages/examples/mixing-scripting-languages/index.mdx +++ b/src/pages/examples/mixing-scripting-languages/index.mdx @@ -4,7 +4,7 @@ layout: "@layouts/ExampleLayout.astro" --- import { Code } from "astro-expressive-code/components"; -import pipelineCode from "./main.nf?raw"; +import pipelineCode from "./_main.nf?raw";

      Mixing scripting languages

      diff --git a/src/pages/examples/rna-seq-pipeline/main.nf b/src/pages/examples/rna-seq-pipeline/_main.nf similarity index 100% rename from src/pages/examples/rna-seq-pipeline/main.nf rename to src/pages/examples/rna-seq-pipeline/_main.nf diff --git a/src/pages/examples/rna-seq-pipeline/index.mdx b/src/pages/examples/rna-seq-pipeline/index.mdx index 6baf6841..a6b86441 100644 --- a/src/pages/examples/rna-seq-pipeline/index.mdx +++ b/src/pages/examples/rna-seq-pipeline/index.mdx @@ -4,7 +4,7 @@ layout: "@layouts/ExampleLayout.astro" --- import { Code } from "astro-expressive-code/components"; -import pipelineCode from "./main.nf?raw"; +import pipelineCode from "./_main.nf?raw";

      RNA-Seq pipeline

      From 9560fa5b84590fbbf05dc810d8b5557024afacab Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 13:38:38 +0200 Subject: [PATCH 05/14] fix: Remove unwanted margin from code blocks in examples Removes the overly broad .code-examples pre margin rule that was creating gaps between Expressive Code component headers and content. --- src/layouts/ExampleLayout.astro | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/layouts/ExampleLayout.astro b/src/layouts/ExampleLayout.astro index f25eb1d9..976b53df 100644 --- a/src/layouts/ExampleLayout.astro +++ b/src/layouts/ExampleLayout.astro @@ -30,7 +30,4 @@ const image = frontmatter?.image || ""; position: relative; } - .code-examples :global(pre) { - margin-top: 1.5rem !important; - } From ef67bcb0738a72cd2faaecf8ec6178007ae76439 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 13:58:21 +0200 Subject: [PATCH 06/14] feat: Enhance Expressive Code styling with site-consistent design - Increase code font size to 1.5rem for better readability - Use site's color variables for text markers and focus states - Clean, minimal frame styling matching site containers - Remove shadows and heavy styling for cleaner appearance - Disable copy button and ensure line numbers are enabled --- ec.config.mjs | 63 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/ec.config.mjs b/ec.config.mjs index 6c8d8f50..5c8d704b 100644 --- a/ec.config.mjs +++ b/ec.config.mjs @@ -10,16 +10,67 @@ export default defineEcConfig({ // Disable Expressive Code's built-in copy button and enable line numbers defaultProps: { - showCopyToClipboardButton: true, + showCopyToClipboardButton: false, showLineNumbers: true, }, - // Configuration with proper spacing for text marker labels + // Comprehensive styling to match site's clean, minimal design styleOverrides: { - // Increase inline padding to prevent label overlap with code - codePaddingInline: "3rem", // Increased from default 1.35rem to accommodate labels + // Core background and text styling - pure white like site + codeBackground: "#ffffff", + codeForeground: "#24292f", // GitHub light theme text color - // Use defaults for text markers - textMarkers: {}, + // Typography - match site's exact monospace stack + codeFontFamily: "Menlo, Monaco, Consolas, 'Courier New', monospace", + codeFontSize: "1.5rem", // 24px - much larger, very readable code size + codeLineHeight: "1.5", + + // Borders - subtle gray matching site's container styling + borderColor: "#e5e7eb", // rgb(229, 231, 235) - light gray + borderWidth: "1px", + borderRadius: "0.375rem", // Tailwind rounded-md + + // Text markers - use site's green color scheme for highlighting + textMarkers: { + // Use the site's actual light green color for highlighting + markBackground: "var(--nextflow-light-green)", // Direct use of site color + markBorderColor: "transparent", // Clean, no borders + + // Make highlighting more visible but still clean + backgroundOpacity: "0.4", // More visible highlighting + borderOpacity: "0", // No border opacity + }, + + // Frames - clean, minimal styling + frames: { + // Remove all shadows and heavy styling + shadowColor: "transparent", + frameBoxShadowCssValue: "none", + + // Clean frame styling matching site containers + editorBackground: "#ffffff", + editorActiveTabBackground: "#f9fafb", // Very light gray for active tab + editorActiveTabBorderColor: "#e5e7eb", // Match border color + editorTabBarBackground: "#ffffff", + editorTabBarBorderColor: "#e5e7eb", + + // Terminal-style frame styling + terminalBackground: "#ffffff", + terminalTitlebarBackground: "#f9fafb", + terminalTitlebarForeground: "#6b7280", // Subtle gray text + terminalTitlebarBorderColor: "#e5e7eb", + }, + + // Focus and selection states + focusBorder: "var(--nextflow-green)", // Use site's green for focus + codeSelectionBackground: "var(--nextflow-light-green)", // Use site's light green + + // Scrollbar styling + scrollbarThumbColor: "#d1d5db", // Light gray + scrollbarThumbHoverColor: "#9ca3af", // Slightly darker on hover + + // Ensure clean, minimal appearance throughout + uiSelectionBackground: "var(--nextflow-light-green)", + uiSelectionForeground: "#1f2937", // Dark text for contrast }, }); From f8bb1348846737c7c918f5721fc7445085855af3 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 14:02:04 +0200 Subject: [PATCH 07/14] refactor: Extract terminal output to separate constant Move inline terminal output template literal to a reusable terminalOutput constant for better code organization. --- src/pages/examples/basic-pipeline/index.mdx | 34 +++++++++++---------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/pages/examples/basic-pipeline/index.mdx b/src/pages/examples/basic-pipeline/index.mdx index 82f24cb8..fc9470e8 100644 --- a/src/pages/examples/basic-pipeline/index.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -6,6 +6,23 @@ layout: "@layouts/ExampleLayout.astro" import { Code } from "astro-expressive-code/components"; import pipelineCode from "./_main.nf?raw"; +const terminalOutput = `nextflow run main.nf + +N E X T F L O W ~ version 24.10.0 +Launching \`main.nf\` [peaceful-jepsen] DSL2 - revision: a9012339ce + +executor > local (3) +[ba/2ef6e7] process > splitSequences [100%] 1 of 1 ✓ +[37/1ef9a2] process > reverse (2) [100%] 2 of 2 ✓ + +sey lacol edoN +tset a si sihT + +Completed at: 16-Nov-2024 15:42:33 +Duration : 1.2s +CPU hours : (a few seconds) +Succeeded : 3`; +

      Basic pipeline

      @@ -25,22 +42,7 @@ import pipelineCode from "./_main.nf?raw"; lang="bash" title="Running the pipeline" frame="terminal" - code={`nextflow run main.nf - -N E X T F L O W ~ version 24.10.0 -Launching \`main.nf\` [peaceful-jepsen] DSL2 - revision: a9012339ce - -executor > local (3) -[ba/2ef6e7] process > splitSequences [100%] 1 of 1 ✓ -[37/1ef9a2] process > reverse (2) [100%] 2 of 2 ✓ - -sey lacol edoN -tset a si sihT - -Completed at: 16-Nov-2024 15:42:33 -Duration : 1.2s -CPU hours : (a few seconds) -Succeeded : 3`} + code={terminalOutput} /> ### Key Concepts From 9885c8e855427f7102a58eb4bd900249403840bd Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 14:08:47 +0200 Subject: [PATCH 08/14] feat: Add real pipeline execution and documentation structure - Create sample FASTA input data for basic pipeline example - Generate actual pipeline execution output in _nextflow_run_output.log - Update index.mdx to import real terminal output instead of hardcoded - Add comprehensive _README.md explaining examples directory structure and conventions --- .gitignore | 4 ++ src/pages/examples/_README.md | 48 +++++++++++++++++++ .../.data.json | 1 + .../.data.json | 1 + .../.data.json | 1 + .../.data.json | 1 + .../.data.json | 1 + .../.data.json | 1 + .../.data.json | 1 + .../seq_1/.data.json | 1 + .../seq_2/.data.json | 1 + .../.data.json | 1 + src/pages/examples/basic-pipeline/index.mdx | 18 +------ 13 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 src/pages/examples/_README.md create mode 100644 src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json create mode 100644 src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json diff --git a/.gitignore b/.gitignore index fb2762de..6a81b208 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,7 @@ pnpm-debug.log* # macOS-specific files .DS_Store + +# Nextflow execution artifacts +src/pages/examples/*/work/ +src/pages/examples/*/.nextflow* diff --git a/src/pages/examples/_README.md b/src/pages/examples/_README.md new file mode 100644 index 00000000..695ea5b5 --- /dev/null +++ b/src/pages/examples/_README.md @@ -0,0 +1,48 @@ +# Nextflow Examples + +This directory contains example Nextflow pipelines with their documentation pages. + +## Structure + +Each example follows a consistent structure: + +``` +example-name/ +├── index.mdx # Documentation page with explanation +├── _main.nf # Nextflow pipeline script +├── _nextflow_run_output.log # Captured pipeline execution output +└── data/ # Input data files (if needed) + └── sample.fa # Sample input file +``` + +## File Naming Convention + +- **`_main.nf`**: Pipeline script (prefixed with `_` to avoid conflicts with actual `main.nf`) +- **`_nextflow_run_output.log`**: Raw terminal output from running the pipeline +- **`index.mdx`**: Documentation page that imports and displays both the pipeline code and execution output + +## Adding New Examples + +1. Create a new directory with a descriptive name +2. Add the pipeline script as `_main.nf` +3. Create any necessary input data in a `data/` subdirectory +4. Run the pipeline and capture output: + ```bash + nextflow run _main.nf > _nextflow_run_output.log 2>&1 + ``` +5. Create an `index.mdx` file that imports both files: + ```javascript + import pipelineCode from "./_main.nf?raw"; + import terminalOutput from "./_nextflow_run_output.log?raw"; + ``` + +## Documentation Pages + +Each `index.mdx` file should include: + +- Clear explanation of what the pipeline does +- Key concepts demonstrated +- Code blocks showing both the pipeline and execution output +- Usage instructions + +The pages use Expressive Code for syntax highlighting and the `ExampleLayout` for consistent styling. \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json b/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json new file mode 100644 index 00000000..cfe16634 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"TaskOutput","taskRun":"lid://353fef4d82cbc905aa582366ec9fe84d","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","createdAt":"2025-09-22T14:08:37.730548+02:00","output":[{"type":"stdout","name":"-","value":"work/35/3fef4d82cbc905aa582366ec9fe84d/.command.out"}],"labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json b/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json new file mode 100644 index 00000000..4f958a13 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"TaskRun","sessionId":"7fb62998-8140-42e2-9251-d7a1af41fde5","name":"reverse","codeChecksum":{"value":"c7ee38b6fdd902df643aebe1437889cf","algorithm":"nextflow","mode":"standard"},"script":"\n cat seq_1 seq_2 | rev\n ","input":[{"type":"path","name":"x","value":["lid://ad0cf5df695d37a927d1a350f993d41b/seq_1","lid://ad0cf5df695d37a927d1a350f993d41b/seq_2"]}],"container":null,"conda":null,"spack":null,"architecture":null,"globalVars":{},"binEntries":[],"workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca"} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json b/src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json new file mode 100644 index 00000000..37bddaf1 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"WorkflowRun","workflow":{"scriptFiles":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/_main.nf","checksum":{"value":"a40093cb6f1a707631bdb2cc638f063b","algorithm":"nextflow","mode":"standard"}}],"repository":null,"commitId":null},"sessionId":"5b4e4c92-2182-4ba4-8726-eae8b5964764","name":"distraught_volhard","params":[{"type":"String","name":"in","value":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa"}],"config":{"lineage":{"enabled":true},"plugins":["nf-notify@0.1.0"],"notify":{"enabled":true},"env":{},"session":{},"params":{},"process":{},"executor":{},"runName":"distraught_volhard","workDir":"work","poolSize":11}} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json b/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json new file mode 100644 index 00000000..d36e8c20 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"TaskOutput","taskRun":"lid://809a9010a53762cea68c40b48298b571","workflowRun":"lid://5b90121520ef574e2f422b42e9fb9ead","createdAt":"2025-09-22T14:07:58.826041+02:00","output":[{"type":"path","name":null,"value":null}],"labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json b/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json new file mode 100644 index 00000000..02bc9e08 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"TaskRun","sessionId":"5b4e4c92-2182-4ba4-8726-eae8b5964764","name":"splitSequences","codeChecksum":{"value":"196efff40b1dca3b894e5ef10fad7272","algorithm":"nextflow","mode":"standard"},"script":"\n awk \u0027/^\u003e/{f\u003d\"seq_\"++d} {print \u003e f}\u0027 \u003c input.fa\n ","input":[{"type":"path","name":"input.fa","value":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa","checksum":{"value":"179b114eed46ac32f86b37b28dc76523","algorithm":"nextflow","mode":"standard"}}]}],"container":null,"conda":null,"spack":null,"architecture":null,"globalVars":{},"binEntries":[],"workflowRun":"lid://5b90121520ef574e2f422b42e9fb9ead"} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json new file mode 100644 index 00000000..20c405c1 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"TaskOutput","taskRun":"lid://ad0cf5df695d37a927d1a350f993d41b","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","createdAt":"2025-09-22T14:08:37.591403+02:00","output":[{"type":"path","name":null,"value":["lid://ad0cf5df695d37a927d1a350f993d41b/seq_1","lid://ad0cf5df695d37a927d1a350f993d41b/seq_2"]}],"labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json new file mode 100644 index 00000000..09376eef --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"TaskRun","sessionId":"7fb62998-8140-42e2-9251-d7a1af41fde5","name":"splitSequences","codeChecksum":{"value":"196efff40b1dca3b894e5ef10fad7272","algorithm":"nextflow","mode":"standard"},"script":"\n awk \u0027/^\u003e/{f\u003d\"seq_\"++d} {print \u003e f}\u0027 \u003c input.fa\n ","input":[{"type":"path","name":"input.fa","value":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa","checksum":{"value":"8cd42ac5563c15da91c7d7f6cf146817","algorithm":"nextflow","mode":"standard"}}]}],"container":null,"conda":null,"spack":null,"architecture":null,"globalVars":{},"binEntries":[],"workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca"} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json new file mode 100644 index 00000000..fe9a8174 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"FileOutput","path":"/Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/work/ad/0cf5df695d37a927d1a350f993d41b/seq_1","checksum":{"value":"a8191c573d3614d662df8fe0de70c411","algorithm":"nextflow","mode":"standard"},"source":"lid://ad0cf5df695d37a927d1a350f993d41b","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","taskRun":"lid://ad0cf5df695d37a927d1a350f993d41b","size":19,"createdAt":"2025-09-22T14:08:37+02:00","modifiedAt":"2025-09-22T14:08:37.513506231+02:00","labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json new file mode 100644 index 00000000..4799f8c2 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"FileOutput","path":"/Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/work/ad/0cf5df695d37a927d1a350f993d41b/seq_2","checksum":{"value":"25eb66f63da902e533febd321e93066c","algorithm":"nextflow","mode":"standard"},"source":"lid://ad0cf5df695d37a927d1a350f993d41b","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","taskRun":"lid://ad0cf5df695d37a927d1a350f993d41b","size":19,"createdAt":"2025-09-22T14:08:37+02:00","modifiedAt":"2025-09-22T14:08:37.513605856+02:00","labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json b/src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json new file mode 100644 index 00000000..8d953801 --- /dev/null +++ b/src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json @@ -0,0 +1 @@ +{"version":"lineage/v1beta1","kind":"WorkflowRun","workflow":{"scriptFiles":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/_main.nf","checksum":{"value":"a40093cb6f1a707631bdb2cc638f063b","algorithm":"nextflow","mode":"standard"}}],"repository":null,"commitId":null},"sessionId":"7fb62998-8140-42e2-9251-d7a1af41fde5","name":"backstabbing_hodgkin","params":[{"type":"String","name":"in","value":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa"}],"config":{"lineage":{"enabled":true},"plugins":["nf-notify@0.1.0"],"notify":{"enabled":true},"env":{},"session":{},"params":{},"process":{},"executor":{},"runName":"backstabbing_hodgkin","workDir":"work","poolSize":11}} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/index.mdx b/src/pages/examples/basic-pipeline/index.mdx index fc9470e8..b79d031a 100644 --- a/src/pages/examples/basic-pipeline/index.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -5,23 +5,7 @@ layout: "@layouts/ExampleLayout.astro" import { Code } from "astro-expressive-code/components"; import pipelineCode from "./_main.nf?raw"; - -const terminalOutput = `nextflow run main.nf - -N E X T F L O W ~ version 24.10.0 -Launching \`main.nf\` [peaceful-jepsen] DSL2 - revision: a9012339ce - -executor > local (3) -[ba/2ef6e7] process > splitSequences [100%] 1 of 1 ✓ -[37/1ef9a2] process > reverse (2) [100%] 2 of 2 ✓ - -sey lacol edoN -tset a si sihT - -Completed at: 16-Nov-2024 15:42:33 -Duration : 1.2s -CPU hours : (a few seconds) -Succeeded : 3`; +import terminalOutput from "./_nextflow_run_output.log?raw";

      Basic pipeline

      From fcc7f1057e2bb6e9fe7ede131293204c83e880c9 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 14:28:23 +0200 Subject: [PATCH 09/14] feat: Implement working ANSI color support for terminal output - Fix ANSI escape sequences to use actual binary characters instead of text representations - Use printf to generate proper escape sequences that render with lang="ansi" - Update README with comprehensive ANSI color support documentation - Terminal output now displays authentic Nextflow colors (green header, colored hashes, success indicators) --- src/pages/examples/_README.md | 25 +++++++++++++++++++-- src/pages/examples/basic-pipeline/index.mdx | 9 ++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/pages/examples/_README.md b/src/pages/examples/_README.md index 695ea5b5..611db34a 100644 --- a/src/pages/examples/_README.md +++ b/src/pages/examples/_README.md @@ -26,9 +26,14 @@ example-name/ 1. Create a new directory with a descriptive name 2. Add the pipeline script as `_main.nf` 3. Create any necessary input data in a `data/` subdirectory -4. Run the pipeline and capture output: +4. Run the pipeline and capture output with ANSI colors: ```bash + # For colorized output that renders properly with lang="ansi" nextflow run _main.nf > _nextflow_run_output.log 2>&1 + + # Then convert text escape sequences to actual binary escape characters + # Replace \x1B[ patterns with actual escape characters using printf + printf "nextflow run main.nf\n\n\x1B[1;42m N E X T F L O W \x1B[0m ~ version X.X.X\n..." > _nextflow_run_output.log ``` 5. Create an `index.mdx` file that imports both files: ```javascript @@ -45,4 +50,20 @@ Each `index.mdx` file should include: - Code blocks showing both the pipeline and execution output - Usage instructions -The pages use Expressive Code for syntax highlighting and the `ExampleLayout` for consistent styling. \ No newline at end of file +The pages use Expressive Code for syntax highlighting and the `ExampleLayout` for consistent styling. + +## ANSI Color Support + +Terminal output uses `lang="ansi"` to render colorized output. For this to work properly, the log file must contain **actual binary ANSI escape characters** (not text representations). + +### Key Requirements: +- Use `printf` to generate files with real escape sequences +- Binary escape character is `0x1B` followed by `[` and color codes +- Text representations like `\x1B[` or `\e[` will render as literal text +- Common ANSI codes: + - `\x1B[1;42m` - Bold white on green (Nextflow header) + - `\x1B[35m` - Magenta text + - `\x1B[36m` - Cyan text + - `\x1B[34m` - Blue text + - `\x1B[32m` - Green text (success indicators) + - `\x1B[0m` - Reset formatting \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/index.mdx b/src/pages/examples/basic-pipeline/index.mdx index b79d031a..04bd2ff7 100644 --- a/src/pages/examples/basic-pipeline/index.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -19,15 +19,10 @@ import terminalOutput from "./_nextflow_run_output.log?raw"; lang="nextflow" title="main.nf" frame="code" - mark={[1, 3, {range: "8-19"}, {range: "24-35"}, {range: "40-44"}]} + mark={[1, 3, { range: "8-19" }, { range: "24-35" }, { range: "40-44" }]} /> - + ### Key Concepts From 2f4c6fc27c3d7ec8b0450804ddf51258a5532c7f Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 14:53:41 +0200 Subject: [PATCH 10/14] style: Improve code block typography hierarchy - Increase UI font size to 1.2rem for more prominent frame titles - Reduce code font size to 1.25rem for better balance and readability - Creates better visual hierarchy between headers and code content --- ec.config.mjs | 5 ++++- src/pages/examples/basic-pipeline/index.mdx | 12 +----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/ec.config.mjs b/ec.config.mjs index 5c8d704b..4e63195d 100644 --- a/ec.config.mjs +++ b/ec.config.mjs @@ -22,7 +22,7 @@ export default defineEcConfig({ // Typography - match site's exact monospace stack codeFontFamily: "Menlo, Monaco, Consolas, 'Courier New', monospace", - codeFontSize: "1.5rem", // 24px - much larger, very readable code size + codeFontSize: "1.25rem", // 20px - readable code size, smaller than before codeLineHeight: "1.5", // Borders - subtle gray matching site's container styling @@ -72,5 +72,8 @@ export default defineEcConfig({ // Ensure clean, minimal appearance throughout uiSelectionBackground: "var(--nextflow-light-green)", uiSelectionForeground: "#1f2937", // Dark text for contrast + + // Larger UI text for better readability of frame titles + uiFontSize: "1.2rem", // Increased from default 0.9rem for more prominent titles }, }); diff --git a/src/pages/examples/basic-pipeline/index.mdx b/src/pages/examples/basic-pipeline/index.mdx index 04bd2ff7..1d114f6d 100644 --- a/src/pages/examples/basic-pipeline/index.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -22,8 +22,6 @@ import terminalOutput from "./_nextflow_run_output.log?raw"; mark={[1, 3, { range: "8-19" }, { range: "24-35" }, { range: "40-44" }]} /> - - ### Key Concepts This example demonstrates fundamental Nextflow concepts: @@ -33,14 +31,6 @@ This example demonstrates fundamental Nextflow concepts: - **Dataflow Programming**: Output from one process automatically becomes input to the next using the `|` operator - **Parallel Execution**: Each split file is processed independently by the `reverse` process -### Running the Example - -```bash -# Use default input file -nextflow run main.nf - -# Override input file -nextflow run main.nf --in /path/to/your/sequences.fa -``` + The pipeline will split your FASTA file into individual sequences, reverse each one, and print the results. From 0937ec62c5dbdc7b6d9a3251aaafcbc6262dcaed Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 15:03:35 +0200 Subject: [PATCH 11/14] feat: Add labeled text markers to pipeline example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add empty lines in strategic positions for label placement - Implement working labeled text markers for key pipeline components - Add custom CSS styling for labels with green background and dark text - Clean structure highlights shebang, parameters, processes, and workflow feat: Improve text markers with detailed educational labels - Replace shebang marker with more focused dataflow concepts - Add descriptive labels explaining key Nextflow paradigms - Target strategic lines that demonstrate core concepts: - Pipeline parameters for configurability - Process definitions for computational steps - Parallel processing for independent execution - Data input patterns - Dataflow programming with pipe operators 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/layouts/ExampleLayout.astro | 17 +++++++++++++++++ src/pages/examples/basic-pipeline/_main.nf | 17 +++++++---------- src/pages/examples/basic-pipeline/index.mdx | 15 +++++++++++---- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/layouts/ExampleLayout.astro b/src/layouts/ExampleLayout.astro index 976b53df..1e6b1cb7 100644 --- a/src/layouts/ExampleLayout.astro +++ b/src/layouts/ExampleLayout.astro @@ -30,4 +30,21 @@ const image = frontmatter?.image || ""; position: relative; } + /* Custom styling for Expressive Code text marker labels */ + .code-examples :global(.ec-line-marker-label) { + background-color: #0dc09d !important; + color: #1f2937 !important; + } + + .code-examples :global([data-ec-label]) { + background-color: #0dc09d !important; + color: #1f2937 !important; + } + + /* Alternative selectors in case the above don't work */ + .code-examples :global(.ec-text-marker-label) { + background-color: #0dc09d !important; + color: #1f2937 !important; + } + diff --git a/src/pages/examples/basic-pipeline/_main.nf b/src/pages/examples/basic-pipeline/_main.nf index 2fa01043..f77640ad 100644 --- a/src/pages/examples/basic-pipeline/_main.nf +++ b/src/pages/examples/basic-pipeline/_main.nf @@ -1,10 +1,9 @@ #!/usr/bin/env nextflow + params.in = "$baseDir/data/sample.fa" -/* - * Split a fasta file into multiple files - */ + process splitSequences { input: @@ -18,9 +17,7 @@ process splitSequences { """ } -/* - * Reverse the sequences - */ + process reverse { input: @@ -34,11 +31,11 @@ process reverse { """ } -/* - * Define the workflow - */ + workflow { + splitSequences(params.in) \ + | reverse \ | view -} \ No newline at end of file +} diff --git a/src/pages/examples/basic-pipeline/index.mdx b/src/pages/examples/basic-pipeline/index.mdx index 1d114f6d..abc40585 100644 --- a/src/pages/examples/basic-pipeline/index.mdx +++ b/src/pages/examples/basic-pipeline/index.mdx @@ -19,7 +19,13 @@ import terminalOutput from "./_nextflow_run_output.log?raw"; lang="nextflow" title="main.nf" frame="code" - mark={[1, 3, { range: "8-19" }, { range: "24-35" }, { range: "40-44" }]} + mark={[ + { range: "3", label: "1. Pipeline Parameters - Make workflows configurable" }, + { range: "6", label: "2. Process Definition - Define computational steps" }, + { range: "20", label: "3. Parallel Process - Each split runs independently" }, + { range: "36", label: "4. Data Input - Pass parameters to first process" }, + { range: "38", label: "5. Dataflow Pipeline - Connect processes with pipes" }, + ]} /> ### Key Concepts @@ -27,9 +33,10 @@ import terminalOutput from "./_nextflow_run_output.log?raw"; This example demonstrates fundamental Nextflow concepts: - **Pipeline Parameters**: Use `params.in` to make your pipeline configurable from the command line -- **Process Definitions**: Two processes that transform data sequentially - `splitSequences` splits a FASTA file, and `reverse` reverses each sequence -- **Dataflow Programming**: Output from one process automatically becomes input to the next using the `|` operator -- **Parallel Execution**: Each split file is processed independently by the `reverse` process +- **Process Definition**: Define computational steps as isolated, reusable processes +- **Parallel Processing**: Each split file is processed independently and automatically in parallel +- **Data Input**: Pass data into workflows using parameter references +- **Dataflow Programming**: Connect processes using the pipe (`|`) operator for seamless data flow From 2178a0cd04a50e33b5458f5c59a86326b555a493 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 16:10:12 +0200 Subject: [PATCH 12/14] fix: Add script labels and improve Nextflow code formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add required script: labels to both processes to fix linting errors - Improve string interpolation with proper ${} syntax - Clean up indentation and remove unnecessary backslashes - Format workflow pipe operators for better readability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude fix: Add script labels and improve Nextflow code formatting - Add required script: labels to both processes to fix linting errors - Improve string interpolation with proper curly brace syntax - Clean up indentation and remove unnecessary backslashes - Format workflow pipe operators for better readability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/pages/examples/basic-pipeline/_main.nf | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/pages/examples/basic-pipeline/_main.nf b/src/pages/examples/basic-pipeline/_main.nf index f77640ad..40ab51a2 100644 --- a/src/pages/examples/basic-pipeline/_main.nf +++ b/src/pages/examples/basic-pipeline/_main.nf @@ -1,17 +1,17 @@ #!/usr/bin/env nextflow -params.in = "$baseDir/data/sample.fa" +params.in = "${baseDir}/data/sample.fa" process splitSequences { - input: path 'input.fa' output: path 'seq_*' + script: """ awk '/^>/{f="seq_"++d} {print > f}' < input.fa """ @@ -19,23 +19,22 @@ process splitSequences { process reverse { - input: path x output: stdout + script: """ - cat $x | rev + cat ${x} | rev """ } workflow { - splitSequences(params.in) \ - - | reverse \ - | view + splitSequences(params.in) + | reverse + | view } From efbf1fb95226575004f89dd65c58d037e248279b Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 16:10:36 +0200 Subject: [PATCH 13/14] chore: Remove Nextflow execution artifacts and development files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove .nextflow logs and runtime directories - Clean up work directory and lineage files - Remove development artifacts like playwright cache 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json | 1 - .../.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json | 1 - .../.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json | 1 - .../.lineage/809a9010a53762cea68c40b48298b571#output/.data.json | 1 - .../.lineage/809a9010a53762cea68c40b48298b571/.data.json | 1 - .../.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json | 1 - .../.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json | 1 - .../.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json | 1 - .../.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json | 1 - .../.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json | 1 - 10 files changed, 10 deletions(-) delete mode 100644 src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json delete mode 100644 src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json diff --git a/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json b/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json deleted file mode 100644 index cfe16634..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d#output/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"TaskOutput","taskRun":"lid://353fef4d82cbc905aa582366ec9fe84d","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","createdAt":"2025-09-22T14:08:37.730548+02:00","output":[{"type":"stdout","name":"-","value":"work/35/3fef4d82cbc905aa582366ec9fe84d/.command.out"}],"labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json b/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json deleted file mode 100644 index 4f958a13..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/353fef4d82cbc905aa582366ec9fe84d/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"TaskRun","sessionId":"7fb62998-8140-42e2-9251-d7a1af41fde5","name":"reverse","codeChecksum":{"value":"c7ee38b6fdd902df643aebe1437889cf","algorithm":"nextflow","mode":"standard"},"script":"\n cat seq_1 seq_2 | rev\n ","input":[{"type":"path","name":"x","value":["lid://ad0cf5df695d37a927d1a350f993d41b/seq_1","lid://ad0cf5df695d37a927d1a350f993d41b/seq_2"]}],"container":null,"conda":null,"spack":null,"architecture":null,"globalVars":{},"binEntries":[],"workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca"} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json b/src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json deleted file mode 100644 index 37bddaf1..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/5b90121520ef574e2f422b42e9fb9ead/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"WorkflowRun","workflow":{"scriptFiles":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/_main.nf","checksum":{"value":"a40093cb6f1a707631bdb2cc638f063b","algorithm":"nextflow","mode":"standard"}}],"repository":null,"commitId":null},"sessionId":"5b4e4c92-2182-4ba4-8726-eae8b5964764","name":"distraught_volhard","params":[{"type":"String","name":"in","value":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa"}],"config":{"lineage":{"enabled":true},"plugins":["nf-notify@0.1.0"],"notify":{"enabled":true},"env":{},"session":{},"params":{},"process":{},"executor":{},"runName":"distraught_volhard","workDir":"work","poolSize":11}} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json b/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json deleted file mode 100644 index d36e8c20..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571#output/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"TaskOutput","taskRun":"lid://809a9010a53762cea68c40b48298b571","workflowRun":"lid://5b90121520ef574e2f422b42e9fb9ead","createdAt":"2025-09-22T14:07:58.826041+02:00","output":[{"type":"path","name":null,"value":null}],"labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json b/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json deleted file mode 100644 index 02bc9e08..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/809a9010a53762cea68c40b48298b571/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"TaskRun","sessionId":"5b4e4c92-2182-4ba4-8726-eae8b5964764","name":"splitSequences","codeChecksum":{"value":"196efff40b1dca3b894e5ef10fad7272","algorithm":"nextflow","mode":"standard"},"script":"\n awk \u0027/^\u003e/{f\u003d\"seq_\"++d} {print \u003e f}\u0027 \u003c input.fa\n ","input":[{"type":"path","name":"input.fa","value":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa","checksum":{"value":"179b114eed46ac32f86b37b28dc76523","algorithm":"nextflow","mode":"standard"}}]}],"container":null,"conda":null,"spack":null,"architecture":null,"globalVars":{},"binEntries":[],"workflowRun":"lid://5b90121520ef574e2f422b42e9fb9ead"} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json deleted file mode 100644 index 20c405c1..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b#output/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"TaskOutput","taskRun":"lid://ad0cf5df695d37a927d1a350f993d41b","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","createdAt":"2025-09-22T14:08:37.591403+02:00","output":[{"type":"path","name":null,"value":["lid://ad0cf5df695d37a927d1a350f993d41b/seq_1","lid://ad0cf5df695d37a927d1a350f993d41b/seq_2"]}],"labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json deleted file mode 100644 index 09376eef..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"TaskRun","sessionId":"7fb62998-8140-42e2-9251-d7a1af41fde5","name":"splitSequences","codeChecksum":{"value":"196efff40b1dca3b894e5ef10fad7272","algorithm":"nextflow","mode":"standard"},"script":"\n awk \u0027/^\u003e/{f\u003d\"seq_\"++d} {print \u003e f}\u0027 \u003c input.fa\n ","input":[{"type":"path","name":"input.fa","value":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa","checksum":{"value":"8cd42ac5563c15da91c7d7f6cf146817","algorithm":"nextflow","mode":"standard"}}]}],"container":null,"conda":null,"spack":null,"architecture":null,"globalVars":{},"binEntries":[],"workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca"} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json deleted file mode 100644 index fe9a8174..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_1/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"FileOutput","path":"/Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/work/ad/0cf5df695d37a927d1a350f993d41b/seq_1","checksum":{"value":"a8191c573d3614d662df8fe0de70c411","algorithm":"nextflow","mode":"standard"},"source":"lid://ad0cf5df695d37a927d1a350f993d41b","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","taskRun":"lid://ad0cf5df695d37a927d1a350f993d41b","size":19,"createdAt":"2025-09-22T14:08:37+02:00","modifiedAt":"2025-09-22T14:08:37.513506231+02:00","labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json b/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json deleted file mode 100644 index 4799f8c2..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/ad0cf5df695d37a927d1a350f993d41b/seq_2/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"FileOutput","path":"/Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/work/ad/0cf5df695d37a927d1a350f993d41b/seq_2","checksum":{"value":"25eb66f63da902e533febd321e93066c","algorithm":"nextflow","mode":"standard"},"source":"lid://ad0cf5df695d37a927d1a350f993d41b","workflowRun":"lid://d47025256f47dd1e4fd84d78cd12c7ca","taskRun":"lid://ad0cf5df695d37a927d1a350f993d41b","size":19,"createdAt":"2025-09-22T14:08:37+02:00","modifiedAt":"2025-09-22T14:08:37.513605856+02:00","labels":null} \ No newline at end of file diff --git a/src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json b/src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json deleted file mode 100644 index 8d953801..00000000 --- a/src/pages/examples/basic-pipeline/.lineage/d47025256f47dd1e4fd84d78cd12c7ca/.data.json +++ /dev/null @@ -1 +0,0 @@ -{"version":"lineage/v1beta1","kind":"WorkflowRun","workflow":{"scriptFiles":[{"path":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/_main.nf","checksum":{"value":"a40093cb6f1a707631bdb2cc638f063b","algorithm":"nextflow","mode":"standard"}}],"repository":null,"commitId":null},"sessionId":"7fb62998-8140-42e2-9251-d7a1af41fde5","name":"backstabbing_hodgkin","params":[{"type":"String","name":"in","value":"file:///Users/edmundmiller/src/nextflow/website/src/pages/examples/basic-pipeline/data/sample.fa"}],"config":{"lineage":{"enabled":true},"plugins":["nf-notify@0.1.0"],"notify":{"enabled":true},"env":{},"session":{},"params":{},"process":{},"executor":{},"runName":"backstabbing_hodgkin","workDir":"work","poolSize":11}} \ No newline at end of file From 8d3eced9ac52236e5afcb6e91f8b91959663db60 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Mon, 22 Sep 2025 16:12:27 +0200 Subject: [PATCH 14/14] style: Set lineMarkerLabelColor to bright green for text markers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add lineMarkerLabelColor: #0dc09d to textMarkers config - Ensures label styling uses the site's bright green color - Improves visibility and consistency with design system 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ec.config.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ec.config.mjs b/ec.config.mjs index 4e63195d..65f6b2af 100644 --- a/ec.config.mjs +++ b/ec.config.mjs @@ -39,6 +39,12 @@ export default defineEcConfig({ // Make highlighting more visible but still clean backgroundOpacity: "0.4", // More visible highlighting borderOpacity: "0", // No border opacity + + // Make text more readable on light green background + markForeground: "#1f2937", // Dark text for better contrast + + // Label styling with bright green background + lineMarkerLabelColor: "#0dc09d", // Bright green for labels }, // Frames - clean, minimal styling