From f2c897a83fd8f2bfebd3aa5524570d43eb779b9a Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Fri, 19 Sep 2025 22:07:13 -0500 Subject: [PATCH 1/4] 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 2/4] 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 3/4] 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 fa5ae6c10a74d1346eca420b868aef77663262a1 Mon Sep 17 00:00:00 2001 From: Edmund Miller Date: Sun, 21 Sep 2025 10:56:00 +0200 Subject: [PATCH 4/4] fix: Rename .nf files to _main.nf to eliminate Astro warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename all main.nf files to _main.nf and update corresponding import statements to prevent Astro from treating pipeline files as pages. - Rename: main.nf → _main.nf in all pipeline subdirectories - Update imports: './main.nf?raw' → './_main.nf?raw' in all .mdx files - Eliminates console warnings about unsupported file types - Maintains functionality while following Astro conventions --- src/pages/examples/basic-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/basic-pipeline/index.mdx | 2 +- src/pages/examples/blast-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/blast-pipeline/index.mdx | 2 +- .../examples/machine-learning-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/machine-learning-pipeline/index.mdx | 2 +- .../examples/mixing-scripting-languages/{main.nf => _main.nf} | 0 src/pages/examples/mixing-scripting-languages/index.mdx | 2 +- src/pages/examples/rna-seq-pipeline/{main.nf => _main.nf} | 0 src/pages/examples/rna-seq-pipeline/index.mdx | 2 +- 10 files changed, 5 insertions(+), 5 deletions(-) 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/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..de962487 100644 --- a/src/pages/examples/basic-pipeline/index.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 "./main.nf?raw"; +import pipelineCode from "./_main.nf?raw";

      Basic pipeline

      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