├── .github ├── assets │ └── readme-header.svg └── workflows │ └── docs.yml ├── .gitignore ├── .vitepress ├── config.mts └── theme │ ├── index.ts │ └── style.css ├── LICENSE ├── README.md ├── design-patterns ├── branch-and-merge │ ├── header.png │ └── index.md ├── conditional-statement │ ├── header.png │ └── index.md ├── linear-chaining │ ├── header.png │ └── index.md ├── multiple-io │ ├── header.png │ └── index.md ├── scatter-gather │ ├── header.png │ └── index.md └── task-aliasing │ ├── header.png │ └── index.md ├── getting-started ├── contributing.md ├── ecosystem.md ├── getting-help.md └── quickstart.md ├── index.md ├── language-guide ├── imports.md ├── structs.md ├── tasks.md ├── variables.md ├── versions.md └── workflows.md ├── overview.md ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── public ├── favicon.ico ├── hero.svg └── logo-only.svg └── reference ├── stdlib ├── file.md ├── numeric.md ├── string-array.md └── string.md └── upgrade-guide.md /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | permissions: 9 | contents: read 10 | pages: write 11 | id-token: write 12 | 13 | concurrency: 14 | group: "pages" 15 | cancel-in-progress: false 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version: "latest" 25 | - run: npm install && npm run docs:build 26 | - uses: actions/upload-pages-artifact@v3 27 | with: 28 | name: "WDL Documentation" 29 | path: ".vitepress/dist" 30 | deploy: 31 | needs: build 32 | if: success() && github.ref == 'refs/heads/main' 33 | permissions: 34 | pages: write 35 | id-token: write 36 | environment: 37 | name: github-pages 38 | url: ${{ steps.deployment.outputs.page_url }} 39 | runs-on: ubuntu-latest 40 | steps: 41 | - name: Deploy to GitHub Pages 42 | id: deployment 43 | uses: actions/deploy-pages@v4 44 | with: 45 | artifact_name: "WDL Documentation" 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | 4 | # Disable the Vitepress cache. 5 | .vitepress/cache/* 6 | 7 | # Disable the Vitepress distribution folder. 8 | .vitepress/dist/* 9 | -------------------------------------------------------------------------------- /.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitepress"; 2 | import axios from "axios"; 3 | 4 | const url = 5 | "https://raw.githubusercontent.com/stjude-rust-labs/sprocket-vscode/refs/heads/main/syntaxes/wdl.tmGrammar.json"; 6 | 7 | /** 8 | * Gets the current version of the Sprocket TextMate grammar. 9 | * @returns the TextMate grammar as a JavaScript object 10 | */ 11 | async function getGrammar() { 12 | try { 13 | var response = await axios.get(url); 14 | return response.data; 15 | } catch (error) { 16 | console.error(`error occurred: ${error}`); 17 | throw error; 18 | } 19 | } 20 | 21 | export default defineConfig({ 22 | title: "Workflow Description Language (WDL) Documentation", 23 | description: 24 | "Guides and reference materials for the Workflow Description Language (WDL).", 25 | appearance: "force-dark", 26 | base: "/", 27 | ignoreDeadLinks: ["./LICENSE"], 28 | head: [ 29 | ["link", { rel: "icon", href: "/favicon.ico" }], 30 | ["link", { rel: "preconnect", href: "https://fonts.googleapis.com" }], 31 | [ 32 | "link", 33 | { rel: "preconnect", href: "https://fonts.gstatic.com", crossorigin: "" }, 34 | ], 35 | [ 36 | "link", 37 | { 38 | href: "https://fonts.googleapis.com/css2?family=Martian+Mono:wght@100..800&family=Public+Sans:ital,wght@0,100..900;1,100..900&display=swap", 39 | rel: "stylesheet", 40 | }, 41 | ], 42 | ], 43 | themeConfig: { 44 | /** 45 | * Logo and site title. 46 | */ 47 | logo: { 48 | src: "/logo-only.svg", 49 | alt: "The Workflow Description Language (WDL) logo.", 50 | }, 51 | siteTitle: "Documentation", 52 | 53 | /** 54 | * Navbar. 55 | */ 56 | nav: [ 57 | { 58 | text: "Specification", 59 | link: "https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md", 60 | }, 61 | ], 62 | 63 | socialLinks: [ 64 | { 65 | icon: "slack", 66 | link: "https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw", 67 | }, 68 | { icon: "github", link: "https://github.com/openwdl/docs" }, 69 | ], 70 | 71 | search: { 72 | provider: "local", 73 | }, 74 | 75 | /** 76 | * Sidebar. 77 | */ 78 | sidebar: [ 79 | { text: "Overview", link: "/overview" }, 80 | { 81 | text: "Getting Started", 82 | items: [ 83 | { text: "Quickstart", link: "/getting-started/quickstart" }, 84 | { text: "Ecosystem", link: "/getting-started/ecosystem" }, 85 | { text: "Getting help", link: "/getting-started/getting-help" }, 86 | { text: "Contributing", link: "/getting-started/contributing" }, 87 | ], 88 | }, 89 | { 90 | text: "Language Guide", 91 | items: [ 92 | { text: "Variables", link: "/language-guide/variables.md" }, 93 | { text: "Structs", link: "/language-guide/structs.md" }, 94 | { text: "Tasks", link: "/language-guide/tasks.md" }, 95 | { text: "Workflows", link: "/language-guide/workflows.md" }, 96 | { text: "Imports", link: "/language-guide/imports.md" }, 97 | { text: "Versions", link: "/language-guide/versions.md" }, 98 | ], 99 | }, 100 | { 101 | text: "Design Patterns", 102 | items: [ 103 | { 104 | text: "Linear chaining", 105 | link: "/design-patterns/linear-chaining/index.md", 106 | }, 107 | { 108 | text: "Multiple I/O", 109 | link: "/design-patterns/multiple-io/index.md", 110 | }, 111 | { 112 | text: "Branch and merge", 113 | link: "/design-patterns/branch-and-merge/index.md", 114 | }, 115 | { 116 | text: "Task aliasing", 117 | link: "/design-patterns/task-aliasing/index.md", 118 | }, 119 | { 120 | text: "Conditional statement", 121 | link: "/design-patterns/conditional-statement/index.md", 122 | }, 123 | { 124 | text: "Scatter-gather", 125 | link: "/design-patterns/scatter-gather/index.md", 126 | }, 127 | ], 128 | }, 129 | { 130 | text: "Reference", 131 | items: [ 132 | { 133 | text: "Upgrade guide", 134 | link: "/reference/upgrade-guide", 135 | }, 136 | { 137 | text: "Standard library", 138 | items: [ 139 | { 140 | text: "Numeric functions", 141 | link: "/reference/stdlib/numeric", 142 | }, 143 | { 144 | text: "String functions", 145 | link: "/reference/stdlib/string", 146 | }, 147 | { 148 | text: "File functions", 149 | link: "/reference/stdlib/file", 150 | }, 151 | { 152 | text: "String Array functions", 153 | link: "/reference/stdlib/string-array", 154 | }, 155 | ], 156 | collapsed: true, 157 | }, 158 | ], 159 | }, 160 | { 161 | text: "Links", 162 | items: [ 163 | { 164 | text: "Cookbook", 165 | link: "https://github.com/openwdl/cookbook", 166 | }, 167 | ], 168 | }, 169 | ], 170 | }, 171 | markdown: { 172 | theme: "github-dark", 173 | shikiSetup: async function (highlighter) { 174 | // Adds the WDL TextMate grammar from the `stjude-rust-labs/sprocket-vscode` repo 175 | // to the Shiki highlighter. 176 | await highlighter.loadLanguage(getGrammar()); 177 | }, 178 | }, 179 | }); 180 | -------------------------------------------------------------------------------- /.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import { h } from "vue"; 3 | import type { Theme } from "vitepress"; 4 | import DefaultTheme from "vitepress/theme"; 5 | import "./style.css"; 6 | 7 | export default { 8 | extends: DefaultTheme, 9 | Layout: () => { 10 | return h(DefaultTheme.Layout, null, { 11 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 12 | }); 13 | }, 14 | enhanceApp({ app, router, siteData }) { 15 | // ... 16 | }, 17 | } satisfies Theme; 18 | -------------------------------------------------------------------------------- /.vitepress/theme/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Customize default theme styling by overriding CSS variables: 3 | * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css 4 | */ 5 | 6 | /** 7 | * Colors 8 | * 9 | * Each colors have exact same color scale system with 3 levels of solid 10 | * colors with different brightness, and 1 soft color. 11 | * 12 | * - `XXX-1`: The most solid color used mainly for colored text. It must 13 | * satisfy the contrast ratio against when used on top of `XXX-soft`. 14 | * 15 | * - `XXX-2`: The color used mainly for hover state of the button. 16 | * 17 | * - `XXX-3`: The color for solid background, such as bg color of the button. 18 | * It must satisfy the contrast ratio with pure white (#ffffff) text on 19 | * top of it. 20 | * 21 | * - `XXX-soft`: The color used for subtle background such as custom container 22 | * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors 23 | * on top of it. 24 | * 25 | * The soft color must be semi transparent alpha channel. This is crucial 26 | * because it allows adding multiple "soft" colors on top of each other 27 | * to create a accent, such as when having inline code block inside 28 | * custom containers. 29 | * 30 | * - `default`: The color used purely for subtle indication without any 31 | * special meanings attched to it such as bg color for menu hover state. 32 | * 33 | * - `brand`: Used for primary brand colors, such as link text, button with 34 | * brand theme, etc. 35 | * 36 | * - `tip`: Used to indicate useful information. The default theme uses the 37 | * brand color for this by default. 38 | * 39 | * - `warning`: Used to indicate warning to the users. Used in custom 40 | * container, badges, etc. 41 | * 42 | * - `danger`: Used to show error, or dangerous message to the users. Used 43 | * in custom container, badges, etc. 44 | * -------------------------------------------------------------------------- */ 45 | 46 | :root { 47 | --vp-c-default-1: var(--vp-c-gray-1); 48 | --vp-c-default-2: var(--vp-c-gray-2); 49 | --vp-c-default-3: var(--vp-c-gray-3); 50 | --vp-c-default-soft: var(--vp-c-gray-soft); 51 | 52 | --vp-c-black: #161619; 53 | 54 | --vp-c-brand-1: #00b4e1; 55 | --vp-c-brand-2: #0a96c3; 56 | --vp-c-brand-3: #006587; 57 | --vp-c-brand-soft: var(--vp-c-indigo-soft); 58 | 59 | --vp-c-text-1: #D6D6D6; 60 | 61 | --vp-c-tip-1: var(--vp-c-brand-1); 62 | --vp-c-tip-2: var(--vp-c-brand-2); 63 | --vp-c-tip-3: var(--vp-c-brand-3); 64 | --vp-c-tip-soft: var(--vp-c-brand-soft); 65 | 66 | --vp-c-warning-1: var(--vp-c-yellow-1); 67 | --vp-c-warning-2: var(--vp-c-yellow-2); 68 | --vp-c-warning-3: var(--vp-c-yellow-3); 69 | --vp-c-warning-soft: var(--vp-c-yellow-soft); 70 | 71 | --vp-c-danger-1: var(--vp-c-red-1); 72 | --vp-c-danger-2: var(--vp-c-red-2); 73 | --vp-c-danger-3: var(--vp-c-red-3); 74 | --vp-c-danger-soft: var(--vp-c-red-soft); 75 | } 76 | 77 | /** 78 | * Component: Fonts 79 | * -------------------------------------------------------------------------- */ 80 | 81 | :root { 82 | --vp-font-family-base: "Public Sans"; 83 | --vp-font-family-mono: "Martian Mono"; 84 | --vp-code-font-size: 12px; 85 | 86 | .text { 87 | font-size: 15px; 88 | line-height: 18px; 89 | } 90 | 91 | .VPFeatures p { 92 | font-size: 17px; 93 | line-height: 20px; 94 | } 95 | 96 | .VPSidebarItem h2 { 97 | margin-bottom: 4px; 98 | } 99 | 100 | .content:not(code) { 101 | font-size: 17px; 102 | line-height: 26px !important; 103 | } 104 | 105 | .details { 106 | line-height: 26px !important; 107 | } 108 | } 109 | 110 | 111 | /** 112 | * Component: Sidebar 113 | * -------------------------------------------------------------------------- */ 114 | 115 | :root { 116 | --vp-layout-max-width: 1325px; 117 | } 118 | 119 | .VPDoc:not(.has-sidebar) .container { 120 | max-width: 100% !important; 121 | } 122 | 123 | .VPDoc:not(.has-sidebar) .content { 124 | max-width: 100% !important; 125 | } 126 | 127 | .VPDoc.has-aside .content-container { 128 | max-width: 100% !important; 129 | } 130 | 131 | /** 132 | * Component: Button 133 | * -------------------------------------------------------------------------- */ 134 | 135 | :root { 136 | --vp-button-brand-border: transparent; 137 | --vp-button-brand-text: var(--vp-c-white); 138 | --vp-button-brand-bg: var(--vp-c-brand-2); 139 | --vp-button-brand-hover-border: transparent; 140 | --vp-button-brand-hover-text: var(--vp-c-white); 141 | --vp-button-brand-hover-bg: var(--vp-c-brand-1); 142 | --vp-button-brand-active-border: transparent; 143 | --vp-button-brand-active-text: var(--vp-c-white); 144 | --vp-button-brand-active-bg: var(--vp-c-brand-3); 145 | } 146 | 147 | /** 148 | * Component: Home 149 | * -------------------------------------------------------------------------- */ 150 | 151 | :root { 152 | --vp-home-hero-name-color: transparent; 153 | 154 | --vp-home-hero-name-background: #ffffff; 155 | 156 | --vp-home-hero-image-background-image: linear-gradient( 157 | -45deg, 158 | #00b4e1 50%, 159 | #47caff 50% 160 | ); 161 | --vp-home-hero-image-filter: blur(44px); 162 | } 163 | 164 | @media (min-width: 640px) { 165 | :root { 166 | --vp-home-hero-image-filter: blur(56px); 167 | } 168 | } 169 | 170 | @media (min-width: 960px) { 171 | :root { 172 | --vp-home-hero-image-filter: blur(68px); 173 | } 174 | } 175 | 176 | /** 177 | * Component: Custom Block 178 | * -------------------------------------------------------------------------- */ 179 | 180 | :root { 181 | --vp-custom-block-tip-border: transparent; 182 | --vp-custom-block-tip-text: var(--vp-c-text-1); 183 | --vp-custom-block-tip-bg: var(--vp-c-brand-soft); 184 | --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft); 185 | } 186 | 187 | /** 188 | * Component: Algolia 189 | * -------------------------------------------------------------------------- */ 190 | 191 | .DocSearch { 192 | --docsearch-primary-color: var(--vp-c-brand-1) !important; 193 | } 194 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, OpenWDL 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | 7 | This repository contains the official WDL community documentation. Enclosed you'll find 8 | community-developed content, such as tutorials, guides, and language reference 9 | materials, that appeal to old and new WDL users alike. Further, you'll find an 10 | up-to-date list of community tools and resources that you can leverage in your work. 11 | Feel free to [join Slack][join-slack] if you have any questions! 12 | 13 | ## Quickstart 14 | 15 | You can use the following commands to get started working with the WDL community 16 | documentation. We recommend installing [`pnpm`](https://pnpm.io/installation), but `npm` 17 | will also work just fine. 18 | 19 | ```bash 20 | # Install the project. 21 | pnpm install 22 | 23 | # Run a development server. 24 | pnpm run docs:dev 25 | 26 | # Create a production build in the `.vitepress/dist` folder. 27 | pnpm run docs:build 28 | ``` 29 | 30 | ### Contributing 31 | 32 | WDL only advances through community contributions. While participating in discussions 33 | and submitting issues are great ways to be involved, help is also needed to implement 34 | changes to the specification. For more information on how you can contribute, please 35 | read the [Contributing] guide. 36 | 37 | ### License 38 | 39 | The WDL documentation is made available to you under the permissive [BSD 3-Clause 40 | License](./LICENSE). 41 | 42 | © 2022-Present The OpenWDL Developers 43 | 44 | [join-slack]: 45 | https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw 46 | [Contributing]: https://github.com/openwdl/governance/blob/main/CONTRIBUTING.md 47 | -------------------------------------------------------------------------------- /design-patterns/branch-and-merge/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/design-patterns/branch-and-merge/header.png -------------------------------------------------------------------------------- /design-patterns/branch-and-merge/index.md: -------------------------------------------------------------------------------- 1 | # Branch and merge 2 | 3 | The ability to connect inputs and outputs described in the [Linear 4 | chaining](../linear-chaining/index.md) and [Multiple 5 | I/O](../multiple-io/index.md) chapters can be further extended to direct a 6 | task's outputs to separate computation paths and merge the results together. 7 | This technique, known as **branching and merging**, is a common way to run 8 | multiple steps of a broader analysis in parallel. 9 | 10 | ![A diagram showing four tasks: `stepA`, `stepB`, `stepC`, and `stepD`. The first task 11 | (`stepA`) accepts no inputs and produces a single output (`out`). The second task 12 | (`stepB`) and third tasks (`stepC`) have a single input (`in`) that is connected to the 13 | `out` output from `stepA`. Each of these tasks has an output named `out`. The fourth 14 | task (`stepD`) has two input: (a) `in1`, which is connected to `out` from `stepB` and 15 | (b) `in2`, which is connected to `out` from `stepC`. This step has one output called 16 | `out`. This forms a structure where `stepA` is executed first, `stepB` and `stepC` are 17 | executed in parallel (the branch), and `stepD` waits on the results of these two 18 | computations before finally executing (the merge).](header.png) 19 | 20 | This often takes a form similar to the following example. 21 | 22 | ```wdl 23 | # ... task definitions ... 24 | 25 | workflow run { 26 | # Run the first task. 27 | call stepA {} 28 | 29 | # Run `stepB`, connecting the `in` input to `stepA`'s `out` output. 30 | call stepB { input: in = stepA.out } 31 | 32 | # Run `stepC`, connecting the `in` input to `stepA`'s `out` output. 33 | call stepC { input: in = stepA.out } 34 | 35 | # Run `stepD`, connecting the `in1` input to `stepB`'s `out` output 36 | # and the `in2` input to `stepC`'s `out` output. 37 | call stepC { input: in1 = stepB.out, in2 = stepC.out } 38 | } 39 | ``` 40 | 41 | ## Continuing our example 42 | 43 | To build on the example started in [Multiple I/O](../multiple-io/index.md#an-example), 44 | we'll extend this workflow to have a filtering step for single nucleotide polymorphisms 45 | and indels separately. This introduces a branch in our computation graph where the 46 | filtering steps can be run concurrently and merged back together after completion. 47 | 48 | ```wdl 49 | version 1.2 50 | 51 | # (1) We write a task to split the VCF into multiple VCFs. 52 | task split_vcf { 53 | input { 54 | File vcf 55 | } 56 | 57 | command <<< 58 | cp ~/Desktop/wdl/file.vcf.gz . 59 | 60 | picard SplitVcfs \ 61 | I="~{vcf}" \ 62 | SNP_OUTPUT="snp.vcf" \ 63 | INDEL_OUTPUT="indel.vcf" \ 64 | STRICT=false 65 | >>> 66 | 67 | output { 68 | File snp_vcf = "snp.vcf" 69 | File indel_vcf = "indel.vcf" 70 | } 71 | } 72 | 73 | # (2) We write a task to filter SNPs using our criteria. 74 | task filter_snps { 75 | input { 76 | File vcf 77 | } 78 | 79 | command <<< 80 | gatk VariantFiltration \ 81 | -V ~{vcf} \ 82 | -O filtered.vcf \ 83 | --filter-expression "QD < 2.0 || FS > 60.0 || MQ < 40.0 || MQRankSum < -12.5 || ReadPosRankSum < -8.0" \ 84 | --filter-name "snp_filter" 85 | >>> 86 | 87 | output { 88 | File filtered_vcf = "filtered.vcf" 89 | } 90 | } 91 | 92 | # (3) We write a task to filter INDELs using out criteria. 93 | task filter_indels { 94 | input { 95 | File vcf 96 | } 97 | 98 | command <<< 99 | gatk VariantFiltration \ 100 | -V ~{vcf} \ 101 | -O filtered.vcf \ 102 | --filter-expression "QD < 2.0 || FS > 200.0 || ReadPosRankSum <-20.0" \ 103 | --filter-name "indel_filter" 104 | >>> 105 | 106 | output { 107 | File filtered_vcf = "filtered.vcf" 108 | } 109 | } 110 | 111 | # (4) We write a task to merge these two VCFs. 112 | task merge_vcfs { 113 | input { 114 | File snp_vcf 115 | File indel_vcf 116 | } 117 | 118 | command <<< 119 | picard MergeVcfs \ 120 | I="~{snp_vcf}" \ 121 | I="~{indel_vcf}" \ 122 | O="combined.vcf" 123 | >>> 124 | 125 | output { 126 | File combined = "combined.vcf" 127 | } 128 | } 129 | 130 | # (5) We write a workflow that branches to the two filtering steps 131 | # and merges back in the `merge_vcfs` task. 132 | workflow run { 133 | input { 134 | File vcf 135 | } 136 | 137 | call split_vcf { input: vcf } 138 | 139 | # (a) The branch happens here. 140 | call filter_snps { input: vcf = split_vcf.snp_vcf } 141 | call filter_indels { input: vcf = split_vcf.indel_vcf } 142 | 143 | # (b) The merge happens here. 144 | call merge_vcfs { input: 145 | snp_vcf = filter_snps.filtered_vcf, 146 | indel_vcf = filter_snps.filtered_vcf, 147 | } 148 | 149 | output { 150 | File combined = merge_vcfs.combined 151 | } 152 | } 153 | ``` 154 | -------------------------------------------------------------------------------- /design-patterns/conditional-statement/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/design-patterns/conditional-statement/header.png -------------------------------------------------------------------------------- /design-patterns/conditional-statement/index.md: -------------------------------------------------------------------------------- 1 | # Conditional statement 2 | 3 | It is often desirable to only execute some section of a computation graph only if a 4 | particular condition holds. This could be as simple as a user input to the workflow 5 | indicating the "mode A" should be run instead of "mode B", whether to scatter and gather 6 | tasks rather than running a single multi-threaded task, or enabling an entire analysis 7 | based on if some analytical check passes a QC threshold. In these cases, you'll want to 8 | reach for **conditional statements** (also known as `if`/`else` statements). 9 | 10 | ![A diagram showing three tasks: `stepA`, `stepB`, and `stepC`. `stepA` is always 11 | executed, and a conditional boolean variable named `perform_further_work` is gating the 12 | execution of the two downstream tasks (`taskB` and `taskC`).](header.png) 13 | 14 | This often takes a form similar to the following example. 15 | 16 | ```wdl 17 | # ... task definitions ... 18 | 19 | workflow run { 20 | inputs { 21 | Boolean perform_further_work = true 22 | } 23 | 24 | # Run the first task. 25 | call stepA {} 26 | 27 | # If the conditional is true, run `stepB` and `stepC`. 28 | if (perform_further_work) { 29 | call stepB { input: in = stepA.out } 30 | call stepC { input: in = stepB.out } 31 | } 32 | } 33 | ``` 34 | 35 | This can also take the form of evaluating outputs from prior workflow steps. For 36 | example, if you had a task `stepA` that contained a `Boolean is_sufficient_quality` 37 | output, you could do the following. 38 | 39 | ```wdl 40 | # ... task definitions ... 41 | 42 | workflow run { 43 | # Run the first task. 44 | call stepA {} 45 | 46 | # If `stepA` determined the sample is of sufficient quality, 47 | # run `stepB` and `stepC`. 48 | if (stepA.is_sufficient_quality) { 49 | call stepB { input: in = stepA.out } 50 | call stepC { input: in = stepB.out } 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /design-patterns/linear-chaining/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/design-patterns/linear-chaining/header.png -------------------------------------------------------------------------------- /design-patterns/linear-chaining/index.md: -------------------------------------------------------------------------------- 1 | # Linear chaining 2 | 3 | The simplest way to chain tasks together in a workflow is a **linear chain**, whereby 4 | the outputs of one tasks feeds into the input of the next task. The diagram below show 5 | the linear chaining of three tasks in a row. 6 | 7 | ![A diagram showing linear chaining of three tasks: `stepA`, `stepB`, and `stepC`. Each 8 | task is laid out linearly in the order described. The first task (`stepA`) accepts no 9 | inputs and produces a single output (`out`). The second task (`stepB`) has a single 10 | input (`in`) that is connected to the `out` output from `stepA` and has a single output 11 | (`out`). The third task (`stepC`) has a single input (`in`) that is connected to the 12 | `out` output from `stepB` and has no outputs. This forms a linear execution chain of 13 | these tasks.](header.png) 14 | 15 | WDL allows this to be expressed simply, as the output of any task (declared in the 16 | `output` section of the task) may be used as an input to another task when it is called 17 | (via the `call` directive). 18 | 19 | ```wdl 20 | # ... task definitions ... 21 | 22 | workflow run { 23 | # Run the first task. 24 | call stepA {} 25 | 26 | # Run `stepB`, connecting the `in` input to `stepA`'s `out` output. 27 | call stepB { input: in = stepA.out } 28 | 29 | # Run `stepC`, connecting the `in` input to `stepB`'s `out` output. 30 | call stepC { input: in = stepB.out } 31 | } 32 | ``` 33 | 34 | This works because each task creates a _scope_ of the same name as the task that 35 | contains that tasks outputs. Similarly, when using a `call` directive, you can set 36 | values of the inputs within that task's scope. 37 | 38 | ## A full example 39 | 40 | For a more complete picture, here is a workflow that actually computes π by getting the 41 | constant from Python. 42 | 43 | ```wdl 44 | version 1.2 45 | 46 | # (1) We write a task to calculate π. 47 | task calculate_pi { 48 | command <<< 49 | python3 -c "import math; print(math.pi)" 50 | >>> 51 | 52 | output { 53 | # (a) π is output as an _output_ of this task here. 54 | # It's read from standard input and parsed as a `Float`. 55 | Float pi = read_float(stdout()) 56 | } 57 | } 58 | 59 | # (2) We write a task that takes in the output from the 60 | # previous task and uses it to compute the area of a circle. 61 | task calculate_circle_area { 62 | input { 63 | # (a) π is taken as an input here. 64 | Float pi 65 | Float radius = 5.0 66 | } 67 | 68 | command <<< 69 | bc -l <<< "2 * ~{pi} * ~{radius}" 70 | >>> 71 | 72 | output { 73 | Float area = read_float(stdout()) 74 | } 75 | } 76 | 77 | # (3) We write a workflow that linearly chains the two tasks 78 | # by connecting the output of the first task to the input of 79 | # the second task. 80 | workflow hello { 81 | # (a) π is calculated in this step. 82 | call calculate_pi 83 | 84 | # (b) the output from the `calculate_pi` step is passed to 85 | # the input of the `calculate_circle_area` input here. 86 | call calculate_circle_area { input: pi = calculate_pi.pi } 87 | 88 | output { 89 | Float area = calculate_circle_area.area 90 | } 91 | } 92 | 93 | # Now, π will first be calculated by calling `calculate_pi` 94 | # and, once that has completed, `calculate_circle_area` will 95 | # be called using the calculated constant. 96 | ``` 97 | -------------------------------------------------------------------------------- /design-patterns/multiple-io/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/design-patterns/multiple-io/header.png -------------------------------------------------------------------------------- /design-patterns/multiple-io/index.md: -------------------------------------------------------------------------------- 1 | # Multiple I/O 2 | 3 | Tasks don't only have to have a single input and output: they can produce accept 4 | **multiple inputs**, produce **multiple outputs**, and workflows can easily specify 5 | which inputs and outputs need to be connected together. For example, take the consider 6 | the following example. 7 | 8 | ![A diagram showing linear chaining of three tasks: `stepA`, `stepB`, and `stepC`. The 9 | first task (`stepA`) accepts no inputs and produces a single output (`out`). The second 10 | task (`stepB`) has a single input (`in`) that is connected to the `out` output from 11 | `stepA` and has two outputs: `out1` and `out2`. The third task (`stepC`) has two inputs 12 | (`in1` and `in2`) that are connected to `out1` and `out2` from `stepB` respectively. 13 | `stepC` has no outputs. This forms a linear chain for these tasks, except that multiple 14 | inputs in `stepC` are connected to multiple outputs in `stepB` to illustrate the 15 | multiple inputs and multiple outputs concept.](header.png) 16 | 17 | Notice that the two outputs from `stepB` have distinctive types and names. Further, the 18 | two inputs in `stepC` has distinctive types and names as well. Because of this, you can 19 | easily direct a workflow to connect the outputs in `stepB` to their respective inputs in 20 | `stepC`. 21 | 22 | ```wdl 23 | # ... task definitions ... 24 | 25 | workflow run { 26 | # Run `stepA`. 27 | call stepA {} 28 | 29 | # Run `stepB`, connecting the `in` input to `stepA`'s `out` output. 30 | call stepB { input: in = stepA.out } 31 | 32 | # Run `stepC`, connecting the `in1` and `in2` inputs to `stepB`'s 33 | # `out1` and `out2` outputs, respectively. 34 | call stepC { input: 35 | in1 = stepB.out1, 36 | in2 = stepB.out2 37 | } 38 | } 39 | ``` 40 | 41 | Again, because each task creates a scope containing each output, the correct inputs and 42 | outputs can be connected together, and names will not conflict. 43 | 44 | ## An example 45 | 46 | To illustrate this concept, here is an example workflow that uses 47 | [Picard](https://broadinstitute.github.io/picard/) to split a VCF into (a) a VCF 48 | containing only single nucleotide variants and (b) a VCF containing only 49 | insertions/deletions, followed by merging them back together. 50 | 51 | ```wdl 52 | version 1.2 53 | 54 | # (1) We write a task to split the VCF into multiple VCFs. 55 | task split_vcf { 56 | input { 57 | # (a) The task takes in a single input VCF. 58 | File vcf 59 | } 60 | 61 | command <<< 62 | java -jar picard.jar SplitVcfs \ 63 | I="~{vcf}" \ 64 | SNP_OUTPUT="snp.vcf" \ 65 | INDEL_OUTPUT="indel.vcf" \ 66 | STRICT=false 67 | >>> 68 | 69 | output { 70 | # (b) The task produces two output VCFs. 71 | File snp_vcf = "snp.vcf" 72 | File indel_vcf = "indel.vcf" 73 | } 74 | } 75 | 76 | # (2) We write a task to merge these two VCFs. 77 | task merge_vcfs { 78 | input { 79 | # (a) Two input VCFs are accepted. 80 | File snp_vcf 81 | File indel_vcf 82 | } 83 | 84 | command <<< 85 | java -jar picard.jar MergeVcfs \ 86 | I="~{snp_vcf}" \ 87 | I="~{indel_vcf}" \ 88 | O="combined.vcf" 89 | >>> 90 | 91 | output { 92 | # (b) One output VCF is produced. 93 | File combined = "combined.vcf" 94 | } 95 | } 96 | 97 | # (3) We write a workflow that connects the multiple outputs 98 | # from the `split_vcf` task into the multiple inputs from the 99 | # `merge_vcfs` task. 100 | workflow run { 101 | input { 102 | File vcf 103 | } 104 | 105 | call split_vcf { input: vcf } 106 | 107 | # (a) The outputs are connected to the inputs here. 108 | call merge_vcfs { input: 109 | snp_vcf = split_vcf.snp_vcf, 110 | indel_vcf = split_vcf.indel_vcf, 111 | } 112 | 113 | output { 114 | File combined = merge_vcfs.combined 115 | } 116 | } 117 | ``` 118 | -------------------------------------------------------------------------------- /design-patterns/scatter-gather/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/design-patterns/scatter-gather/header.png -------------------------------------------------------------------------------- /design-patterns/scatter-gather/index.md: -------------------------------------------------------------------------------- 1 | # Scatter-gather 2 | 3 | Scatter-gather is a paradigm of parallel computing whereby a computation is split into 4 | smaller, independent pieces, those pieces "scattered" across multiple, parallel 5 | executions, and the results each execution is "gathered" into a single result. This is 6 | incredibly useful when attempting to optimize the speed of computations that don't 7 | depend on one another. Some examples of this design pattern in practice include (a) 8 | scattering of a complex analysis for a single sample across multiple, independent 9 | chromosomes and merging the results together or (b) scattering the generation of 10 | independent [gVCFs] from multiple samples, followed by a gathering [joint genotyping 11 | step] employed by the GATK. 12 | 13 | ![A diagram showing two steps: `stepA` and `stepB`. Multiple instances of `stepA` are 14 | called—one instance for each input file. Each of these produces an output (`out`). 15 | `stepB` is then called once accepting all of these `out` from each `stepA` call and 16 | combining the results. This, in essence, is the power of the scatter-gather 17 | paradigm.](header.png) 18 | 19 | This often takes a form similar to the following example. 20 | 21 | ```wdl 22 | # ... task definitions ... 23 | 24 | workflow run { 25 | inputs { 26 | Array[File] files 27 | } 28 | 29 | # Perform `stepA` for each of the inputs in parallel (scatter). 30 | scatter(file in files) { 31 | call stepA { input: in = file } 32 | } 33 | 34 | # Collect the results from the scatter (gather). 35 | # 36 | # Note that the outputs from `stepA` are automatically coerced 37 | # into an `Array` that you can pass in elsewhere. 38 | call stepB { input: files = stepA.out } 39 | } 40 | ``` 41 | 42 | [gVCFs]: 43 | https://gatk.broadinstitute.org/hc/en-us/articles/360035531812-GVCF-Genomic-Variant-Call-Format 44 | [joint genotyping step]: 45 | https://gatk.broadinstitute.org/hc/en-us/articles/360037057852-GenotypeGVCFs 46 | -------------------------------------------------------------------------------- /design-patterns/task-aliasing/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/design-patterns/task-aliasing/header.png -------------------------------------------------------------------------------- /design-patterns/task-aliasing/index.md: -------------------------------------------------------------------------------- 1 | # Task aliasing 2 | 3 | Occasionally, you will need to call the same task multiple times within the same 4 | workflow. For example, you might need to run the same variant caller between two samples 5 | to determine the variants that are unique to one. Another interesting use case might be 6 | to run the same variant caller on the same sample with different parameters to examine 7 | the differences. In these cases, you'll want to reach for **task aliasing** to ensure 8 | that the names for each `call` remain unique. 9 | 10 | ![A diagram showing three steps: `stepA`, `stepB`, and `stepC`. `stepA` is run twice 11 | with aliases `first` and `second`: both of these instances take one input from 12 | (`sampleA` and `sampleB` respectively) and produce a single output (`out`). `taskB` 13 | takes one input (`in`) that is connected to `out` from `first`. `taskC` 14 | takes one input (`in`) that is connected to `out` from `second`. Both `taskB` and 15 | `taskC` produce a single output (`out`). In this way, the utility of aliasing multiple 16 | `call`s of the same task is demonstrated.](header.png) 17 | 18 | This often takes a form similar to the following example. 19 | 20 | ```wdl 21 | # ... task definitions ... 22 | 23 | workflow run { 24 | # `taskA` is run twice—this is enabled using task aliasing. 25 | call stepA as first {} 26 | call stepA as second {} 27 | 28 | # `taskB` takes in the output from the `first` task. 29 | call stepB { input: in = first.out } 30 | 31 | # `taskC` takes in the output from the `second` task. 32 | call stepC { input: in = second.out } 33 | } 34 | ``` 35 | 36 | [gVCFs]: 37 | https://gatk.broadinstitute.org/hc/en-us/articles/360035531812-GVCF-Genomic-Variant-Call-Format 38 | [joint genotyping step]: 39 | https://gatk.broadinstitute.org/hc/en-us/articles/360037057852-GenotypeGVCFs 40 | -------------------------------------------------------------------------------- /getting-started/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | WDL is a community project and, thus, depends on _your_ contributions to make sure it 4 | continues to thrive. Contributions can come in various forms, including 5 | 6 | - filing issues when you run into problems on GitHub, 7 | - participating as part of language design discussions (via the [RFC process]), 8 | - contributing language or code changes via [pull requests], and 9 | - helping answer questions on [Slack][slack-invite]. 10 | 11 | Please browse the [OpenWDL organization] to learn about the different parts of the 12 | project and get an idea of how you could contribute. Keep in mind that contributions to 13 | WDL must be contributed according to the `CONTRIBUTING.md` ([link][contributing-md]) 14 | document. 15 | 16 | ### Suggested first steps 17 | 18 | While all of these projects are important, consider starting with the [specification] 19 | and [documentation] repositories. In particular keeping the documentation up to date is 20 | important—things like typo fixes, updates to existing content, suggestions for new 21 | documentation, and keeping the list of resources in the [Ecosystem](./ecosystem.md) page 22 | is incredibly helpful! 23 | 24 | [documentation]: https://github.com/openwdl/docs/ 25 | [OpenWDL organization]: https://github.com/openwdl/ 26 | [pull requests]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request 27 | [RFC process]: https://github.com/openwdl/wdl/blob/wdl-1.2/RFC.md 28 | [slack-invite]: https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw 29 | [specification]: https://github.com/openwdl/wdl/ 30 | [contributing-md]: https://github.com/openwdl/wdl/blob/wdl-1.2/CONTRIBUTING.md 31 | -------------------------------------------------------------------------------- /getting-started/ecosystem.md: -------------------------------------------------------------------------------- 1 | # Ecosystem 2 | 3 | WDL has a rich, distributed ecosystem of interconnected developer tools and execution 4 | engines to ensure (a) users can quickly write high-quality, idiomatic workflows, and (b) 5 | scaling the execution of those workflows within any computation environment is a breeze. 6 | 7 | ::: tip 8 | 9 | The WDL ecosystem is rapidly evolving, and, while we're always looking to expand 10 | the list of known ecosystem tools, sometimes tools get missed. If you know of a tool 11 | that needs to be listed here but isn't, we encourage you to [create a pull request] and 12 | let us know! 13 | 14 | ::: 15 | 16 | ## Execution Engines 17 | 18 | The following list contains the known execution engines listed alphabetically. 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 41 | 45 | 50 | 51 | 52 | 60 | 65 | 69 | 74 | 75 | 76 | 84 | 89 | 93 | 99 | 100 | 101 | 109 | 114 | 120 | 126 | 127 | 128 | 136 | 141 | 145 | 150 | 151 | 152 | 160 | 165 | 169 | 174 | 175 |
EngineLocalHPCCloud
29 | 30 | AWS HealthOmics 31 | 32 |
33 | Hosted Platform
34 | Support WDL v1.1 35 |
37 |
38 | 39 |
40 |
42 | Slurm
43 | IBM LSF 44 |
46 | Amazon AWS
47 | Microsoft Azure
48 | Google Cloud 49 |
53 | 54 | Cromwell 55 | 56 |
57 | Binary/Executable
58 | Support WDL v1.0 59 |
61 |
62 | 63 |
64 |
66 | Slurm
67 | IBM LSF 68 |
70 | Amazon AWS
71 | Microsoft Azure
72 | Google Cloud 73 |
77 | 78 | dxCompiler 79 | 80 |
81 | Binary/Executable
82 | Support WDL v1.1 and v2.0 83 |
85 |
86 | 87 |
88 |
90 | Slurm
91 | IBM LSF 92 |
94 | Amazon AWS*
95 | Microsoft Azure*
96 | Google Cloud

97 | * via DNAnexus 98 |
102 | 103 | miniwdl 104 | 105 |
106 | Binary/Executable
107 | Support WDL v1.1 108 |
110 |
111 | 112 |
113 |
115 | 116 | Slurm (plugin)
117 | 118 | IBM LSF (plugin) 119 |
121 | 122 | Amazon AWS (plugin)
123 | Microsoft Azure
124 | Google Cloud 125 |
129 | 130 | Terra 131 | 132 |
133 | Hosted Platform
134 | Support WDL v1.0 135 |
137 |
138 | 139 |
140 |
142 | Slurm
143 | IBM LSF 144 |
146 | Amazon AWS
147 | Microsoft Azure
148 | Google Cloud 149 |
153 | 154 | Toil 155 | 156 |
157 | Binary/Executable
158 | Support WDL v1.1 159 |
161 |
162 | 163 |
164 |
166 | Slurm
167 | IBM LSF 168 |
170 | Amazon AWS
171 | Microsoft Azure
172 | Google Cloud 173 |
176 | 177 | 178 | ## IDE Support 179 | 180 | Extensions and other IDE support tools listed sorted by the editor. 181 | 182 | | Name | Editor | Supports | 183 | | :-------------------------------------- | :----------------- | :--------------------------------------------------------------------------------- | 184 | | [Sprocket][sprocket] (LSP) | Editors with LSP | Formatting, linting, snippets, syntax highlighting, and validation. | 185 | | [wdl-mode] | Emacs | Syntax highlighting. | 186 | | [poly-wdl] | Emacs | Integration with [polymode]. | 187 | | [Winstanly WDL] | JetBrains | Linting and syntax highlighting. | 188 | | [wdl-sublime] | Sublime Text | Syntax highlighting. | 189 | | [wdl-vim] | Vim | Syntax highlighting. | 190 | | [Sprocket][sprocket-vscode] (extension) | Visual Studio Code | Formatting, linting, snippets, syntax highlighting, and validation. | 191 | | [Syntax Highlighter] | Visual Studio Code | Syntax highlighting. | 192 | 193 | ## Development Tools 194 | 195 | The following are tools to enhance the experience of working with WDL sorted by 196 | the category. 197 | 198 | | Name | Category | Description | 199 | | :---------------- | :----------------------- | :-------------------------------------------------------- | 200 | | [wdl-tests] | Conformance testing | Conformance tests for WDL execution engines. | 201 | | [wdl-aid] | Documentation generation | _"Automatic input generation for WDL worflows."_ | 202 | | [pytest-workflow] | Testing | Testing framework for workflow languages (including WDL). | 203 | | [wdldoc] | Documentation generation | _"Create WDL documentation using Markdown."_ | 204 | | [wdl-packager] | Package management | _"Package a WDL and imports into a zip file."_ | 205 | | [pytest-wdl] | Testing | _"WDL plugin for pytest."_ | 206 | 207 | ## Community Workflows 208 | 209 | The following is an incomplete list of large WDL workflow repositories sorted by name. 210 | 211 | | Name | Description | 212 | | :-------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 213 | | [BioWDL]
_LUMC_ | _"Bioinformatics workflows and tasks, written in WDL."_ BioWDL is a large GitHub organization that contains the WDL workflows developed at LUMC ([link](https://lumc.nl)). | 214 | | [Chan Zuckerberg]
_Chan Zuckerberg Initiative_ | Official repository for the WDL workflows developed at the Chan Zuckerberg Initiative for the CZID platform ([link](https://czid.org)). | 215 | | [Dockstore]
_Multiple_ | Dockstore describes itself as "an app store for bioinformatics"—it's an open source platform for sharing analytical tools and workflows. WDL is one of the supported languages. | 216 | | [ENCODE]
_ENCODE Consortium_ | Official repository of the ENCODE Data Coordinating Center's Uniform Processing Pipelines. These pipelines are designed to "create high-quality, consistent, and reproducible data" for the ENCODE project. | 217 | | [GATK]
_Broad Institute_ | Official GATK best practices workflows developed at and published by the Broad Institute's Data Sciences Platform. | 218 | | [PacBio]
_Pacific Biosciences_ | Official repository for the best practices workflows for PacBio data. | 219 | | [St. Jude Cloud]
_St. Jude Children's Research Hospital_ | Official repository for data processing pipelines used on St. Jude Cloud ([link](https://platform.stjude.cloud)). | 220 | | [Thiagen]
_Theiagen Genomics_ | Official repository of Thiagen's WDL workflows. | 221 | | [WARP]
_Broad Institute_ | WARP stands for "WDL Research Analysis Pipelines" and contains cloud-optimized pipelines for processing biological data from the Broad Institute Data Sciences Platform. | 222 | | [WILDS]
_Fred Hutch_ | Official repositories of the Workflows for Integration of Large Data and Software (WILDS) developed at the Fred Hutch Data Science Lab. | 223 | 224 | [create a pull request]: https://github.com/openwdl/docs/pulls 225 | [BioWDL]: https://github.com/biowdl 226 | [Chan Zuckerberg]: https://github.com/chanzuckerberg/czid-workflows 227 | [Dockstore]: 228 | https://dockstore.org/search?descriptorType=WDL&entryType=workflows&searchMode=files 229 | [ENCODE]: https://www.encodeproject.org/pages/pipelines 230 | [GATK]: https://github.com/gatk-workflows/ 231 | [PacBio]: https://github.com/orgs/PacificBiosciences/repositories?q=lang%3Awdl&type=all 232 | [poly-wdl]: https://github.com/jmonlong/poly-wdl 233 | [polymode]: https://github.com/polymode/polymode 234 | [pytest-wdl]: https://github.com/EliLillyCo/pytest-wdl 235 | [pytest-workflow]: https://github.com/LUMC/pytest-workflow 236 | [sprocket-vscode]: 237 | https://marketplace.visualstudio.com/items?itemName=stjude-rust-labs.sprocket-vscode 238 | [sprocket]: https://github.com/stjude-rust-labs/sprocket 239 | [St. Jude Cloud]: https://github.com/stjudecloud/workflows 240 | [Syntax Highlighter]: 241 | https://marketplace.visualstudio.com/items?itemName=broadinstitute.wdl 242 | [Thiagen]: https://github.com/theiagen/public_health_bioinformatics 243 | [WARP]: https://broadinstitute.github.io/warp/docs/get-started/ 244 | [wdl-aid]: https://github.com/biowdl/wdl-aid 245 | [wdl-mode]: https://github.com/zhanxw/wdl-mode 246 | [wdl-packager]: https://github.com/biowdl/wdl-packager 247 | [wdl-sublime]: https://github.com/broadinstitutewdl-sublime/ 248 | [wdl-tests]: https://github.com/openwdl/wdl-tests 249 | [wdl-vim]: https://github.com/broadinstitute/vim-wdl 250 | [wdldoc]: https://github.com/stjudecloud/wdldoc 251 | [WILDS]: https://github.com/orgs/getwilds/repositories?q=lang%3Awdl&type=all 252 | [Winstanly WDL]: https://plugins.jetbrains.com/plugin/8154-winstanley-wdl 253 | -------------------------------------------------------------------------------- /getting-started/getting-help.md: -------------------------------------------------------------------------------- 1 | # Getting Help 2 | 3 | The WDL community has a wide range of resources to help you when you need a helping 4 | hand. 5 | 6 | ### Questions 7 | 8 | As you're learning WDL, you're bound to have questions. We suggest the following 9 | mechanisms for getting the answers you need. 10 | 11 | - Search the [discussions](https://github.com/openwdl/wdl/discussions) to see if your 12 | question has been asked already; if it hasn't been asked, feel free start a new 13 | discussion! If it's been asked but not yet answered, upvote the topic (if it's been 14 | some time, also feel free to chime in on the thread)! 15 | - You may also join the community [Slack][slack-invite] and ask in the `#support` 16 | channel. We highly prefer that you come to the Slack channel with an issue that you 17 | can link us to, as responding to your issue helps us _more permanently_ answer the 18 | question for future askers. 19 | 20 | ### Bugs and new features 21 | 22 | - Search the [issues](https://github.com/openwdl/wdl/issues) to see if someone's already 23 | reported the issue. If your issue has _not_ already been reported, feel free to create 24 | a new one! 25 | - In particular, for feature requests, you are encouraged to start a discussion first 26 | at one of the places in the section above to get community buy-in before proceeding. 27 | - If you'd like to provide a fix/implementation for an issue, please read about 28 | [contributing][contributing-md] before submitting a [pull 29 | request](https://github.com/openwdl/wdl/pulls). 30 | 31 | ### Community Resources 32 | 33 | Last, we have a number of official resources to make sure you have materials to learn 34 | from: be sure to check them out! 35 | 36 | - The [official WDL documentation] (this site) is a great place to learn how to read and 37 | write WDL. All of the basic information you need to get started should be here! how to 38 | read and write WDL WDL. 39 | - If you're more of a guided learner, the [Learn WDL guide] walks you step-by-step 40 | through the basics writing and running WDL—it even has an accompanying YouTube video! 41 | - The [official WDL template repository] is a starter template for a best practice WDL workflow 42 | repository. 43 | - Last, the [WDL specification] exhaustively documents the WDL standard. 44 | 45 | [contributing-md]: https://github.com/openwdl/wdl/blob/wdl-1.2/CONTRIBUTING.md 46 | [Learn WDL guide]: https://github.com/openwdl/learn-wdl 47 | [official WDL documentation]: https://github.com/openwdl/docs 48 | [official WDL template repository]: https://github.com/openwdl/workflow-template-wdl 49 | [slack-invite]: https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw 50 | [WDL specification]: https://github.com/openwdl/wdl 51 | -------------------------------------------------------------------------------- /getting-started/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | 3 | Welcome to the WDL quickstart guide 🚀! This brief guide gives an overview of all the 4 | important bits of the WDL language to ensure you become an expert in writing your own 5 | tasks and workflows. Before diving into an example, let's take a closer look at the 6 | major concepts within the language. 7 | 8 | ### Tasks 9 | 10 | **Tasks** are the atomic units of computation within WDL. Tasks are comprised of a set 11 | of inputs (defined within the `input` section), a set of outputs (defined within the 12 | `output` section), and a command (defined within the `command` section), which is simply 13 | a Bash script to execute. Tasks also support defining _requirements_ (defined within the 14 | `requirements` section) which dictate certain aspects of the task runtime environment. 15 | Importantly, tasks are executed within a [container][container-explanation] to ensure 16 | portability across different execution environments (e.g., your local computer, an HPC, 17 | or the cloud). 18 | 19 | ### Workflows 20 | 21 | **Workflows** string together tasks via their inputs and outputs into a larger 22 | computation graph that can be executed. Workflows are arranged similarly to 23 | tasks except that (a) they don't have a `command` or `requirements` section and 24 | (b) they make available more control flow facilities that aren't relevant within 25 | a task context. For example, the workflow below uses both _conditional 26 | execution_ (the `if` statement) and a _scatter-gather_ (the `scatter` keyword 27 | and `messages` output). Notably, workflows can also define inputs and outputs, 28 | and these generally serve as the global inputs and outputs for the execution of 29 | a workflow. 30 | 31 | ### Inputs and Outputs 32 | 33 | JSON is used for specifying both inputs to and outputs from a workflow. In the code 34 | block below the workflow, you can see the inputs that are specified for the top-level 35 | `name` parameter. You can also optionally provide a value for the `is_pirate` 36 | parameter. Further, the output of the workflow is communicated back to you via JSON. 37 | Executing workflows typically involves preparing the needed JSON files and reading the 38 | outputs within the JSON returned from your execution engine. 39 | 40 | ### An example 41 | 42 | For example, assume you wanted to write a task that greets someone, as defined in the 43 | `name` input, in multiple different languages. If that individual is a pirate, you might 44 | even wish to greet them conditionally with `Ahoy`! WDL allows you to express this in a 45 | straightforward manner by (a) constructing the atomic computation you'd like to achieve 46 | using a `task` and (b) running that task for each of your greetings using a `workflow`. 47 | 48 | ```wdl 49 | version 1.2 50 | 51 | task say_hello { 52 | input { 53 | String greeting 54 | String name 55 | } 56 | 57 | command <<< 58 | echo "~{greeting}, ~{name}!" 59 | >>> 60 | 61 | output { 62 | String message = read_string(stdout()) 63 | } 64 | 65 | requirements { 66 | container: "ubuntu:latest" 67 | } 68 | } 69 | 70 | workflow main { 71 | input { 72 | String name 73 | Boolean is_pirate = false 74 | } 75 | 76 | Array[String] greetings = select_all([ 77 | "Hello", 78 | "Hallo", 79 | "Hej", 80 | ( 81 | if is_pirate 82 | then "Ahoy" 83 | else None 84 | ), 85 | ]) 86 | 87 | scatter (greeting in greetings) { 88 | call say_hello { 89 | greeting, 90 | name, 91 | } 92 | } 93 | 94 | output { 95 | Array[String] messages = say_hello.message 96 | } 97 | } 98 | 99 | ``` 100 | 101 | #### Running the example 102 | 103 | If you were to run the example above with these inputs, 104 | 105 | ```json 106 | { 107 | "main.name": "world", 108 | // "main.is_pirate": true, 109 | } 110 | ``` 111 | 112 | the output of the above workflow would be the following. 113 | 114 | ```json 115 | { 116 | "messages": [ 117 | "Hello, world!", 118 | "Hallo, world!", 119 | "Hej, world!", 120 | // "Ahoy, world!" is included is `is_pirate` is set to `true` above. 121 | ] 122 | } 123 | ``` 124 | 125 | ### Conclusion 126 | 127 | This workflow, though simple, demonstrates the how WDL accomplishes its main values: 128 | namely, its _human-readable/writable_ style and its _straightforward but powerful_ 129 | control flow abstractions. You can learn more about the values of the WDL language on 130 | the [Overview](../overview.md#values) page. 131 | 132 | [container-explanation]: 133 | https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-a-container/ 134 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: "Workflow Description Language Docs" 7 | tagline: Guides and reference materials for the Workflow Description Language (WDL). 8 | image: "hero.svg" 9 | actions: 10 | - theme: brand 11 | text: Get Started 🎉 12 | link: /overview 13 | - theme: alt 14 | text: Join Slack 👋 15 | link: https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw 16 | 17 | features: 18 | - icon: 🔎️ 19 | title: Human-readable and -writable 20 | details: > 21 | Designed to be written and understood by software engineers, domain experts, 22 | and platform operators. 23 | - icon: ⚡ 24 | title: Powerful Abstractions 25 | details: > 26 | Express idiomatic workflow execution patterns such as conditional execution, 27 | dynamic resource allocation, and scatter-gather operations with ease. 28 | - icon: 📖 29 | title: Open Standard 30 | details: > 31 | WDL is collectively designed and developed by a distributed, open community. Join 32 | Slack or participate on GitHub to have your voice heard in that process! 33 | --- 34 | -------------------------------------------------------------------------------- /language-guide/imports.md: -------------------------------------------------------------------------------- 1 | # Imports 2 | 3 | Often, it is desirable to split WDL code between multiple files. For example, you may 4 | have several common tasks that you want to share between multiple workflows. In these 5 | cases, you can use `import` statements ([spec link][spec-import-statements]) to refer to 6 | code across files. 7 | 8 | The most important bits to understand are: 9 | 10 | * Imports get their own namespace within WDL files, 11 | * Imports can be local files or URLs (technically, arbitrary URIs), 12 | * Imported documents **must** be the same version as the current document, and 13 | * You may alias imports or their constituent parts to avoid name collisions. 14 | 15 | The example below shows some representative imports with brief descriptions of each. 16 | 17 | ```wdl 18 | # Importing from a file `foo.wdl` with the namespace `foo`. 19 | import "foo.wdl" 20 | 21 | # Importing form a file `bar.wdl` but defining its namespace as `baz`. 22 | import "bar.wdl" as baz 23 | 24 | # Importing the `Person` struct from `person.wdl` directly into the 25 | # current namespace with the name `Individual`.. 26 | import "person.wdl" alias Person as Individual 27 | 28 | # Importing from a URI. 29 | import "http://example.com/lib/stdlib.wdl" 30 | ``` 31 | 32 | [spec-import-statements]: 33 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#import-statements 34 | -------------------------------------------------------------------------------- /language-guide/structs.md: -------------------------------------------------------------------------------- 1 | # Structs 2 | 3 | **Structs** ([spec link][spec-structs]) represent custom types that you can define an 4 | pass around within WDL. Structs are comprised of _member_ fields that have a name and an 5 | associated type. The use of these custom types in more complex situations allows the 6 | execution engine to do validation on your behalf, ensuring that your task or workflow 7 | has all the information it needs in a packaged unit to run smoothly. 8 | 9 | For example, consider a situation where you need to model an `Address` and some broader 10 | `ContactInformation`. 11 | 12 | ```wdl 13 | # Create a custom type named `Address`. 14 | struct Address { 15 | Int street_number 16 | String street_address 17 | Array[Int] zip_code 18 | String city 19 | String state 20 | Array[Int]+? gate_code 21 | } 22 | 23 | # Create a custom type named `ContactInformation`. It can contain 24 | # other structs, like it does here with the `address` field. 25 | struct ContactInformation { 26 | String first_name 27 | String last_name 28 | Address address 29 | String? email_address 30 | } 31 | 32 | # An example workflow using these structs. 33 | workflow run { 34 | output { 35 | ContactInformation john = ContactInformation { 36 | first_name: "John", 37 | last_name: "Smith", 38 | address: Address { 39 | street_number: 123, 40 | street_address: "Main Street", 41 | zip_code: [0, 1, 2, 3, 4 ], 42 | city: "Somewhere", 43 | state: "Foobar", 44 | gate_code: None, 45 | }, 46 | } 47 | 48 | Boolean has_email = defined(john.email_address) 49 | } 50 | } 51 | ``` 52 | 53 | To conclude, structs are an idiomatic mechanism for packaging up complex pieces of data 54 | that need to be passed around as a unit: we highly recommend you use them when you can. 55 | 56 | [spec-structs]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#custom-types-structs 57 | -------------------------------------------------------------------------------- /language-guide/tasks.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Tasks 6 | 7 | **Tasks** ([spec link][spec-tasks]) are the atomic unit of computation within WDL. 8 | Fundamentally, the represent a bash script that is intended to be run to accomplish some 9 | goal. You'll reach for tasks when defining each of the constituent analyses within a 10 | broader [workflow](./workflows.md). 11 | 12 | Tasks have a required ```command``` section and several optional sections for things 13 | like defining inputs, defining outputs, documenting your task, and specifying runtime 14 | requirements. We'll cover each of these in detail here while leaving an exhaustive 15 | explanation to [the specification][spec-tasks]. 16 | 17 | Below is a representative example of what a simple task might look like. 18 | 19 | ```wdl 20 | task say_hello { 21 | input { 22 | String greeting 23 | String name 24 | } 25 | 26 | command <<< 27 | echo "~{greeting}, ~{name}!" 28 | >>> 29 | 30 | output { 31 | String message = read_string(stdout()) 32 | } 33 | 34 | requirements { 35 | container: "ubuntu:latest" 36 | } 37 | } 38 | ``` 39 | 40 | ### The `command` section 41 | 42 | The most important part of a task (and the only _required_ section) is the `command` 43 | section. The command section is simply a Bash script that should be executed when the 44 | task is run. As you can see in the snippet below, variables from within WDL can be 45 | injected into the Bash script at runtime using the `~{variable_name}` syntax. 46 | 47 | ```wdl 48 | task say_hello { 49 | input { 50 | String greeting 51 | String name 52 | } 53 | 54 | command <<< 55 | echo "~{greeting}, ~{name}!" 56 | >>> 57 | 58 | # ... 59 | } 60 | ``` 61 | 62 | ### The `input` section 63 | 64 | You can pass inputs to your task using the `input` section ([spec 65 | link][spec-task-inputs]). Task inputs are declared as WDL variables and are generally 66 | intended to be used as (a) values to be interpolated within the `command` section or (b) 67 | values that are manipulated and passed through directly to the `output` section. 68 | Variables, and how they might be declared in `input` sections, are more fully covered in 69 | the [Variables](./variables.md#declarations) section of the language guide. 70 | 71 | ### The `output` section 72 | 73 | Similarly, you can declare outputs from your task using the `output` section ([spec 74 | link][spec-task-outputs]). Outputs are generally gathered by either (a) using one or 75 | more standard library functions to collect output from the tasks execution directory or 76 | (b) referring to other variables directly. 77 | 78 | ```wdl 79 | task run { 80 | # ... 81 | 82 | output { 83 | # Reads an integer from a file called `threshold.txt`. 84 | Int threshold = read_int("threshold.txt") 85 | 86 | # Gathers a list of CSV files from the task's execution directory. 87 | Array[File]+ csvs = glob("*.csv") 88 | 89 | # Examines an existing variable to evaluate a boolean expression. 90 | Boolean two_csvs = length(csvs) == 2 91 | } 92 | } 93 | ``` 94 | 95 | Again, variables and the way they can be declared in `output` sections are more fully 96 | covered in the [Variables](./variables.md#declarations) section of the language guide. 97 | 98 | ### The `requirements` section 99 | 100 | The `requirements` section ([spec link][spec-requirements]) allows you to specify 101 | runtime requirements for a task. By far the most common use of `requirements` is to 102 | specify a [container][container-explanation] for your task to run within. This ensure 103 | that the task remains portable across multiple execution environments and is always 104 | recommended. That being said, a whole host of [`requirements` 105 | attributes][spec-requirements-attributes] exist. These cover a wide range of concepts 106 | from things like the amount resources required to run the job (e.g., the number of 107 | required cores, the amount of RAM, the amount of disk space) all the way to the valid 108 | exit codes for the job. 109 | 110 | ```wdl 111 | task run { 112 | # ... 113 | 114 | requirements { 115 | # Constrain the container within which this task should run. 116 | container: "ubuntu:latest", 117 | 118 | # Ensure that 8 cores are requisitioned. 119 | cpu: 8, 120 | 121 | # Request 16 gibibytes of random-access memory. 122 | memory: "16 GiB", 123 | } 124 | } 125 | ``` 126 | 127 | Because this list is evolving relatively rapidly, we recommend that you go take a look 128 | at the currently supported attributes [in the specification 129 | directly][spec-requirements-attributes] to ensure you know what can be specified. 130 | 131 | ### Documentation and metadata 132 | 133 | Last, documentation and other metadata for your tasks is generally written in the `meta` 134 | ([spec link][spec-meta]) and `parameter_meta` ([spec link][spec-parameter-meta]) 135 | sections. 136 | 137 | * `meta` contains information related to _the task itself_. It's structured as an object 138 | of key-values pairs that you can define for various metadata attributes of your task. 139 | * `parameter_meta` contains information related to _the inputs and outputs of the task_. 140 | It's also structured as an object of key-values pairs, but each key _must_ correspond 141 | to one of the inputs or outputs of the task. 142 | 143 | At present, there is no defined standard for which keys should exist: keys are typically 144 | added by convention for each code base and/or tool that utilizes them. Future versions 145 | of WDL may consider defining conventional keys for different concepts. Below is a 146 | representative example of what a `meta` and `parameter_meta` section might look like in 147 | a task. 148 | 149 | ```wdl 150 | task run { 151 | # ... 152 | 153 | meta { 154 | authors: ["Foo Bar ", "Baz Quux "], 155 | description: "This is a task that accomplishes ...", 156 | } 157 | 158 | parameter_meta { 159 | in: { 160 | help: "The `in` parameter defines an input file that is used to ..." 161 | }, 162 | out: { 163 | help: "The `out` parameter defines an output file that contains ..." 164 | } 165 | } 166 | 167 | # ... 168 | } 169 | ``` 170 | 171 | ### Other sections 172 | 173 | The above sections cover the most commonly used sections within tasks. Importantly, 174 | other concepts in the `task` section exist, such as the `hints` section ([spec 175 | link][spec-hints]), the use of private declarations ([spec link][spec-declarations]), 176 | and the use of `env` input variables ([spec link][spec-env-variables]). These are more 177 | reserved for more niche use-cases, but users may refer to the spec to learn how to use 178 | them when the need arises. 179 | 180 | [spec-tasks]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#task-definition 181 | [spec-task-inputs]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#task-inputs 182 | [spec-task-inputs]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#task-outputs 183 | [spec-requirements]: 184 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-requirements-section 185 | [spec-requirements-attributes]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#requirements-attributes 186 | [container-explanation]: 187 | https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-a-container/ 188 | [spec-meta]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#meta-values 189 | [spec-parameter-meta]: 190 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#parameter-metadata-section 191 | [spec-hints]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-hints-section 192 | [spec-env-variables]: 193 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#environment-variables 194 | [spec-declarations]: 195 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#private-declarations 196 | -------------------------------------------------------------------------------- /language-guide/variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Variables 6 | 7 | WDL supports the creation and manipulation of variables within the computation 8 | graph. Each variable can have either a _primitive_ type or a _compound_ types. 9 | Types may also be _optional_ meaning that they may or may not have a proper 10 | value (i.e., their value is `None`). 11 | 12 | ### Declarations 13 | 14 | Variables are generally created and assigned through **declarations** ([spec 15 | link][spec-declarations]). Briefly, if a variable is assigned to, the declaration is 16 | known as a _bound_ declaration. If the variable is _not_ assigned, the declaration is 17 | known as an _unbound_ declaration. 18 | 19 | Bound and unbound declarations may be used in various contexts within WDL as laid out in 20 | the specification. While a complete review of these rules is left to the specification, 21 | a quick example should give a sense of how variables are intended to be declared and 22 | assigned. 23 | 24 | ```wdl 25 | workflow run { 26 | # Inputs may have either bound or unbound inputs. Bound inputs 27 | # represent default values for the variable. 28 | input { 29 | # `radius` is defined in an _unbound_ declaration. The value must 30 | # be supplied by the caller of the workflow. 31 | Int radius 32 | 33 | # `pi` is defined in a _bound_ declaration. It has a default value 34 | # of `3.14`, but that value may be overridden by the caller. 35 | Float pi = 3.14 36 | 37 | # `reference` here is an _optional_ variable. It may be provided 38 | # by the caller, but it will have `None` as the value otherwise. 39 | File? reference 40 | } 41 | 42 | # A private declaration can be declared within a workflow or task, 43 | # but it must be bound. 44 | Int three = 1 + 2 45 | 46 | output { 47 | # Output declarations, such as `six` must also be bound. 48 | Float six = 2 * three 49 | } 50 | } 51 | ``` 52 | 53 | ### Primitive types 54 | 55 | **Primitive types** ([spec link][spec-primitive-types]) are the base types that 56 | variables can take. The specification defines the following primitive types: 57 | 58 | * A `Boolean` represents `true` or `false`. 59 | * An `Int` represents a 64-bit signed integer. 60 | * A `Float` represents a 64-bit IEEE-754 floating point number. 61 | * A `String` represents a unicode character string following the format described 62 | [here][spec-strings]. 63 | * A `File` represents a file (or file-like object) 64 | * A `Directory` represents a (possibly nested) directory of files. 65 | 66 | ### Optional types 67 | 68 | Types that have a `?` postfix quantifier are declared as **optional types** ([spec 69 | link][spec-optional-types]), meaning that they can also take the special value of 70 | `None`. This concept is useful if, for example, you have optional inputs to a workflow 71 | or you only produce some output if a particular operation mode is turned on. There are 72 | many facilities to interact with an inspect optional types, such as the [`defined`] and 73 | [`select_first`] standard library functions. 74 | 75 | ### Compound types 76 | 77 | **Compound types** ([spec link][spec-primitive-types]) are higher-order types that 78 | organize other types in useful ways. The specification defines the following compound 79 | types: 80 | 81 | * A `Array[X]` represents an ordered list of elements of the same type ([spec 82 | link][spec-arrays]). 83 | * A `Pair[X, Y]` represents two associated values ([spec link][spec-pairs]) that are 84 | permitted to have different types. 85 | * A `Map[X, Y]` represents an associative array of key-value pairs ([spec 86 | link][spec-maps]). 87 | * 🗑 An `Object` represents an unordered associative array of name-value pairs ([spec 88 | link][spec-maps]). Though valid WDL today, `Object`s are deprecated and are not 89 | suggested for future use. 90 | 91 | [`defined`]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#select_first 92 | [`select_first`]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#select_first 93 | [spec-arrays]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#arrayx 94 | [spec-objects]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-object 95 | [spec-maps]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#mapp-y 96 | [spec-pairs]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#pairx-y 97 | [spec-declarations]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#declarations 98 | [spec-optional-types]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#optional-types-and-none 99 | [spec-primitive-types]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#primitive-types 100 | [spec-strings]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#strings 101 | -------------------------------------------------------------------------------- /language-guide/versions.md: -------------------------------------------------------------------------------- 1 | # Verisons 2 | 3 | The Workflow Description Language has two concepts of versions within the project: 4 | 5 | * The WDL _language_ has a two-number version (e.g., `1.2`). An increase in the 6 | minor (second) version number (e.g., `1.1` to `1.2`) indicates the addition 7 | of, or non-breaking changes to, the language or standard library functions. An 8 | increase in the major (first) version number (e.g., `1.0` to `2.0`) indicates 9 | that breaking changes have been made. 10 | 11 | * The WDL _specification_ has a three-number version (e.g., `1.2.0`). The 12 | specification version tracks the language version, but there may also be patch 13 | releases (indicated by a change to the patch, or third, version number) that 14 | include fixes for typos, additional examples, or non-breaking clarifications 15 | of ambiguous language. 16 | 17 | In general, users of WDL only need to care about the version of the WDL 18 | _language_—you'll rarely, if ever, need to care about the version of the 19 | _specification_ itself. 20 | 21 | ## Upgrading 22 | 23 | If you're interested in learning more about the finer details of upgrading 24 | between versions, such as what features new versions introduce, common pitfalls 25 | of upgrading, and how to get help, see the [Upgrade guide] in the Reference section. 26 | 27 | ## Version specification 28 | 29 | The WDL version is a statement that appears at the top of a WDL document—when included, 30 | it **must** be the first non-comment within the document. 31 | 32 | :::tip NOTE 33 | Technically, the version statement is not _required_, but it is highly recommended that 34 | you do include it in all of your WDL documents. Omission of the version statement 35 | defaults to a very early version of the WDL specification (`draft-2`). 36 | ::: 37 | 38 | 39 | You can specify the version of your WDL document like so: 40 | 41 | ```wdl 42 | version 1.2 43 | 44 | # ... other document contents ... 45 | ``` 46 | 47 | ## Compatability considerations 48 | 49 | Documents may only import other WDL documents of the same version. This is 50 | because the imported documents are effectively comingled within their importer's 51 | context and processed holistically (instead of, for example, being compiled 52 | independently). 53 | 54 | [Upgrade guide]: ../reference/upgrade-guide.md 55 | -------------------------------------------------------------------------------- /language-guide/workflows.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Workflows 6 | 7 | **Workflows** ([spec link][spec-workflows]) define the computation graph that connects 8 | global inputs, outputs, and `tasks` together to build a comprehensive execution plan. 9 | While tasks are focused at the atomic computational unit level, workflows are typically 10 | concerned with how to orchestrate the execution of those tasks in a scalable manner. 11 | 12 | 13 | ### Common sections with `task` 14 | 15 | Workflows contain multiple sections that are common with `task`s, including the `input` 16 | section, the `output` section, and the `meta` and `parameter_meta` sections. The 17 | description of these sections are identical with `task`s and, for brevity, we will not 18 | cover these again in this section of the guide. If you need a refresher, we recommend 19 | you read the relevant sections in the [Tasks](tasks.md) section. 20 | 21 | [spec-workflows]: 22 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#workflow-definition 23 | 24 | ### The `call` statement 25 | 26 | The `call` statement ([spec link][spec-call]) directs the workflow to execute the 27 | specified task or subworkflow. `call`-ing a task or subworkflow brings its name into 28 | scope within the workflow such that its inputs and outputs can be connected 29 | together—either to global inputs and outputs of the workflow or to other 30 | tasks/subworkflows. Further, you can use the `as` keyword to avoid naming collisions 31 | (see [this design pattern](../design-patterns/task-aliasing/) for more information). 32 | 33 | Below is an example of a typical workflow that uses call statements. 34 | 35 | ```wdl 36 | task stepA { 37 | # ... 38 | } 39 | 40 | task stepB { 41 | # ... 42 | } 43 | 44 | workflow run { 45 | # You can instruct the workflow to run `stepA` by `call`-ing it. 46 | call stepA {} 47 | 48 | # If there are inputs, you can include them within the brackets. 49 | call stepB { input: foo = bar } 50 | 51 | # Normally, if you wanted to call `stepA` again, there would be 52 | # a name conflict because the identifier `stepA` would be brought 53 | # into the workflow's scope twice. You can use the `as` keyword 54 | # to assign the task an alias. 55 | call stepA as stepA_again {} 56 | } 57 | ``` 58 | 59 | ### Non-sequentialism 60 | 61 | A quick note on non-sequentialism: in the example above, tasks are not necessarily 62 | executed in the order they are defined. For example, because `stepA_again` does not 63 | depend on any outputs from `stepA` or `stepB`, it can be run immediately when the 64 | workflow starts. This illustrates a broader point—defining a workflow means that you are 65 | defining a _graph_ of computation—not a serial program to be executed. You can learn 66 | more about this in [this section of the spec][spec-element-evaluation]. 67 | 68 | ### Conditional statement 69 | 70 | A **conditional statement**, also known as an `if`/`else` statement ([spec 71 | link][spec-conditional]) allows some subsection of the computation graph to 72 | conditionally occur based on the specified condition. This is useful if, for example, 73 | you want to support different modes of operation based on an input or optionally enable 74 | an entire subanalysis of some data based on passing a QC threshold. 75 | 76 | Building on our example above, we can see conditional statements in action. 77 | 78 | ```wdl 79 | task stepA { 80 | # ... 81 | } 82 | 83 | task stepB { 84 | # ... 85 | } 86 | 87 | workflow run { 88 | input { 89 | Boolean run_stepB 90 | } 91 | 92 | call stepA {} 93 | 94 | if (run_stepB) { 95 | call stepB { input: in = stepA.out } 96 | } 97 | 98 | # ... 99 | } 100 | ``` 101 | 102 | For a bit more complicated example, the workflow below demonstrates (a) conditionally 103 | executing a "standard" or "alternate" mode for `stepA` and then (b) only running `stepB` 104 | if some QC metric from either mode passes. 105 | 106 | ```wdl 107 | task stepA { 108 | # ... 109 | } 110 | 111 | task stepA_alternate { 112 | # ... 113 | } 114 | 115 | task stepB { 116 | # ... 117 | } 118 | 119 | workflow run { 120 | input { 121 | # `alternate_execution_mode` is a required workflow input. 122 | Boolean alternate_execution_mode 123 | } 124 | 125 | # Based on the value passed in as an input, either... 126 | if (alternate_execution_mode) { 127 | # the alternate execution mode will run, or... 128 | call stepA_alternate { 129 | } 130 | } 131 | 132 | if (!alternate_execution_mode) { 133 | # the standard execution mode will run... 134 | call stepA { 135 | } 136 | } 137 | 138 | # Using `select_first`, we can pick up an output named `qc_passed` 139 | # in either `stepA` or `stepA_alternate` (whichever ran) and then 140 | # conditionally run `stepB` based on that result. 141 | if (select_first([ 142 | stepA.qc_passed, 143 | stepA_alternate.qc_passed, 144 | ])) { 145 | call stepB {} 146 | } 147 | 148 | # ... 149 | } 150 | ``` 151 | 152 | Note that the above example uses two `if` statements because WDL doesn't yet support 153 | `else` statements. Instead, one can achieve the same effect with two if 154 | statements and a negated conditional on the second statement. 155 | 156 | ### Design patterns 157 | 158 | Ensuring that your workflow takes full advantage of parallelism is critical to ensuring 159 | your workflow scales well. In fact, the ease with which workflows can be defined and 160 | scaled is one of the hallmarks of the WDL language. This concept is so important that 161 | the is an entire section of the documentation titled "Design Patterns" that covers 162 | idiomatic approaches to construct workflows 163 | ([link](../design-patterns/linear-chaining/)). We highly recommend you read that section 164 | to take full advantages of the facilities WDL provides. 165 | 166 | [spec-call]: https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#call-statement 167 | [spec-element-evaluation]: 168 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#evaluation-of-workflow-elements 169 | [spec-conditional]: 170 | https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#conditional-statement 171 | -------------------------------------------------------------------------------- /overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Overview 6 | 7 | The **Workflow Description Language (WDL)** (pronounced as _/hwɪdl/_ or "whittle" with a 8 | 'd') is an open standard for describing data processing workflows using a 9 | human-readable/writeable syntax. It introduces a domain-specific language, as ratified 10 | in [the openly developed specification][specification], that aims to provide simple but 11 | powerful facilities for (a) defining atomic units of computation (a `task`), (b) for 12 | connecting those atomic units together into a larger computation graph (a `workflow`), 13 | and (c) for effortlessly scaling the execution of these graphs across multiple execution 14 | environments. 15 | 16 | ### Values 17 | 18 | The following are the top-level values of the project. 19 | 20 | - **Human-readable and -writable.** WDL aims to be readable and writable by a wide 21 | variety of audiences, including software engineers, domain experts, and platform 22 | operators. To this end, the language prioritizes providing a concise, domain-specific 23 | grammar that expresses the majority of (but not all) workflows succinctly. This 24 | simplicity is the hallmark of WDL and contrasts with many other modern workflow 25 | languages that aim for enhanced flexibility at the cost of complexity. 26 | - **Powerful abstractions.** WDL aims to be "batteries included" by exposing idiomatic 27 | workflow execution abstractions directly within the language. Concepts such 28 | as conditional execution, dynamic resource allocation, and scatter-gather operations 29 | are easy to understand and express in your workflows. Further, WDL includes a 30 | comprehensive standard library of common functions. 31 | - **Community-driven, open standard.** WDL is collectively designed and developed by a 32 | number of distributed community members via an open process. This means you can 33 | develop with confidence knowing that the foundation you build on will remain open in 34 | perpetuity. It also means that _you_ can participate in the community make sure WDL is 35 | as good as it can be! Join Slack or participate on GitHub to have your voice heard in 36 | that process (see the [Contributing][contributing] section to learn more). 37 | 38 | WDL also maintains a list of other values that are adhered to when possible, but not at 39 | the cost of the top-level values above. 40 | 41 | - **Portability.** WDL aims to be portable—if your task or workflow conforms to the WDL 42 | specification, it should run on any platform supported by your execution engine of 43 | choice. This is particularly true if you enable [one of the LSP 44 | integrations](./getting-started/ecosystem.md#ide-support) in your editor and follow 45 | the portability related lints. 46 | 47 | ### Antivalues 48 | 49 | The following are explicitly _not_ values of the WDL language. 50 | 51 | - _Flexibility at all costs._ WDL is a domain-specific language for expressing 52 | computation graphs—it is not, itself, a programming language, nor is it embedded 53 | within an existing programming language. This is an intentional decision to make WDL 54 | more accessible to non-software engineers. That being said, the downside of that 55 | decision is that arbitrary execution patterns cannot be expressed in WDL. If you find 56 | yourself wanting more flexibility at the cost of added complexity, you're probably 57 | better off using a workflow language that functions more like a programming language, 58 | such as [Nextflow] or [Snakemake]. 59 | 60 | ### Where to start 61 | 62 | If you're just getting started with WDL, we recommend you do a couple of things to 63 | ensure you have the best possible experience: 64 | 65 | * Follow the quickstart guide to learn the most important concepts in WDL 66 | ([link](./getting-started/quickstart.md)). 67 | * Install an developer extension within LSP integration, such as 68 | [Sprocket][sprocket-ext], and pay attention to the validation errors and lints. 69 | * Select an execution engine for the environment(s) you're planning to run your 70 | workflows within and stick with it 71 | ([link](./getting-started/ecosystem.md#execution-engines))—contributing issues and ideas to these 72 | engines will ultimately improve the experience for everyone! 73 | * Join Slack to get help and participate in the broader community ([link][slack-invite]). 74 | 75 | Happy workflowing 👋! 76 | 77 | [contributing]: ./getting-started/contributing.md 78 | [Nextflow]: https://nextflow.io 79 | [Snakemake]: https://snakemake.readthedocs.io/en/stable 80 | [specification]: https://github.com/openwdl/wdl 81 | [sprocket-ext]: 82 | https://marketplace.visualstudio.com/items?itemName=stjude-rust-labs.sprocket-vscode 83 | [slack-invite]: 84 | https://join.slack.com/t/openwdl/shared_invite/zt-ctmj4mhf-cFBNxIiZYs6SY9HgM9UAVw 85 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wdl/docs", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "docs:dev": "vitepress dev", 4 | "docs:build": "vitepress build", 5 | "docs:preview": "vitepress preview" 6 | }, 7 | "devDependencies": { 8 | "axios": "^1.7.9", 9 | "vitepress": "^1.5.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | devDependencies: 11 | axios: 12 | specifier: ^1.7.9 13 | version: 1.7.9 14 | vitepress: 15 | specifier: ^1.5.0 16 | version: 1.5.0(@algolia/client-search@5.19.0)(axios@1.7.9)(postcss@8.4.49)(search-insights@2.17.3) 17 | 18 | packages: 19 | 20 | '@algolia/autocomplete-core@1.17.7': 21 | resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} 22 | 23 | '@algolia/autocomplete-plugin-algolia-insights@1.17.7': 24 | resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} 25 | peerDependencies: 26 | search-insights: '>= 1 < 3' 27 | 28 | '@algolia/autocomplete-preset-algolia@1.17.7': 29 | resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} 30 | peerDependencies: 31 | '@algolia/client-search': '>= 4.9.1 < 6' 32 | algoliasearch: '>= 4.9.1 < 6' 33 | 34 | '@algolia/autocomplete-shared@1.17.7': 35 | resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} 36 | peerDependencies: 37 | '@algolia/client-search': '>= 4.9.1 < 6' 38 | algoliasearch: '>= 4.9.1 < 6' 39 | 40 | '@algolia/client-abtesting@5.19.0': 41 | resolution: {integrity: sha512-dMHwy2+nBL0SnIsC1iHvkBao64h4z+roGelOz11cxrDBrAdASxLxmfVMop8gmodQ2yZSacX0Rzevtxa+9SqxCw==} 42 | engines: {node: '>= 14.0.0'} 43 | 44 | '@algolia/client-analytics@5.19.0': 45 | resolution: {integrity: sha512-CDW4RwnCHzU10upPJqS6N6YwDpDHno7w6/qXT9KPbPbt8szIIzCHrva4O9KIfx1OhdsHzfGSI5hMAiOOYl4DEQ==} 46 | engines: {node: '>= 14.0.0'} 47 | 48 | '@algolia/client-common@5.19.0': 49 | resolution: {integrity: sha512-2ERRbICHXvtj5kfFpY5r8qu9pJII/NAHsdgUXnUitQFwPdPL7wXiupcvZJC7DSntOnE8AE0lM7oDsPhrJfj5nQ==} 50 | engines: {node: '>= 14.0.0'} 51 | 52 | '@algolia/client-insights@5.19.0': 53 | resolution: {integrity: sha512-xPOiGjo6I9mfjdJO7Y+p035aWePcbsItizIp+qVyfkfZiGgD+TbNxM12g7QhFAHIkx/mlYaocxPY/TmwPzTe+A==} 54 | engines: {node: '>= 14.0.0'} 55 | 56 | '@algolia/client-personalization@5.19.0': 57 | resolution: {integrity: sha512-B9eoce/fk8NLboGje+pMr72pw+PV7c5Z01On477heTZ7jkxoZ4X92dobeGuEQop61cJ93Gaevd1of4mBr4hu2A==} 58 | engines: {node: '>= 14.0.0'} 59 | 60 | '@algolia/client-query-suggestions@5.19.0': 61 | resolution: {integrity: sha512-6fcP8d4S8XRDtVogrDvmSM6g5g6DndLc0pEm1GCKe9/ZkAzCmM3ZmW1wFYYPxdjMeifWy1vVEDMJK7sbE4W7MA==} 62 | engines: {node: '>= 14.0.0'} 63 | 64 | '@algolia/client-search@5.19.0': 65 | resolution: {integrity: sha512-Ctg3xXD/1VtcwmkulR5+cKGOMj4r0wC49Y/KZdGQcqpydKn+e86F6l3tb3utLJQVq4lpEJud6kdRykFgcNsp8Q==} 66 | engines: {node: '>= 14.0.0'} 67 | 68 | '@algolia/ingestion@1.19.0': 69 | resolution: {integrity: sha512-LO7w1MDV+ZLESwfPmXkp+KLeYeFrYEgtbCZG6buWjddhYraPQ9MuQWLhLLiaMlKxZ/sZvFTcZYuyI6Jx4WBhcg==} 70 | engines: {node: '>= 14.0.0'} 71 | 72 | '@algolia/monitoring@1.19.0': 73 | resolution: {integrity: sha512-Mg4uoS0aIKeTpu6iv6O0Hj81s8UHagi5TLm9k2mLIib4vmMtX7WgIAHAcFIaqIZp5D6s5EVy1BaDOoZ7buuJHA==} 74 | engines: {node: '>= 14.0.0'} 75 | 76 | '@algolia/recommend@5.19.0': 77 | resolution: {integrity: sha512-PbgrMTbUPlmwfJsxjFhal4XqZO2kpBNRjemLVTkUiti4w/+kzcYO4Hg5zaBgVqPwvFDNQ8JS4SS3TBBem88u+g==} 78 | engines: {node: '>= 14.0.0'} 79 | 80 | '@algolia/requester-browser-xhr@5.19.0': 81 | resolution: {integrity: sha512-GfnhnQBT23mW/VMNs7m1qyEyZzhZz093aY2x8p0era96MMyNv8+FxGek5pjVX0b57tmSCZPf4EqNCpkGcGsmbw==} 82 | engines: {node: '>= 14.0.0'} 83 | 84 | '@algolia/requester-fetch@5.19.0': 85 | resolution: {integrity: sha512-oyTt8ZJ4T4fYvW5avAnuEc6Laedcme9fAFryMD9ndUTIUe/P0kn3BuGcCLFjN3FDmdrETHSFkgPPf1hGy3sLCw==} 86 | engines: {node: '>= 14.0.0'} 87 | 88 | '@algolia/requester-node-http@5.19.0': 89 | resolution: {integrity: sha512-p6t8ue0XZNjcRiqNkb5QAM0qQRAKsCiebZ6n9JjWA+p8fWf8BvnhO55y2fO28g3GW0Imj7PrAuyBuxq8aDVQwQ==} 90 | engines: {node: '>= 14.0.0'} 91 | 92 | '@babel/helper-string-parser@7.25.9': 93 | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} 94 | engines: {node: '>=6.9.0'} 95 | 96 | '@babel/helper-validator-identifier@7.25.9': 97 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 98 | engines: {node: '>=6.9.0'} 99 | 100 | '@babel/parser@7.26.5': 101 | resolution: {integrity: sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==} 102 | engines: {node: '>=6.0.0'} 103 | hasBin: true 104 | 105 | '@babel/types@7.26.5': 106 | resolution: {integrity: sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==} 107 | engines: {node: '>=6.9.0'} 108 | 109 | '@docsearch/css@3.8.2': 110 | resolution: {integrity: sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==} 111 | 112 | '@docsearch/js@3.8.2': 113 | resolution: {integrity: sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==} 114 | 115 | '@docsearch/react@3.8.2': 116 | resolution: {integrity: sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==} 117 | peerDependencies: 118 | '@types/react': '>= 16.8.0 < 19.0.0' 119 | react: '>= 16.8.0 < 19.0.0' 120 | react-dom: '>= 16.8.0 < 19.0.0' 121 | search-insights: '>= 1 < 3' 122 | peerDependenciesMeta: 123 | '@types/react': 124 | optional: true 125 | react: 126 | optional: true 127 | react-dom: 128 | optional: true 129 | search-insights: 130 | optional: true 131 | 132 | '@esbuild/aix-ppc64@0.21.5': 133 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 134 | engines: {node: '>=12'} 135 | cpu: [ppc64] 136 | os: [aix] 137 | 138 | '@esbuild/android-arm64@0.21.5': 139 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 140 | engines: {node: '>=12'} 141 | cpu: [arm64] 142 | os: [android] 143 | 144 | '@esbuild/android-arm@0.21.5': 145 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 146 | engines: {node: '>=12'} 147 | cpu: [arm] 148 | os: [android] 149 | 150 | '@esbuild/android-x64@0.21.5': 151 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 152 | engines: {node: '>=12'} 153 | cpu: [x64] 154 | os: [android] 155 | 156 | '@esbuild/darwin-arm64@0.21.5': 157 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 158 | engines: {node: '>=12'} 159 | cpu: [arm64] 160 | os: [darwin] 161 | 162 | '@esbuild/darwin-x64@0.21.5': 163 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 164 | engines: {node: '>=12'} 165 | cpu: [x64] 166 | os: [darwin] 167 | 168 | '@esbuild/freebsd-arm64@0.21.5': 169 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 170 | engines: {node: '>=12'} 171 | cpu: [arm64] 172 | os: [freebsd] 173 | 174 | '@esbuild/freebsd-x64@0.21.5': 175 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 176 | engines: {node: '>=12'} 177 | cpu: [x64] 178 | os: [freebsd] 179 | 180 | '@esbuild/linux-arm64@0.21.5': 181 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 182 | engines: {node: '>=12'} 183 | cpu: [arm64] 184 | os: [linux] 185 | 186 | '@esbuild/linux-arm@0.21.5': 187 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 188 | engines: {node: '>=12'} 189 | cpu: [arm] 190 | os: [linux] 191 | 192 | '@esbuild/linux-ia32@0.21.5': 193 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 194 | engines: {node: '>=12'} 195 | cpu: [ia32] 196 | os: [linux] 197 | 198 | '@esbuild/linux-loong64@0.21.5': 199 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 200 | engines: {node: '>=12'} 201 | cpu: [loong64] 202 | os: [linux] 203 | 204 | '@esbuild/linux-mips64el@0.21.5': 205 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 206 | engines: {node: '>=12'} 207 | cpu: [mips64el] 208 | os: [linux] 209 | 210 | '@esbuild/linux-ppc64@0.21.5': 211 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 212 | engines: {node: '>=12'} 213 | cpu: [ppc64] 214 | os: [linux] 215 | 216 | '@esbuild/linux-riscv64@0.21.5': 217 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 218 | engines: {node: '>=12'} 219 | cpu: [riscv64] 220 | os: [linux] 221 | 222 | '@esbuild/linux-s390x@0.21.5': 223 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 224 | engines: {node: '>=12'} 225 | cpu: [s390x] 226 | os: [linux] 227 | 228 | '@esbuild/linux-x64@0.21.5': 229 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 230 | engines: {node: '>=12'} 231 | cpu: [x64] 232 | os: [linux] 233 | 234 | '@esbuild/netbsd-x64@0.21.5': 235 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 236 | engines: {node: '>=12'} 237 | cpu: [x64] 238 | os: [netbsd] 239 | 240 | '@esbuild/openbsd-x64@0.21.5': 241 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 242 | engines: {node: '>=12'} 243 | cpu: [x64] 244 | os: [openbsd] 245 | 246 | '@esbuild/sunos-x64@0.21.5': 247 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 248 | engines: {node: '>=12'} 249 | cpu: [x64] 250 | os: [sunos] 251 | 252 | '@esbuild/win32-arm64@0.21.5': 253 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 254 | engines: {node: '>=12'} 255 | cpu: [arm64] 256 | os: [win32] 257 | 258 | '@esbuild/win32-ia32@0.21.5': 259 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 260 | engines: {node: '>=12'} 261 | cpu: [ia32] 262 | os: [win32] 263 | 264 | '@esbuild/win32-x64@0.21.5': 265 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 266 | engines: {node: '>=12'} 267 | cpu: [x64] 268 | os: [win32] 269 | 270 | '@iconify-json/simple-icons@1.2.19': 271 | resolution: {integrity: sha512-5ntmhLBUEKiakX3quPPXft+WfXIVfDINzTm3djZzzewah9ACxsCVaxoa4QVxlW8PMoF8jndXOqyHYZGCxwxoZw==} 272 | 273 | '@iconify/types@2.0.0': 274 | resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} 275 | 276 | '@jridgewell/sourcemap-codec@1.5.0': 277 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 278 | 279 | '@rollup/rollup-android-arm-eabi@4.30.1': 280 | resolution: {integrity: sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==} 281 | cpu: [arm] 282 | os: [android] 283 | 284 | '@rollup/rollup-android-arm64@4.30.1': 285 | resolution: {integrity: sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==} 286 | cpu: [arm64] 287 | os: [android] 288 | 289 | '@rollup/rollup-darwin-arm64@4.30.1': 290 | resolution: {integrity: sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==} 291 | cpu: [arm64] 292 | os: [darwin] 293 | 294 | '@rollup/rollup-darwin-x64@4.30.1': 295 | resolution: {integrity: sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==} 296 | cpu: [x64] 297 | os: [darwin] 298 | 299 | '@rollup/rollup-freebsd-arm64@4.30.1': 300 | resolution: {integrity: sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==} 301 | cpu: [arm64] 302 | os: [freebsd] 303 | 304 | '@rollup/rollup-freebsd-x64@4.30.1': 305 | resolution: {integrity: sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==} 306 | cpu: [x64] 307 | os: [freebsd] 308 | 309 | '@rollup/rollup-linux-arm-gnueabihf@4.30.1': 310 | resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==} 311 | cpu: [arm] 312 | os: [linux] 313 | 314 | '@rollup/rollup-linux-arm-musleabihf@4.30.1': 315 | resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==} 316 | cpu: [arm] 317 | os: [linux] 318 | 319 | '@rollup/rollup-linux-arm64-gnu@4.30.1': 320 | resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==} 321 | cpu: [arm64] 322 | os: [linux] 323 | 324 | '@rollup/rollup-linux-arm64-musl@4.30.1': 325 | resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==} 326 | cpu: [arm64] 327 | os: [linux] 328 | 329 | '@rollup/rollup-linux-loongarch64-gnu@4.30.1': 330 | resolution: {integrity: sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==} 331 | cpu: [loong64] 332 | os: [linux] 333 | 334 | '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': 335 | resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==} 336 | cpu: [ppc64] 337 | os: [linux] 338 | 339 | '@rollup/rollup-linux-riscv64-gnu@4.30.1': 340 | resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==} 341 | cpu: [riscv64] 342 | os: [linux] 343 | 344 | '@rollup/rollup-linux-s390x-gnu@4.30.1': 345 | resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==} 346 | cpu: [s390x] 347 | os: [linux] 348 | 349 | '@rollup/rollup-linux-x64-gnu@4.30.1': 350 | resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==} 351 | cpu: [x64] 352 | os: [linux] 353 | 354 | '@rollup/rollup-linux-x64-musl@4.30.1': 355 | resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==} 356 | cpu: [x64] 357 | os: [linux] 358 | 359 | '@rollup/rollup-win32-arm64-msvc@4.30.1': 360 | resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==} 361 | cpu: [arm64] 362 | os: [win32] 363 | 364 | '@rollup/rollup-win32-ia32-msvc@4.30.1': 365 | resolution: {integrity: sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==} 366 | cpu: [ia32] 367 | os: [win32] 368 | 369 | '@rollup/rollup-win32-x64-msvc@4.30.1': 370 | resolution: {integrity: sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==} 371 | cpu: [x64] 372 | os: [win32] 373 | 374 | '@shikijs/core@1.26.1': 375 | resolution: {integrity: sha512-yeo7sG+WZQblKPclUOKRPwkv1PyoHYkJ4gP9DzhFJbTdueKR7wYTI1vfF/bFi1NTgc545yG/DzvVhZgueVOXMA==} 376 | 377 | '@shikijs/engine-javascript@1.26.1': 378 | resolution: {integrity: sha512-CRhA0b8CaSLxS0E9A4Bzcb3LKBNpykfo9F85ozlNyArxjo2NkijtiwrJZ6eHa+NT5I9Kox2IXVdjUsP4dilsmw==} 379 | 380 | '@shikijs/engine-oniguruma@1.26.1': 381 | resolution: {integrity: sha512-F5XuxN1HljLuvfXv7d+mlTkV7XukC1cawdtOo+7pKgPD83CAB1Sf8uHqP3PK0u7njFH0ZhoXE1r+0JzEgAQ+kg==} 382 | 383 | '@shikijs/langs@1.26.1': 384 | resolution: {integrity: sha512-oz/TQiIqZejEIZbGtn68hbJijAOTtYH4TMMSWkWYozwqdpKR3EXgILneQy26WItmJjp3xVspHdiUxUCws4gtuw==} 385 | 386 | '@shikijs/themes@1.26.1': 387 | resolution: {integrity: sha512-JDxVn+z+wgLCiUhBGx2OQrLCkKZQGzNH3nAxFir4PjUcYiyD8Jdms9izyxIogYmSwmoPTatFTdzyrRKbKlSfPA==} 388 | 389 | '@shikijs/transformers@1.26.1': 390 | resolution: {integrity: sha512-IRLJEP7YxkRMsHo367+7qDlpWjsUu6O79pdlUlkcbF1A5TrF1Ln0FBNrgHA/i9p+IKXiiKNATURa6WXh3iq7Uw==} 391 | 392 | '@shikijs/types@1.26.1': 393 | resolution: {integrity: sha512-d4B00TKKAMaHuFYgRf3L0gwtvqpW4hVdVwKcZYbBfAAQXspgkbWqnFfuFl3MDH6gLbsubOcr+prcnsqah3ny7Q==} 394 | 395 | '@shikijs/vscode-textmate@10.0.1': 396 | resolution: {integrity: sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg==} 397 | 398 | '@types/estree@1.0.6': 399 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 400 | 401 | '@types/hast@3.0.4': 402 | resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} 403 | 404 | '@types/linkify-it@5.0.0': 405 | resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} 406 | 407 | '@types/markdown-it@14.1.2': 408 | resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} 409 | 410 | '@types/mdast@4.0.4': 411 | resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} 412 | 413 | '@types/mdurl@2.0.0': 414 | resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} 415 | 416 | '@types/unist@3.0.3': 417 | resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} 418 | 419 | '@types/web-bluetooth@0.0.20': 420 | resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} 421 | 422 | '@ungap/structured-clone@1.2.1': 423 | resolution: {integrity: sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==} 424 | 425 | '@vitejs/plugin-vue@5.2.1': 426 | resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} 427 | engines: {node: ^18.0.0 || >=20.0.0} 428 | peerDependencies: 429 | vite: ^5.0.0 || ^6.0.0 430 | vue: ^3.2.25 431 | 432 | '@vue/compiler-core@3.5.13': 433 | resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} 434 | 435 | '@vue/compiler-dom@3.5.13': 436 | resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} 437 | 438 | '@vue/compiler-sfc@3.5.13': 439 | resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} 440 | 441 | '@vue/compiler-ssr@3.5.13': 442 | resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} 443 | 444 | '@vue/devtools-api@7.7.0': 445 | resolution: {integrity: sha512-bHEv6kT85BHtyGgDhE07bAUMAy7zpv6nnR004nSTd0wWMrAOtcrYoXO5iyr20Hkf5jR8obQOfS3byW+I3l2CCA==} 446 | 447 | '@vue/devtools-kit@7.7.0': 448 | resolution: {integrity: sha512-5cvZ+6SA88zKC8XiuxUfqpdTwVjJbvYnQZY5NReh7qlSGPvVDjjzyEtW+gdzLXNSd8tStgOjAdMCpvDQamUXtA==} 449 | 450 | '@vue/devtools-shared@7.7.0': 451 | resolution: {integrity: sha512-jtlQY26R5thQxW9YQTpXbI0HoK0Wf9Rd4ekidOkRvSy7ChfK0kIU6vvcBtjj87/EcpeOSK49fZAicaFNJcoTcQ==} 452 | 453 | '@vue/reactivity@3.5.13': 454 | resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} 455 | 456 | '@vue/runtime-core@3.5.13': 457 | resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} 458 | 459 | '@vue/runtime-dom@3.5.13': 460 | resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} 461 | 462 | '@vue/server-renderer@3.5.13': 463 | resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} 464 | peerDependencies: 465 | vue: 3.5.13 466 | 467 | '@vue/shared@3.5.13': 468 | resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} 469 | 470 | '@vueuse/core@11.3.0': 471 | resolution: {integrity: sha512-7OC4Rl1f9G8IT6rUfi9JrKiXy4bfmHhZ5x2Ceojy0jnd3mHNEvV4JaRygH362ror6/NZ+Nl+n13LPzGiPN8cKA==} 472 | 473 | '@vueuse/integrations@11.3.0': 474 | resolution: {integrity: sha512-5fzRl0apQWrDezmobchoiGTkGw238VWESxZHazfhP3RM7pDSiyXy18QbfYkILoYNTd23HPAfQTJpkUc5QbkwTw==} 475 | peerDependencies: 476 | async-validator: ^4 477 | axios: ^1 478 | change-case: ^5 479 | drauu: ^0.4 480 | focus-trap: ^7 481 | fuse.js: ^7 482 | idb-keyval: ^6 483 | jwt-decode: ^4 484 | nprogress: ^0.2 485 | qrcode: ^1.5 486 | sortablejs: ^1 487 | universal-cookie: ^7 488 | peerDependenciesMeta: 489 | async-validator: 490 | optional: true 491 | axios: 492 | optional: true 493 | change-case: 494 | optional: true 495 | drauu: 496 | optional: true 497 | focus-trap: 498 | optional: true 499 | fuse.js: 500 | optional: true 501 | idb-keyval: 502 | optional: true 503 | jwt-decode: 504 | optional: true 505 | nprogress: 506 | optional: true 507 | qrcode: 508 | optional: true 509 | sortablejs: 510 | optional: true 511 | universal-cookie: 512 | optional: true 513 | 514 | '@vueuse/metadata@11.3.0': 515 | resolution: {integrity: sha512-pwDnDspTqtTo2HwfLw4Rp6yywuuBdYnPYDq+mO38ZYKGebCUQC/nVj/PXSiK9HX5otxLz8Fn7ECPbjiRz2CC3g==} 516 | 517 | '@vueuse/shared@11.3.0': 518 | resolution: {integrity: sha512-P8gSSWQeucH5821ek2mn/ciCk+MS/zoRKqdQIM3bHq6p7GXDAJLmnRRKmF5F65sAVJIfzQlwR3aDzwCn10s8hA==} 519 | 520 | algoliasearch@5.19.0: 521 | resolution: {integrity: sha512-zrLtGhC63z3sVLDDKGW+SlCRN9eJHFTgdEmoAOpsVh6wgGL1GgTTDou7tpCBjevzgIvi3AIyDAQO3Xjbg5eqZg==} 522 | engines: {node: '>= 14.0.0'} 523 | 524 | asynckit@0.4.0: 525 | resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} 526 | 527 | axios@1.7.9: 528 | resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} 529 | 530 | birpc@0.2.19: 531 | resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} 532 | 533 | ccount@2.0.1: 534 | resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} 535 | 536 | character-entities-html4@2.1.0: 537 | resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} 538 | 539 | character-entities-legacy@3.0.0: 540 | resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} 541 | 542 | combined-stream@1.0.8: 543 | resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} 544 | engines: {node: '>= 0.8'} 545 | 546 | comma-separated-tokens@2.0.3: 547 | resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} 548 | 549 | copy-anything@3.0.5: 550 | resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} 551 | engines: {node: '>=12.13'} 552 | 553 | csstype@3.1.3: 554 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 555 | 556 | delayed-stream@1.0.0: 557 | resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} 558 | engines: {node: '>=0.4.0'} 559 | 560 | dequal@2.0.3: 561 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} 562 | engines: {node: '>=6'} 563 | 564 | devlop@1.1.0: 565 | resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} 566 | 567 | emoji-regex-xs@1.0.0: 568 | resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} 569 | 570 | entities@4.5.0: 571 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 572 | engines: {node: '>=0.12'} 573 | 574 | esbuild@0.21.5: 575 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 576 | engines: {node: '>=12'} 577 | hasBin: true 578 | 579 | estree-walker@2.0.2: 580 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 581 | 582 | focus-trap@7.6.4: 583 | resolution: {integrity: sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==} 584 | 585 | follow-redirects@1.15.9: 586 | resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} 587 | engines: {node: '>=4.0'} 588 | peerDependencies: 589 | debug: '*' 590 | peerDependenciesMeta: 591 | debug: 592 | optional: true 593 | 594 | form-data@4.0.1: 595 | resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} 596 | engines: {node: '>= 6'} 597 | 598 | fsevents@2.3.3: 599 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 600 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 601 | os: [darwin] 602 | 603 | hast-util-to-html@9.0.4: 604 | resolution: {integrity: sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==} 605 | 606 | hast-util-whitespace@3.0.0: 607 | resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} 608 | 609 | hookable@5.5.3: 610 | resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} 611 | 612 | html-void-elements@3.0.0: 613 | resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} 614 | 615 | is-what@4.1.16: 616 | resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} 617 | engines: {node: '>=12.13'} 618 | 619 | magic-string@0.30.17: 620 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} 621 | 622 | mark.js@8.11.1: 623 | resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} 624 | 625 | mdast-util-to-hast@13.2.0: 626 | resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} 627 | 628 | micromark-util-character@2.1.1: 629 | resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} 630 | 631 | micromark-util-encode@2.0.1: 632 | resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} 633 | 634 | micromark-util-sanitize-uri@2.0.1: 635 | resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} 636 | 637 | micromark-util-symbol@2.0.1: 638 | resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} 639 | 640 | micromark-util-types@2.0.1: 641 | resolution: {integrity: sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==} 642 | 643 | mime-db@1.52.0: 644 | resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} 645 | engines: {node: '>= 0.6'} 646 | 647 | mime-types@2.1.35: 648 | resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} 649 | engines: {node: '>= 0.6'} 650 | 651 | minisearch@7.1.1: 652 | resolution: {integrity: sha512-b3YZEYCEH4EdCAtYP7OlDyx7FdPwNzuNwLQ34SfJpM9dlbBZzeXndGavTrC+VCiRWomL21SWfMc6SCKO/U2ZNw==} 653 | 654 | mitt@3.0.1: 655 | resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} 656 | 657 | nanoid@3.3.8: 658 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} 659 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 660 | hasBin: true 661 | 662 | oniguruma-to-es@0.10.0: 663 | resolution: {integrity: sha512-zapyOUOCJxt+xhiNRPPMtfJkHGsZ98HHB9qJEkdT8BGytO/+kpe4m1Ngf0MzbzTmhacn11w9yGeDP6tzDhnCdg==} 664 | 665 | perfect-debounce@1.0.0: 666 | resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} 667 | 668 | picocolors@1.1.1: 669 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 670 | 671 | postcss@8.4.49: 672 | resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} 673 | engines: {node: ^10 || ^12 || >=14} 674 | 675 | preact@10.25.4: 676 | resolution: {integrity: sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==} 677 | 678 | property-information@6.5.0: 679 | resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} 680 | 681 | proxy-from-env@1.1.0: 682 | resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} 683 | 684 | regex-recursion@5.1.1: 685 | resolution: {integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==} 686 | 687 | regex-utilities@2.3.0: 688 | resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} 689 | 690 | regex@5.1.1: 691 | resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==} 692 | 693 | rfdc@1.4.1: 694 | resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} 695 | 696 | rollup@4.30.1: 697 | resolution: {integrity: sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==} 698 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 699 | hasBin: true 700 | 701 | search-insights@2.17.3: 702 | resolution: {integrity: sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==} 703 | 704 | shiki@1.26.1: 705 | resolution: {integrity: sha512-Gqg6DSTk3wYqaZ5OaYtzjcdxcBvX5kCy24yvRJEgjT5U+WHlmqCThLuBUx0juyxQBi+6ug53IGeuQS07DWwpcw==} 706 | 707 | source-map-js@1.2.1: 708 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 709 | engines: {node: '>=0.10.0'} 710 | 711 | space-separated-tokens@2.0.2: 712 | resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} 713 | 714 | speakingurl@14.0.1: 715 | resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} 716 | engines: {node: '>=0.10.0'} 717 | 718 | stringify-entities@4.0.4: 719 | resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} 720 | 721 | superjson@2.2.2: 722 | resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==} 723 | engines: {node: '>=16'} 724 | 725 | tabbable@6.2.0: 726 | resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} 727 | 728 | trim-lines@3.0.1: 729 | resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} 730 | 731 | unist-util-is@6.0.0: 732 | resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} 733 | 734 | unist-util-position@5.0.0: 735 | resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} 736 | 737 | unist-util-stringify-position@4.0.0: 738 | resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} 739 | 740 | unist-util-visit-parents@6.0.1: 741 | resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} 742 | 743 | unist-util-visit@5.0.0: 744 | resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} 745 | 746 | vfile-message@4.0.2: 747 | resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} 748 | 749 | vfile@6.0.3: 750 | resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} 751 | 752 | vite@5.4.11: 753 | resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} 754 | engines: {node: ^18.0.0 || >=20.0.0} 755 | hasBin: true 756 | peerDependencies: 757 | '@types/node': ^18.0.0 || >=20.0.0 758 | less: '*' 759 | lightningcss: ^1.21.0 760 | sass: '*' 761 | sass-embedded: '*' 762 | stylus: '*' 763 | sugarss: '*' 764 | terser: ^5.4.0 765 | peerDependenciesMeta: 766 | '@types/node': 767 | optional: true 768 | less: 769 | optional: true 770 | lightningcss: 771 | optional: true 772 | sass: 773 | optional: true 774 | sass-embedded: 775 | optional: true 776 | stylus: 777 | optional: true 778 | sugarss: 779 | optional: true 780 | terser: 781 | optional: true 782 | 783 | vitepress@1.5.0: 784 | resolution: {integrity: sha512-q4Q/G2zjvynvizdB3/bupdYkCJe2umSAMv9Ju4d92E6/NXJ59z70xB0q5p/4lpRyAwflDsbwy1mLV9Q5+nlB+g==} 785 | hasBin: true 786 | peerDependencies: 787 | markdown-it-mathjax3: ^4 788 | postcss: ^8 789 | peerDependenciesMeta: 790 | markdown-it-mathjax3: 791 | optional: true 792 | postcss: 793 | optional: true 794 | 795 | vue-demi@0.14.10: 796 | resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} 797 | engines: {node: '>=12'} 798 | hasBin: true 799 | peerDependencies: 800 | '@vue/composition-api': ^1.0.0-rc.1 801 | vue: ^3.0.0-0 || ^2.6.0 802 | peerDependenciesMeta: 803 | '@vue/composition-api': 804 | optional: true 805 | 806 | vue@3.5.13: 807 | resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} 808 | peerDependencies: 809 | typescript: '*' 810 | peerDependenciesMeta: 811 | typescript: 812 | optional: true 813 | 814 | zwitch@2.0.4: 815 | resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} 816 | 817 | snapshots: 818 | 819 | '@algolia/autocomplete-core@1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0)(search-insights@2.17.3)': 820 | dependencies: 821 | '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0)(search-insights@2.17.3) 822 | '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0) 823 | transitivePeerDependencies: 824 | - '@algolia/client-search' 825 | - algoliasearch 826 | - search-insights 827 | 828 | '@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0)(search-insights@2.17.3)': 829 | dependencies: 830 | '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0) 831 | search-insights: 2.17.3 832 | transitivePeerDependencies: 833 | - '@algolia/client-search' 834 | - algoliasearch 835 | 836 | '@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0)': 837 | dependencies: 838 | '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0) 839 | '@algolia/client-search': 5.19.0 840 | algoliasearch: 5.19.0 841 | 842 | '@algolia/autocomplete-shared@1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0)': 843 | dependencies: 844 | '@algolia/client-search': 5.19.0 845 | algoliasearch: 5.19.0 846 | 847 | '@algolia/client-abtesting@5.19.0': 848 | dependencies: 849 | '@algolia/client-common': 5.19.0 850 | '@algolia/requester-browser-xhr': 5.19.0 851 | '@algolia/requester-fetch': 5.19.0 852 | '@algolia/requester-node-http': 5.19.0 853 | 854 | '@algolia/client-analytics@5.19.0': 855 | dependencies: 856 | '@algolia/client-common': 5.19.0 857 | '@algolia/requester-browser-xhr': 5.19.0 858 | '@algolia/requester-fetch': 5.19.0 859 | '@algolia/requester-node-http': 5.19.0 860 | 861 | '@algolia/client-common@5.19.0': {} 862 | 863 | '@algolia/client-insights@5.19.0': 864 | dependencies: 865 | '@algolia/client-common': 5.19.0 866 | '@algolia/requester-browser-xhr': 5.19.0 867 | '@algolia/requester-fetch': 5.19.0 868 | '@algolia/requester-node-http': 5.19.0 869 | 870 | '@algolia/client-personalization@5.19.0': 871 | dependencies: 872 | '@algolia/client-common': 5.19.0 873 | '@algolia/requester-browser-xhr': 5.19.0 874 | '@algolia/requester-fetch': 5.19.0 875 | '@algolia/requester-node-http': 5.19.0 876 | 877 | '@algolia/client-query-suggestions@5.19.0': 878 | dependencies: 879 | '@algolia/client-common': 5.19.0 880 | '@algolia/requester-browser-xhr': 5.19.0 881 | '@algolia/requester-fetch': 5.19.0 882 | '@algolia/requester-node-http': 5.19.0 883 | 884 | '@algolia/client-search@5.19.0': 885 | dependencies: 886 | '@algolia/client-common': 5.19.0 887 | '@algolia/requester-browser-xhr': 5.19.0 888 | '@algolia/requester-fetch': 5.19.0 889 | '@algolia/requester-node-http': 5.19.0 890 | 891 | '@algolia/ingestion@1.19.0': 892 | dependencies: 893 | '@algolia/client-common': 5.19.0 894 | '@algolia/requester-browser-xhr': 5.19.0 895 | '@algolia/requester-fetch': 5.19.0 896 | '@algolia/requester-node-http': 5.19.0 897 | 898 | '@algolia/monitoring@1.19.0': 899 | dependencies: 900 | '@algolia/client-common': 5.19.0 901 | '@algolia/requester-browser-xhr': 5.19.0 902 | '@algolia/requester-fetch': 5.19.0 903 | '@algolia/requester-node-http': 5.19.0 904 | 905 | '@algolia/recommend@5.19.0': 906 | dependencies: 907 | '@algolia/client-common': 5.19.0 908 | '@algolia/requester-browser-xhr': 5.19.0 909 | '@algolia/requester-fetch': 5.19.0 910 | '@algolia/requester-node-http': 5.19.0 911 | 912 | '@algolia/requester-browser-xhr@5.19.0': 913 | dependencies: 914 | '@algolia/client-common': 5.19.0 915 | 916 | '@algolia/requester-fetch@5.19.0': 917 | dependencies: 918 | '@algolia/client-common': 5.19.0 919 | 920 | '@algolia/requester-node-http@5.19.0': 921 | dependencies: 922 | '@algolia/client-common': 5.19.0 923 | 924 | '@babel/helper-string-parser@7.25.9': {} 925 | 926 | '@babel/helper-validator-identifier@7.25.9': {} 927 | 928 | '@babel/parser@7.26.5': 929 | dependencies: 930 | '@babel/types': 7.26.5 931 | 932 | '@babel/types@7.26.5': 933 | dependencies: 934 | '@babel/helper-string-parser': 7.25.9 935 | '@babel/helper-validator-identifier': 7.25.9 936 | 937 | '@docsearch/css@3.8.2': {} 938 | 939 | '@docsearch/js@3.8.2(@algolia/client-search@5.19.0)(search-insights@2.17.3)': 940 | dependencies: 941 | '@docsearch/react': 3.8.2(@algolia/client-search@5.19.0)(search-insights@2.17.3) 942 | preact: 10.25.4 943 | transitivePeerDependencies: 944 | - '@algolia/client-search' 945 | - '@types/react' 946 | - react 947 | - react-dom 948 | - search-insights 949 | 950 | '@docsearch/react@3.8.2(@algolia/client-search@5.19.0)(search-insights@2.17.3)': 951 | dependencies: 952 | '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0)(search-insights@2.17.3) 953 | '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@5.19.0)(algoliasearch@5.19.0) 954 | '@docsearch/css': 3.8.2 955 | algoliasearch: 5.19.0 956 | optionalDependencies: 957 | search-insights: 2.17.3 958 | transitivePeerDependencies: 959 | - '@algolia/client-search' 960 | 961 | '@esbuild/aix-ppc64@0.21.5': 962 | optional: true 963 | 964 | '@esbuild/android-arm64@0.21.5': 965 | optional: true 966 | 967 | '@esbuild/android-arm@0.21.5': 968 | optional: true 969 | 970 | '@esbuild/android-x64@0.21.5': 971 | optional: true 972 | 973 | '@esbuild/darwin-arm64@0.21.5': 974 | optional: true 975 | 976 | '@esbuild/darwin-x64@0.21.5': 977 | optional: true 978 | 979 | '@esbuild/freebsd-arm64@0.21.5': 980 | optional: true 981 | 982 | '@esbuild/freebsd-x64@0.21.5': 983 | optional: true 984 | 985 | '@esbuild/linux-arm64@0.21.5': 986 | optional: true 987 | 988 | '@esbuild/linux-arm@0.21.5': 989 | optional: true 990 | 991 | '@esbuild/linux-ia32@0.21.5': 992 | optional: true 993 | 994 | '@esbuild/linux-loong64@0.21.5': 995 | optional: true 996 | 997 | '@esbuild/linux-mips64el@0.21.5': 998 | optional: true 999 | 1000 | '@esbuild/linux-ppc64@0.21.5': 1001 | optional: true 1002 | 1003 | '@esbuild/linux-riscv64@0.21.5': 1004 | optional: true 1005 | 1006 | '@esbuild/linux-s390x@0.21.5': 1007 | optional: true 1008 | 1009 | '@esbuild/linux-x64@0.21.5': 1010 | optional: true 1011 | 1012 | '@esbuild/netbsd-x64@0.21.5': 1013 | optional: true 1014 | 1015 | '@esbuild/openbsd-x64@0.21.5': 1016 | optional: true 1017 | 1018 | '@esbuild/sunos-x64@0.21.5': 1019 | optional: true 1020 | 1021 | '@esbuild/win32-arm64@0.21.5': 1022 | optional: true 1023 | 1024 | '@esbuild/win32-ia32@0.21.5': 1025 | optional: true 1026 | 1027 | '@esbuild/win32-x64@0.21.5': 1028 | optional: true 1029 | 1030 | '@iconify-json/simple-icons@1.2.19': 1031 | dependencies: 1032 | '@iconify/types': 2.0.0 1033 | 1034 | '@iconify/types@2.0.0': {} 1035 | 1036 | '@jridgewell/sourcemap-codec@1.5.0': {} 1037 | 1038 | '@rollup/rollup-android-arm-eabi@4.30.1': 1039 | optional: true 1040 | 1041 | '@rollup/rollup-android-arm64@4.30.1': 1042 | optional: true 1043 | 1044 | '@rollup/rollup-darwin-arm64@4.30.1': 1045 | optional: true 1046 | 1047 | '@rollup/rollup-darwin-x64@4.30.1': 1048 | optional: true 1049 | 1050 | '@rollup/rollup-freebsd-arm64@4.30.1': 1051 | optional: true 1052 | 1053 | '@rollup/rollup-freebsd-x64@4.30.1': 1054 | optional: true 1055 | 1056 | '@rollup/rollup-linux-arm-gnueabihf@4.30.1': 1057 | optional: true 1058 | 1059 | '@rollup/rollup-linux-arm-musleabihf@4.30.1': 1060 | optional: true 1061 | 1062 | '@rollup/rollup-linux-arm64-gnu@4.30.1': 1063 | optional: true 1064 | 1065 | '@rollup/rollup-linux-arm64-musl@4.30.1': 1066 | optional: true 1067 | 1068 | '@rollup/rollup-linux-loongarch64-gnu@4.30.1': 1069 | optional: true 1070 | 1071 | '@rollup/rollup-linux-powerpc64le-gnu@4.30.1': 1072 | optional: true 1073 | 1074 | '@rollup/rollup-linux-riscv64-gnu@4.30.1': 1075 | optional: true 1076 | 1077 | '@rollup/rollup-linux-s390x-gnu@4.30.1': 1078 | optional: true 1079 | 1080 | '@rollup/rollup-linux-x64-gnu@4.30.1': 1081 | optional: true 1082 | 1083 | '@rollup/rollup-linux-x64-musl@4.30.1': 1084 | optional: true 1085 | 1086 | '@rollup/rollup-win32-arm64-msvc@4.30.1': 1087 | optional: true 1088 | 1089 | '@rollup/rollup-win32-ia32-msvc@4.30.1': 1090 | optional: true 1091 | 1092 | '@rollup/rollup-win32-x64-msvc@4.30.1': 1093 | optional: true 1094 | 1095 | '@shikijs/core@1.26.1': 1096 | dependencies: 1097 | '@shikijs/engine-javascript': 1.26.1 1098 | '@shikijs/engine-oniguruma': 1.26.1 1099 | '@shikijs/types': 1.26.1 1100 | '@shikijs/vscode-textmate': 10.0.1 1101 | '@types/hast': 3.0.4 1102 | hast-util-to-html: 9.0.4 1103 | 1104 | '@shikijs/engine-javascript@1.26.1': 1105 | dependencies: 1106 | '@shikijs/types': 1.26.1 1107 | '@shikijs/vscode-textmate': 10.0.1 1108 | oniguruma-to-es: 0.10.0 1109 | 1110 | '@shikijs/engine-oniguruma@1.26.1': 1111 | dependencies: 1112 | '@shikijs/types': 1.26.1 1113 | '@shikijs/vscode-textmate': 10.0.1 1114 | 1115 | '@shikijs/langs@1.26.1': 1116 | dependencies: 1117 | '@shikijs/types': 1.26.1 1118 | 1119 | '@shikijs/themes@1.26.1': 1120 | dependencies: 1121 | '@shikijs/types': 1.26.1 1122 | 1123 | '@shikijs/transformers@1.26.1': 1124 | dependencies: 1125 | shiki: 1.26.1 1126 | 1127 | '@shikijs/types@1.26.1': 1128 | dependencies: 1129 | '@shikijs/vscode-textmate': 10.0.1 1130 | '@types/hast': 3.0.4 1131 | 1132 | '@shikijs/vscode-textmate@10.0.1': {} 1133 | 1134 | '@types/estree@1.0.6': {} 1135 | 1136 | '@types/hast@3.0.4': 1137 | dependencies: 1138 | '@types/unist': 3.0.3 1139 | 1140 | '@types/linkify-it@5.0.0': {} 1141 | 1142 | '@types/markdown-it@14.1.2': 1143 | dependencies: 1144 | '@types/linkify-it': 5.0.0 1145 | '@types/mdurl': 2.0.0 1146 | 1147 | '@types/mdast@4.0.4': 1148 | dependencies: 1149 | '@types/unist': 3.0.3 1150 | 1151 | '@types/mdurl@2.0.0': {} 1152 | 1153 | '@types/unist@3.0.3': {} 1154 | 1155 | '@types/web-bluetooth@0.0.20': {} 1156 | 1157 | '@ungap/structured-clone@1.2.1': {} 1158 | 1159 | '@vitejs/plugin-vue@5.2.1(vite@5.4.11)(vue@3.5.13)': 1160 | dependencies: 1161 | vite: 5.4.11 1162 | vue: 3.5.13 1163 | 1164 | '@vue/compiler-core@3.5.13': 1165 | dependencies: 1166 | '@babel/parser': 7.26.5 1167 | '@vue/shared': 3.5.13 1168 | entities: 4.5.0 1169 | estree-walker: 2.0.2 1170 | source-map-js: 1.2.1 1171 | 1172 | '@vue/compiler-dom@3.5.13': 1173 | dependencies: 1174 | '@vue/compiler-core': 3.5.13 1175 | '@vue/shared': 3.5.13 1176 | 1177 | '@vue/compiler-sfc@3.5.13': 1178 | dependencies: 1179 | '@babel/parser': 7.26.5 1180 | '@vue/compiler-core': 3.5.13 1181 | '@vue/compiler-dom': 3.5.13 1182 | '@vue/compiler-ssr': 3.5.13 1183 | '@vue/shared': 3.5.13 1184 | estree-walker: 2.0.2 1185 | magic-string: 0.30.17 1186 | postcss: 8.4.49 1187 | source-map-js: 1.2.1 1188 | 1189 | '@vue/compiler-ssr@3.5.13': 1190 | dependencies: 1191 | '@vue/compiler-dom': 3.5.13 1192 | '@vue/shared': 3.5.13 1193 | 1194 | '@vue/devtools-api@7.7.0': 1195 | dependencies: 1196 | '@vue/devtools-kit': 7.7.0 1197 | 1198 | '@vue/devtools-kit@7.7.0': 1199 | dependencies: 1200 | '@vue/devtools-shared': 7.7.0 1201 | birpc: 0.2.19 1202 | hookable: 5.5.3 1203 | mitt: 3.0.1 1204 | perfect-debounce: 1.0.0 1205 | speakingurl: 14.0.1 1206 | superjson: 2.2.2 1207 | 1208 | '@vue/devtools-shared@7.7.0': 1209 | dependencies: 1210 | rfdc: 1.4.1 1211 | 1212 | '@vue/reactivity@3.5.13': 1213 | dependencies: 1214 | '@vue/shared': 3.5.13 1215 | 1216 | '@vue/runtime-core@3.5.13': 1217 | dependencies: 1218 | '@vue/reactivity': 3.5.13 1219 | '@vue/shared': 3.5.13 1220 | 1221 | '@vue/runtime-dom@3.5.13': 1222 | dependencies: 1223 | '@vue/reactivity': 3.5.13 1224 | '@vue/runtime-core': 3.5.13 1225 | '@vue/shared': 3.5.13 1226 | csstype: 3.1.3 1227 | 1228 | '@vue/server-renderer@3.5.13(vue@3.5.13)': 1229 | dependencies: 1230 | '@vue/compiler-ssr': 3.5.13 1231 | '@vue/shared': 3.5.13 1232 | vue: 3.5.13 1233 | 1234 | '@vue/shared@3.5.13': {} 1235 | 1236 | '@vueuse/core@11.3.0(vue@3.5.13)': 1237 | dependencies: 1238 | '@types/web-bluetooth': 0.0.20 1239 | '@vueuse/metadata': 11.3.0 1240 | '@vueuse/shared': 11.3.0(vue@3.5.13) 1241 | vue-demi: 0.14.10(vue@3.5.13) 1242 | transitivePeerDependencies: 1243 | - '@vue/composition-api' 1244 | - vue 1245 | 1246 | '@vueuse/integrations@11.3.0(axios@1.7.9)(focus-trap@7.6.4)(vue@3.5.13)': 1247 | dependencies: 1248 | '@vueuse/core': 11.3.0(vue@3.5.13) 1249 | '@vueuse/shared': 11.3.0(vue@3.5.13) 1250 | vue-demi: 0.14.10(vue@3.5.13) 1251 | optionalDependencies: 1252 | axios: 1.7.9 1253 | focus-trap: 7.6.4 1254 | transitivePeerDependencies: 1255 | - '@vue/composition-api' 1256 | - vue 1257 | 1258 | '@vueuse/metadata@11.3.0': {} 1259 | 1260 | '@vueuse/shared@11.3.0(vue@3.5.13)': 1261 | dependencies: 1262 | vue-demi: 0.14.10(vue@3.5.13) 1263 | transitivePeerDependencies: 1264 | - '@vue/composition-api' 1265 | - vue 1266 | 1267 | algoliasearch@5.19.0: 1268 | dependencies: 1269 | '@algolia/client-abtesting': 5.19.0 1270 | '@algolia/client-analytics': 5.19.0 1271 | '@algolia/client-common': 5.19.0 1272 | '@algolia/client-insights': 5.19.0 1273 | '@algolia/client-personalization': 5.19.0 1274 | '@algolia/client-query-suggestions': 5.19.0 1275 | '@algolia/client-search': 5.19.0 1276 | '@algolia/ingestion': 1.19.0 1277 | '@algolia/monitoring': 1.19.0 1278 | '@algolia/recommend': 5.19.0 1279 | '@algolia/requester-browser-xhr': 5.19.0 1280 | '@algolia/requester-fetch': 5.19.0 1281 | '@algolia/requester-node-http': 5.19.0 1282 | 1283 | asynckit@0.4.0: {} 1284 | 1285 | axios@1.7.9: 1286 | dependencies: 1287 | follow-redirects: 1.15.9 1288 | form-data: 4.0.1 1289 | proxy-from-env: 1.1.0 1290 | transitivePeerDependencies: 1291 | - debug 1292 | 1293 | birpc@0.2.19: {} 1294 | 1295 | ccount@2.0.1: {} 1296 | 1297 | character-entities-html4@2.1.0: {} 1298 | 1299 | character-entities-legacy@3.0.0: {} 1300 | 1301 | combined-stream@1.0.8: 1302 | dependencies: 1303 | delayed-stream: 1.0.0 1304 | 1305 | comma-separated-tokens@2.0.3: {} 1306 | 1307 | copy-anything@3.0.5: 1308 | dependencies: 1309 | is-what: 4.1.16 1310 | 1311 | csstype@3.1.3: {} 1312 | 1313 | delayed-stream@1.0.0: {} 1314 | 1315 | dequal@2.0.3: {} 1316 | 1317 | devlop@1.1.0: 1318 | dependencies: 1319 | dequal: 2.0.3 1320 | 1321 | emoji-regex-xs@1.0.0: {} 1322 | 1323 | entities@4.5.0: {} 1324 | 1325 | esbuild@0.21.5: 1326 | optionalDependencies: 1327 | '@esbuild/aix-ppc64': 0.21.5 1328 | '@esbuild/android-arm': 0.21.5 1329 | '@esbuild/android-arm64': 0.21.5 1330 | '@esbuild/android-x64': 0.21.5 1331 | '@esbuild/darwin-arm64': 0.21.5 1332 | '@esbuild/darwin-x64': 0.21.5 1333 | '@esbuild/freebsd-arm64': 0.21.5 1334 | '@esbuild/freebsd-x64': 0.21.5 1335 | '@esbuild/linux-arm': 0.21.5 1336 | '@esbuild/linux-arm64': 0.21.5 1337 | '@esbuild/linux-ia32': 0.21.5 1338 | '@esbuild/linux-loong64': 0.21.5 1339 | '@esbuild/linux-mips64el': 0.21.5 1340 | '@esbuild/linux-ppc64': 0.21.5 1341 | '@esbuild/linux-riscv64': 0.21.5 1342 | '@esbuild/linux-s390x': 0.21.5 1343 | '@esbuild/linux-x64': 0.21.5 1344 | '@esbuild/netbsd-x64': 0.21.5 1345 | '@esbuild/openbsd-x64': 0.21.5 1346 | '@esbuild/sunos-x64': 0.21.5 1347 | '@esbuild/win32-arm64': 0.21.5 1348 | '@esbuild/win32-ia32': 0.21.5 1349 | '@esbuild/win32-x64': 0.21.5 1350 | 1351 | estree-walker@2.0.2: {} 1352 | 1353 | focus-trap@7.6.4: 1354 | dependencies: 1355 | tabbable: 6.2.0 1356 | 1357 | follow-redirects@1.15.9: {} 1358 | 1359 | form-data@4.0.1: 1360 | dependencies: 1361 | asynckit: 0.4.0 1362 | combined-stream: 1.0.8 1363 | mime-types: 2.1.35 1364 | 1365 | fsevents@2.3.3: 1366 | optional: true 1367 | 1368 | hast-util-to-html@9.0.4: 1369 | dependencies: 1370 | '@types/hast': 3.0.4 1371 | '@types/unist': 3.0.3 1372 | ccount: 2.0.1 1373 | comma-separated-tokens: 2.0.3 1374 | hast-util-whitespace: 3.0.0 1375 | html-void-elements: 3.0.0 1376 | mdast-util-to-hast: 13.2.0 1377 | property-information: 6.5.0 1378 | space-separated-tokens: 2.0.2 1379 | stringify-entities: 4.0.4 1380 | zwitch: 2.0.4 1381 | 1382 | hast-util-whitespace@3.0.0: 1383 | dependencies: 1384 | '@types/hast': 3.0.4 1385 | 1386 | hookable@5.5.3: {} 1387 | 1388 | html-void-elements@3.0.0: {} 1389 | 1390 | is-what@4.1.16: {} 1391 | 1392 | magic-string@0.30.17: 1393 | dependencies: 1394 | '@jridgewell/sourcemap-codec': 1.5.0 1395 | 1396 | mark.js@8.11.1: {} 1397 | 1398 | mdast-util-to-hast@13.2.0: 1399 | dependencies: 1400 | '@types/hast': 3.0.4 1401 | '@types/mdast': 4.0.4 1402 | '@ungap/structured-clone': 1.2.1 1403 | devlop: 1.1.0 1404 | micromark-util-sanitize-uri: 2.0.1 1405 | trim-lines: 3.0.1 1406 | unist-util-position: 5.0.0 1407 | unist-util-visit: 5.0.0 1408 | vfile: 6.0.3 1409 | 1410 | micromark-util-character@2.1.1: 1411 | dependencies: 1412 | micromark-util-symbol: 2.0.1 1413 | micromark-util-types: 2.0.1 1414 | 1415 | micromark-util-encode@2.0.1: {} 1416 | 1417 | micromark-util-sanitize-uri@2.0.1: 1418 | dependencies: 1419 | micromark-util-character: 2.1.1 1420 | micromark-util-encode: 2.0.1 1421 | micromark-util-symbol: 2.0.1 1422 | 1423 | micromark-util-symbol@2.0.1: {} 1424 | 1425 | micromark-util-types@2.0.1: {} 1426 | 1427 | mime-db@1.52.0: {} 1428 | 1429 | mime-types@2.1.35: 1430 | dependencies: 1431 | mime-db: 1.52.0 1432 | 1433 | minisearch@7.1.1: {} 1434 | 1435 | mitt@3.0.1: {} 1436 | 1437 | nanoid@3.3.8: {} 1438 | 1439 | oniguruma-to-es@0.10.0: 1440 | dependencies: 1441 | emoji-regex-xs: 1.0.0 1442 | regex: 5.1.1 1443 | regex-recursion: 5.1.1 1444 | 1445 | perfect-debounce@1.0.0: {} 1446 | 1447 | picocolors@1.1.1: {} 1448 | 1449 | postcss@8.4.49: 1450 | dependencies: 1451 | nanoid: 3.3.8 1452 | picocolors: 1.1.1 1453 | source-map-js: 1.2.1 1454 | 1455 | preact@10.25.4: {} 1456 | 1457 | property-information@6.5.0: {} 1458 | 1459 | proxy-from-env@1.1.0: {} 1460 | 1461 | regex-recursion@5.1.1: 1462 | dependencies: 1463 | regex: 5.1.1 1464 | regex-utilities: 2.3.0 1465 | 1466 | regex-utilities@2.3.0: {} 1467 | 1468 | regex@5.1.1: 1469 | dependencies: 1470 | regex-utilities: 2.3.0 1471 | 1472 | rfdc@1.4.1: {} 1473 | 1474 | rollup@4.30.1: 1475 | dependencies: 1476 | '@types/estree': 1.0.6 1477 | optionalDependencies: 1478 | '@rollup/rollup-android-arm-eabi': 4.30.1 1479 | '@rollup/rollup-android-arm64': 4.30.1 1480 | '@rollup/rollup-darwin-arm64': 4.30.1 1481 | '@rollup/rollup-darwin-x64': 4.30.1 1482 | '@rollup/rollup-freebsd-arm64': 4.30.1 1483 | '@rollup/rollup-freebsd-x64': 4.30.1 1484 | '@rollup/rollup-linux-arm-gnueabihf': 4.30.1 1485 | '@rollup/rollup-linux-arm-musleabihf': 4.30.1 1486 | '@rollup/rollup-linux-arm64-gnu': 4.30.1 1487 | '@rollup/rollup-linux-arm64-musl': 4.30.1 1488 | '@rollup/rollup-linux-loongarch64-gnu': 4.30.1 1489 | '@rollup/rollup-linux-powerpc64le-gnu': 4.30.1 1490 | '@rollup/rollup-linux-riscv64-gnu': 4.30.1 1491 | '@rollup/rollup-linux-s390x-gnu': 4.30.1 1492 | '@rollup/rollup-linux-x64-gnu': 4.30.1 1493 | '@rollup/rollup-linux-x64-musl': 4.30.1 1494 | '@rollup/rollup-win32-arm64-msvc': 4.30.1 1495 | '@rollup/rollup-win32-ia32-msvc': 4.30.1 1496 | '@rollup/rollup-win32-x64-msvc': 4.30.1 1497 | fsevents: 2.3.3 1498 | 1499 | search-insights@2.17.3: {} 1500 | 1501 | shiki@1.26.1: 1502 | dependencies: 1503 | '@shikijs/core': 1.26.1 1504 | '@shikijs/engine-javascript': 1.26.1 1505 | '@shikijs/engine-oniguruma': 1.26.1 1506 | '@shikijs/langs': 1.26.1 1507 | '@shikijs/themes': 1.26.1 1508 | '@shikijs/types': 1.26.1 1509 | '@shikijs/vscode-textmate': 10.0.1 1510 | '@types/hast': 3.0.4 1511 | 1512 | source-map-js@1.2.1: {} 1513 | 1514 | space-separated-tokens@2.0.2: {} 1515 | 1516 | speakingurl@14.0.1: {} 1517 | 1518 | stringify-entities@4.0.4: 1519 | dependencies: 1520 | character-entities-html4: 2.1.0 1521 | character-entities-legacy: 3.0.0 1522 | 1523 | superjson@2.2.2: 1524 | dependencies: 1525 | copy-anything: 3.0.5 1526 | 1527 | tabbable@6.2.0: {} 1528 | 1529 | trim-lines@3.0.1: {} 1530 | 1531 | unist-util-is@6.0.0: 1532 | dependencies: 1533 | '@types/unist': 3.0.3 1534 | 1535 | unist-util-position@5.0.0: 1536 | dependencies: 1537 | '@types/unist': 3.0.3 1538 | 1539 | unist-util-stringify-position@4.0.0: 1540 | dependencies: 1541 | '@types/unist': 3.0.3 1542 | 1543 | unist-util-visit-parents@6.0.1: 1544 | dependencies: 1545 | '@types/unist': 3.0.3 1546 | unist-util-is: 6.0.0 1547 | 1548 | unist-util-visit@5.0.0: 1549 | dependencies: 1550 | '@types/unist': 3.0.3 1551 | unist-util-is: 6.0.0 1552 | unist-util-visit-parents: 6.0.1 1553 | 1554 | vfile-message@4.0.2: 1555 | dependencies: 1556 | '@types/unist': 3.0.3 1557 | unist-util-stringify-position: 4.0.0 1558 | 1559 | vfile@6.0.3: 1560 | dependencies: 1561 | '@types/unist': 3.0.3 1562 | vfile-message: 4.0.2 1563 | 1564 | vite@5.4.11: 1565 | dependencies: 1566 | esbuild: 0.21.5 1567 | postcss: 8.4.49 1568 | rollup: 4.30.1 1569 | optionalDependencies: 1570 | fsevents: 2.3.3 1571 | 1572 | vitepress@1.5.0(@algolia/client-search@5.19.0)(axios@1.7.9)(postcss@8.4.49)(search-insights@2.17.3): 1573 | dependencies: 1574 | '@docsearch/css': 3.8.2 1575 | '@docsearch/js': 3.8.2(@algolia/client-search@5.19.0)(search-insights@2.17.3) 1576 | '@iconify-json/simple-icons': 1.2.19 1577 | '@shikijs/core': 1.26.1 1578 | '@shikijs/transformers': 1.26.1 1579 | '@shikijs/types': 1.26.1 1580 | '@types/markdown-it': 14.1.2 1581 | '@vitejs/plugin-vue': 5.2.1(vite@5.4.11)(vue@3.5.13) 1582 | '@vue/devtools-api': 7.7.0 1583 | '@vue/shared': 3.5.13 1584 | '@vueuse/core': 11.3.0(vue@3.5.13) 1585 | '@vueuse/integrations': 11.3.0(axios@1.7.9)(focus-trap@7.6.4)(vue@3.5.13) 1586 | focus-trap: 7.6.4 1587 | mark.js: 8.11.1 1588 | minisearch: 7.1.1 1589 | shiki: 1.26.1 1590 | vite: 5.4.11 1591 | vue: 3.5.13 1592 | optionalDependencies: 1593 | postcss: 8.4.49 1594 | transitivePeerDependencies: 1595 | - '@algolia/client-search' 1596 | - '@types/node' 1597 | - '@types/react' 1598 | - '@vue/composition-api' 1599 | - async-validator 1600 | - axios 1601 | - change-case 1602 | - drauu 1603 | - fuse.js 1604 | - idb-keyval 1605 | - jwt-decode 1606 | - less 1607 | - lightningcss 1608 | - nprogress 1609 | - qrcode 1610 | - react 1611 | - react-dom 1612 | - sass 1613 | - sass-embedded 1614 | - search-insights 1615 | - sortablejs 1616 | - stylus 1617 | - sugarss 1618 | - terser 1619 | - typescript 1620 | - universal-cookie 1621 | 1622 | vue-demi@0.14.10(vue@3.5.13): 1623 | dependencies: 1624 | vue: 3.5.13 1625 | 1626 | vue@3.5.13: 1627 | dependencies: 1628 | '@vue/compiler-dom': 3.5.13 1629 | '@vue/compiler-sfc': 3.5.13 1630 | '@vue/runtime-dom': 3.5.13 1631 | '@vue/server-renderer': 3.5.13(vue@3.5.13) 1632 | '@vue/shared': 3.5.13 1633 | 1634 | zwitch@2.0.4: {} 1635 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openwdl/docs/b6bc4b502d9b10cf785a01d3cbfe8c31595694f0/public/favicon.ico -------------------------------------------------------------------------------- /public/hero.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/logo-only.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /reference/stdlib/file.md: -------------------------------------------------------------------------------- 1 | # File Functions 2 | 3 | - [`basename`](#basename) 4 | - [`join_paths`](#join-paths) 5 | - [`glob`](#glob) 6 | - [`size`](#size) 7 | - [`stdout`](#stdout) 8 | - [`stderr`](#stderr) 9 | - [`read_string`](#read-string) 10 | - [`read_int`](#read-int) 11 | - [`read_float`](#read-float) 12 | - [`read_boolean`](#read-boolean) 13 | - [`read_lines`](#read-lines) 14 | - [`write_lines`](#write-lines) 15 | - [`read_tsv`](#read-tsv) 16 | - [`write_tsv`](#write-tsv) 17 | - [`read_map`](#read-map) 18 | - [`write_map`](#write-map) 19 | - [`read_json`](#read-json) 20 | - [`write_json`](#write-json) 21 | - [`read_object`](#read-object) 22 | - [`read_objects`](#read-objects) 23 | - [`write_object`](#write-object) 24 | - [`write_objects`](#write-objects) 25 | 26 | ## `basename` 27 | 28 | Returns the "basename" of a file or directory - the name after the last directory 29 | separator in the path. 30 | 31 | The optional second parameter specifies a literal suffix to remove from the file name. 32 | If the file name does not end with the specified suffix then it is ignored. 33 | 34 | **Signatures** 35 | 36 | ```wdl 37 | String basename(File, [String]) 38 | String basename(Directory, [String]) 39 | ``` 40 | 41 | **Parameters** 42 | 43 | 1. **`File|Directory`**: Path of the file or directory to read. If the argument is a 44 | `String`, it is assumed to be a local file path relative to the current working 45 | directory of the task. 46 | 2. **`String`**: (Optional) Suffix to remove from the file name. 47 | 48 | **Returns** 49 | 50 | 1. The file's basename as a `String`. 51 | 52 | **Example** 53 | 54 | ```wdl 55 | String bn = basename("/path/to/file.txt") 56 | # `bn` contains `"file.txt"`. 57 | 58 | String bn = basename("/path/to/file.txt", ".txt") 59 | # `bn` contains `"file"`. 60 | ``` 61 | 62 | ## `join_paths` 63 | 64 | Joins together two or more paths into an absolute path in the host filesystem. 65 | 66 | There are three variants of this function: 67 | 68 | 1. `File join_paths(File, String)`: Joins together exactly two paths. The first path may 69 | be either absolute or relative and must specify a directory; the second path is 70 | relative to the first path and may specify a file or directory. 71 | 2. `File join_paths(File, Array[String]+)`: Joins together any number of relative paths 72 | with a base path. The first argument may be either an absolute or a relative path and 73 | must specify a directory. The paths in the second array argument must all be 74 | relative. The *last* element may specify a file or directory; all other elements must 75 | specify a directory. 76 | 3. `File join_paths(Array[String]+)`: Joins together any number of paths. The array must 77 | not be empty. The *first* element of the array may be either absolute or relative; 78 | subsequent path(s) must be relative. The *last* element may specify a file or 79 | directory; all other elements must specify a directory. 80 | 81 | An absolute path starts with `/` and indicates that the path is relative to the root of 82 | the environment in which the task is executed. Only the first path may be absolute. If 83 | any subsequent paths are absolute, it is an error. 84 | 85 | A relative path does not start with `/` and indicates the path is relative to its parent 86 | directory. It is up to the execution engine to determine which directory to use as the 87 | parent when resolving relative paths; by default it is the working directory in which 88 | the task is executed. 89 | 90 | **Signatures** 91 | 92 | ```wdl 93 | File join_paths(File, String) 94 | File join_paths(File, Array[String]+) 95 | File join_paths(Array[String]+) 96 | ``` 97 | 98 | **Parameters** 99 | 100 | 1. **`File|Array[String]+`**: Either a path or an array of paths. 101 | 2. **`String|Array[String]+`**: A relative path or paths; only allowed if the first 102 | argument is a `File`. 103 | 104 | **Returns** 105 | 106 | 1. A `File` representing an absolute path that results from joining all the paths in 107 | order (left-to-right), and resolving the resulting path against the default parent 108 | directory if it is relative. 109 | 110 | **Example** 111 | 112 | ```wdl 113 | File path = join_paths(["/usr", "bin", "env"]) 114 | # `path` points to `/usr/bin/env`. 115 | ``` 116 | 117 | ## `glob` 118 | 119 | Returns the Bash expansion of the [glob 120 | string](https://en.wikipedia.org/wiki/Glob_(programming)) relative to the task's 121 | execution directory, and in the same order. 122 | 123 | `glob` finds all of the files (but not the directories) in the same order as would be 124 | matched by running `echo ` in Bash from the task's execution directory. 125 | 126 | At least in standard Bash, glob expressions are not evaluated recursively, i.e., files 127 | in nested directories are not included. 128 | 129 | **Signatures** 130 | 131 | ```wdl 132 | Array[File] glob(String) 133 | ``` 134 | 135 | **Parameters** 136 | 137 | 1. **`String`**: The glob string. 138 | 139 | **Returns** 140 | 141 | 1. An array of all files matched by the glob. 142 | 143 | **Example** 144 | 145 | ```wdl 146 | Array paths = glob("*.py") 147 | # `paths` contains all files with the `.py` extension in the current directory. 148 | ``` 149 | 150 | ## `size` 151 | 152 | Determines the size of a file, directory, or the sum total sizes of the 153 | files/directories contained within a compound value. The files may be optional values; 154 | `None` values have a size of `0.0`. By default, the size is returned in bytes unless the 155 | optional second argument is specified with a [unit](#units-of-storage) 156 | 157 | In the second variant of the `size` function, the parameter type `X` represents any 158 | compound type that contains `File` or `File?` nested at any depth. 159 | 160 | If the size cannot be represented in the specified unit because the resulting value is 161 | too large to fit in a `Float`, an error is raised. It is recommended to use a unit that 162 | will always be large enough to handle any expected inputs without numerical overflow. 163 | 164 | **Signatures** 165 | 166 | ```wdl 167 | Float size(File|File?, [String]) 168 | Float size(Directory|Directory?, [String]) 169 | Float size(X|X?, [String]) 170 | ``` 171 | 172 | **Parameters** 173 | 174 | 1. **`File|File?|Directory|Directory?|X|X?`**: A file, directory, or a compound value 175 | containing files/directories, for which to determine the size. 176 | 2. **`String`**: (Optional) The unit of storage; defaults to 'B'. 177 | 178 | **Returns** 179 | 180 | 1. The size of the files/directories as a `Float`. 181 | 182 | **Example** 183 | 184 | ```wdl 185 | Float size = size("foo.txt") 186 | # `size` contains the size of `foo.txt`. 187 | ``` 188 | 189 | ## `stdout` 190 | 191 | Returns the value of the executed command's standard output (stdout) as a `File`. The 192 | engine should give the file a random name and write it in a temporary directory, so as 193 | not to conflict with any other task output files. 194 | 195 | **Signatures** 196 | 197 | ```wdl 198 | File stdout() 199 | ``` 200 | 201 | **Parameters** 202 | 203 | _None._ 204 | 205 | **Returns** 206 | 207 | 1. A `File` whose contents are the stdout generated by the command of the task where the 208 | function is called. 209 | 210 | **Example** 211 | 212 | ```wdl 213 | String message = read_string(stdout()) 214 | # `message` contains the output of the process's `stdout`. 215 | ``` 216 | 217 | ## `stderr` 218 | 219 | Returns the value of the executed command's standard error (stderr) as a `File`. The 220 | file should be given a random name and written in a temporary directory, so as not to 221 | conflict with any other task output files. 222 | 223 | 224 | **Signatures** 225 | 226 | ```wdl 227 | File stderr() 228 | ``` 229 | 230 | **Parameters** 231 | 232 | _None._ 233 | 234 | **Returns** 235 | 236 | 1. A `File` whose contents are the stderr generated by the command of the task where the 237 | function is called. 238 | 239 | **Example** 240 | 241 | ```wdl 242 | String message = read_string(stderr()) 243 | # `message` contains the output of the process's `stderr`. 244 | ``` 245 | 246 | ## `read_string` 247 | 248 | Reads an entire file as a `String`, with any trailing end-of-line characters (`\r` and 249 | `\n`) stripped off. If the file is empty, an empty string is returned. 250 | 251 | If the file contains any internal newline characters, they are left in tact. 252 | 253 | **Signatures** 254 | 255 | ```wdl 256 | String read_string(File) 257 | ``` 258 | 259 | **Parameters** 260 | 261 | 1. **`File`**: Path of the file to read. 262 | 263 | **Returns** 264 | 265 | 1. A `String`. 266 | 267 | **Example** 268 | 269 | ```wdl 270 | String message = read_string(stdout()) 271 | # `message` contains the output of the process's `stdout`. 272 | ``` 273 | 274 | ## `read_int` 275 | 276 | Reads a file that contains a single line containing only an integer and (optional) 277 | whitespace. If the line contains a valid integer, that value is returned as an `Int`. If 278 | the file is empty or does not contain a single integer, an error is raised. 279 | 280 | **Signatures** 281 | 282 | ```wdl 283 | Int read_int(File) 284 | ``` 285 | 286 | **Parameters** 287 | 288 | 1. **`File`**: Path of the file to read. 289 | 290 | **Returns** 291 | 292 | 1. An `Int`. 293 | 294 | **Example** 295 | 296 | ```wdl 297 | Int number = read_int(stdout()) 298 | # If `stdout` contains an int, returns the int. Else, an error is raised. 299 | ``` 300 | 301 | ## `read_float` 302 | 303 | Reads a file that contains only a numeric value and (optional) whitespace. If the line 304 | contains a valid floating point number, that value is returned as a `Float`. If the file 305 | is empty or does not contain a single float, an error is raised. 306 | 307 | **Signatures** 308 | 309 | ```wdl 310 | Float read_float(File) 311 | ``` 312 | 313 | **Parameters** 314 | 315 | 1. **`File`**: Path of the file to read. 316 | 317 | **Returns** 318 | 319 | 1. A `Float`. 320 | 321 | **Example** 322 | 323 | ```wdl 324 | Float number = read_float(stdout()) 325 | # If `stdout` contains a float, returns the float. Else, an error is raised. 326 | ``` 327 | 328 | ## `read_boolean` 329 | 330 | Reads a file that contains a single line containing only a boolean value and (optional) 331 | whitespace. If the non-whitespace content of the line is "true" or "false", that value 332 | is returned as a `Boolean`. If the file is empty or does not contain a single boolean, 333 | an error is raised. The comparison is case- and whitespace-insensitive. 334 | 335 | **Signatures** 336 | 337 | ```wdl 338 | Boolean read_boolean(File) 339 | ``` 340 | 341 | **Parameters** 342 | 343 | 1. **`File`**: Path of the file to read. 344 | 345 | **Returns** 346 | 347 | 1. A `Boolean`. 348 | 349 | **Example** 350 | 351 | ```wdl 352 | Boolean value = read_float(stdout()) 353 | # If `stdout` contains a boolean, returns the boolean. Else, an error is raised. 354 | ``` 355 | 356 | ## `read_lines` 357 | 358 | Reads each line of a file as a `String`, and returns all lines in the file as an 359 | `Array[String]`. Trailing end-of-line characters (`\r` and `\n`) are removed from each 360 | line. 361 | 362 | The order of the lines in the returned `Array[String]` is the order in which the lines 363 | appear in the file. 364 | 365 | If the file is empty, an empty array is returned. 366 | 367 | **Signatures** 368 | 369 | ```wdl 370 | Array[String] read_lines(File) 371 | ``` 372 | 373 | **Parameters** 374 | 375 | 1. **`File`**: Path of the file to read. 376 | 377 | **Returns** 378 | 379 | 1. An `Array[String]` representation of the lines in the file. 380 | 381 | **Example** 382 | 383 | ```wdl 384 | Array[String] lines = read_lines("foo.txt") 385 | # `lines` contains the newline-delimited lines read from `foo.txt`. 386 | ``` 387 | 388 | ## `write_lines` 389 | 390 | Writes a file with one line for each element in a `Array[String]`. All lines are 391 | terminated by the newline (`\n`) character (following the [POSIX 392 | standard](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206)). 393 | If the `Array` is empty, an empty file is written. 394 | 395 | **Signatures** 396 | 397 | ```wdl 398 | File write_lines(Array[String]) 399 | ``` 400 | 401 | **Parameters** 402 | 403 | 1. **`Array[String]`**: Array of strings to write. 404 | 405 | **Returns** 406 | 407 | 1. A `File`. 408 | 409 | **Example** 410 | 411 | ```wdl 412 | Array[String] lines = ["first", "second", "third"] 413 | 414 | File result = write_lines(lines) 415 | # `result` now points to a file with the contents `"first\nsecond\nthird"`. 416 | ``` 417 | 418 | ## `read_tsv` 419 | 420 | Reads a tab-separated value (TSV) file as an `Array[Array[String]]` representing a table 421 | of values. Trailing end-of-line characters (`\r` and `\n`) are removed from each line. 422 | 423 | This function has three variants: 424 | 425 | 1. `Array[Array[String]] read_tsv(File, [false])`: Returns each row of the table as an 426 | `Array[String]`. There is no requirement that the rows of the table are all the same 427 | length. 428 | 2. `Array[Object] read_tsv(File, true)`: The second parameter must be `true` and 429 | specifies that the TSV file contains a header line. Each row is returned as an 430 | `Object` with its keys determined by the header (the first line in the file) and its 431 | values as `String`s. All rows in the file must be the same length and the field names 432 | in the header row must be valid `Object` field names, or an error is raised. 433 | 3. `Array[Object] read_tsv(File, Boolean, Array[String])`: The second parameter 434 | specifies whether the TSV file contains a header line, and the third parameter is an 435 | array of field names that is used to specify the field names to use for the returned 436 | `Object`s. If the second parameter is `true`, the specified field names override 437 | those in the file's header (i.e., the header line is ignored). 438 | 439 | If the file is empty, an empty array is returned. 440 | 441 | If the entire contents of the file can not be read for any reason, the calling task or 442 | workflow fails with an error. Examples of failure include, but are not limited to, not 443 | having access to the file, resource limitations (e.g. memory) when reading the file, and 444 | implementation-imposed file size limits. 445 | 446 | **Signatures** 447 | 448 | ```wdl 449 | Array[Array[String]] read_tsv(File) 450 | Array[Object] read_tsv(File, true) 451 | Array[Object] read_tsv(File, Boolean, Array[String]) 452 | ``` 453 | 454 | **Parameters** 455 | 456 | 1. **`File`**: The TSV file to read. 457 | 2. **`Boolean`**: (Optional) Whether to treat the file's first line as a header. 458 | 3. **`Array[String]`**: (Optional) An array of field names. If specified, then the 459 | second parameter is also required. 460 | 461 | **Returns** 462 | 463 | 1. An `Array` of rows in the TSV file, where each row is an `Array[String]` of fields or 464 | an `Object` with keys determined by the second and third parameters and `String` 465 | values. 466 | 467 | **Example** 468 | 469 | ```wdl 470 | Array[Object] objects = read_tsv("data.tsv", true) 471 | # `objects` holds an array of objects read in from `data.tsv`. 472 | ``` 473 | 474 | ## `write_tsv` 475 | 476 | Given an `Array` of elements, writes a tab-separated value (TSV) file with one line for 477 | each element. 478 | 479 | There are three variants of this function: 480 | 481 | 1. `File write_tsv(Array[Array[String]])`: Each element is concatenated using a tab 482 | ('\t') delimiter and written as a row in the file. There is no header row. 483 | 484 | 2. `File write_tsv(Array[Array[String]], true, Array[String])`: The second argument must 485 | be `true` and the third argument provides an `Array` of column names. The column 486 | names are concatenated to create a header that is written as the first row of the 487 | file. All elements must be the same length as the header array. 488 | 489 | 3. `File write_tsv(Array[Struct], [Boolean, [Array[String]]])`: Each element is a struct 490 | whose field values are concatenated in the order the fields are defined. The optional 491 | second argument specifies whether to write a header row. If it is `true`, then the 492 | header is created from the struct field names. If the second argument is `true`, then 493 | the optional third argument may be used to specify column names to use instead of the 494 | struct field names. 495 | 496 | Each line is terminated by the newline (`\n`) character. 497 | 498 | The generated file should be given a random name and written in a temporary directory, 499 | so as not to conflict with any other task output files. 500 | 501 | If the entire contents of the file can not be written for any reason, the calling task 502 | or workflow fails with an error. Examples of failure include, but are not limited to, 503 | insufficient disk space to write the file. 504 | 505 | **Signatures** 506 | 507 | ```wdl 508 | File write_tsv(Array[Array[String]]|Array[Struct]) 509 | File write_tsv(Array[Array[String]], true, Array[String]) 510 | File write_tsv(Array[Struct], Boolean, Array[String]) 511 | ``` 512 | 513 | **Parameters** 514 | 515 | 1. **`Array[Array[String]] | Array[Struct]`**: An array of rows, where each row is either an 516 | `Array` of column values or a struct whose values are the column values. 517 | 2. **`Boolean`**: (Optional) Whether to write a header row. 518 | 3. **`Array[String]`**: An array of column names. If the first argument is 519 | `Array[Array[String]]` and the second argument is `true` then it is required, 520 | otherwise it is optional. Ignored if the second argument is `false`. 521 | 522 | **Returns** 523 | 524 | 1. A `File`. 525 | 526 | **Example** 527 | 528 | ```wdl 529 | Array[Array[String]] array = [["one", "two", "three"], ["un", "deux", "trois"]] 530 | File result = write_tsv(array) 531 | # `result` points to a file with the content of `array` written as a TSV. 532 | ``` 533 | 534 | ## `read_map` 535 | 536 | Reads a tab-separated value (TSV) file representing a set of pairs. Each row must have 537 | exactly two columns, e.g., `col1\tcol2`. Trailing end-of-line characters (`\r` and `\n`) 538 | are removed from each line. 539 | 540 | Each pair is added to a `Map[String, String]` in order. The values in the first column 541 | must be unique; if there are any duplicate keys, an error is raised. 542 | 543 | If the file is empty, an empty map is returned. 544 | 545 | **Signatures** 546 | 547 | ```wdl 548 | Map[String, String] read_map(File) 549 | ``` 550 | 551 | **Parameters** 552 | 553 | 1. **`File`**: Path of the two-column TSV file to read. 554 | 555 | **Returns** 556 | 557 | 1. A `Map[String, String]`, with one element for each row in the TSV file. 558 | 559 | **Example** 560 | 561 | ```wdl 562 | Map[String, String] result = read_map(stdout()) 563 | # `result` contains a map of the values within the two column tab-delimited text 564 | # returned in `stdout`. 565 | ``` 566 | 567 | ## `write_map` 568 | 569 | Writes a tab-separated value (TSV) file with one line for each element in a `Map[String, 570 | String]`. Each element is concatenated into a single tab-delimited string of the format 571 | `~{key}\t~{value}`. Each line is terminated by the newline (`\n`) character. If the 572 | `Map` is empty, an empty file is written. 573 | 574 | Since `Map`s are ordered, the order of the lines in the file is guaranteed to be the 575 | same order that the elements were added to the `Map`. 576 | 577 | **Signatures** 578 | 579 | ```wdl 580 | File write_map(Map[String, String]) 581 | ``` 582 | 583 | **Parameters** 584 | 585 | 1. **`Map[String, String]`**: A `Map`, where each element will be a row in the generated 586 | file. 587 | 588 | **Returns** 589 | 590 | 1. A `File`. 591 | 592 | **Example** 593 | 594 | ```wdl 595 | Map[String, String] map = {"key1": "value1", "key2": "value2"} 596 | File result = write_map(map) 597 | # `result` points to a file with the contents `"key1\tvalue1\nkey2\tvalue2"`. 598 | ``` 599 | 600 | ## `read_json` 601 | 602 | Reads a JSON file into a WDL value whose type depends on the file's contents. The 603 | mapping of JSON type to WDL type is: 604 | 605 | | JSON Type | WDL Type | 606 | | --------- | ---------------- | 607 | | object | `Object` | 608 | | array | `Array[X]` | 609 | | number | `Int` or `Float` | 610 | | string | `String` | 611 | | boolean | `Boolean` | 612 | | null | `None` | 613 | 614 | The return value is of type [`Union`](#union-hidden-type) and must be used in a context 615 | where it can be coerced to the expected type, or an error is raised. For example, if the 616 | JSON file contains `null`, then the return value will be `None`, meaning the value can 617 | only be used in a context where an optional type is expected. 618 | 619 | If the JSON file contains an array, then all the elements of the array must be coercible 620 | to the same type, or an error is raised. 621 | 622 | The `read_json` function does not have access to any WDL type information, so it cannot 623 | return an instance of a specific `Struct` type. Instead, it returns a generic `Object` 624 | value that must be coerced to the desired `Struct` type. 625 | 626 | Note that an empty file is not valid according to the JSON specification, and so calling 627 | `read_json` on an empty file raises an error. 628 | 629 | **Signatures** 630 | 631 | ```wdl 632 | Union read_json(File) 633 | ``` 634 | 635 | **Parameters** 636 | 637 | 1. **`File`**: Path of the JSON file to read. 638 | 639 | **Returns** 640 | 641 | 1. A value whose type is dependent on the contents of the JSON file. 642 | 643 | **Example** 644 | 645 | ```wdl 646 | struct Person { 647 | String name 648 | Int age 649 | } 650 | 651 | Person person = read_json(json_file) 652 | # `person` contains a person deserialized from a file. 653 | ``` 654 | 655 | ## `write_json` 656 | 657 | Writes a JSON file with the serialized form of a WDL value. The following WDL types can 658 | be serialized: 659 | 660 | | WDL Type | JSON Type | 661 | | ---------------- | --------- | 662 | | `Struct` | object | 663 | | `Object` | object | 664 | | `Map[String, X]` | object | 665 | | `Array[X]` | array | 666 | | `Int` | number | 667 | | `Float` | number | 668 | | `String` | string | 669 | | `File` | string | 670 | | `Boolean` | boolean | 671 | | `None` | null | 672 | 673 | When serializing compound types, all nested types must be serializable or an error is 674 | raised. 675 | 676 | **Signatures** 677 | 678 | ```wdl 679 | File write_json(X) 680 | ``` 681 | 682 | **Parameters** 683 | 684 | 1. **`X`**: A WDL value of a supported type. 685 | 686 | **Returns** 687 | 688 | 1. A `File`. 689 | 690 | **Example** 691 | 692 | ```wdl 693 | struct Person { 694 | String name 695 | Int age 696 | } 697 | 698 | Array[Person] people = [ 699 | Person { 700 | name: "Jane Doe", 701 | age: 29, 702 | }, 703 | Person { 704 | name: "John Doe", 705 | age: 28, 706 | } 707 | ] 708 | 709 | File result = write_tsv(people) 710 | # `people` points to a file with the contents `"Jane Doe\t29\nJohn Doe\t28"`. 711 | ``` 712 | 713 | ## `read_object` 714 | 715 | Reads a tab-separated value (TSV) file representing the names and values of the members 716 | of an `Object`. There must be exactly two rows, and each row must have the same number 717 | of elements, otherwise an error is raised. Trailing end-of-line characters (`\r` and 718 | `\n`) are removed from each line. 719 | 720 | The first row specifies the object member names. The names in the first row must be 721 | unique; if there are any duplicate names, an error is raised. 722 | 723 | The second row specifies the object member values corresponding to the names in the 724 | first row. All of the `Object`'s values are of type `String`. 725 | 726 | **Signatures** 727 | 728 | ```wdl 729 | Object read_object(File) 730 | ``` 731 | 732 | **Parameters** 733 | 734 | 1. **`File`**: Path of the two-row TSV file to read. 735 | 736 | **Returns** 737 | 738 | 1. An `Object`, with as many members as there are unique names in the TSV. 739 | 740 | **Example** 741 | 742 | ```wdl 743 | Object object = read_object(stdout()) 744 | # `object` contains an `Object` with the key value pairs from `stdout`. 745 | ``` 746 | 747 | ## `read_objects` 748 | 749 | Reads a tab-separated value (TSV) file representing the names and values of the members 750 | of any number of `Object`s. Trailing end-of-line characters (`\r` and `\n`) are removed 751 | from each line. 752 | 753 | The first line of the file must be a header row with the names of the object members. 754 | The names in the first row must be unique; if there are any duplicate names, an error is 755 | raised. 756 | 757 | There are any number of additional rows, where each additional row contains the values 758 | of an object corresponding to the member names. Each row in the file must have the same 759 | number of fields as the header row. All of the `Object`'s values are of type `String`. 760 | 761 | If the file is empty or contains only a header line, an empty array is returned. 762 | 763 | **Signatures** 764 | 765 | ```wdl 766 | Array[Object] read_objects(File) 767 | ``` 768 | 769 | **Parameters** 770 | 771 | 1. **`File`**: Path of the TSV file to read. 772 | 773 | **Returns** 774 | 775 | 1. An `Array[Object]`, with `N-1` elements, where `N` is the number of rows in the file. 776 | 777 | **Example** 778 | 779 | ```wdl 780 | Array[Object] objects = read_objects(stdout()) 781 | # `objects` contains an array of `Object`s with the key value pairs provided on each 782 | # line from `stdout`. 783 | ``` 784 | 785 | ## `write_object` 786 | 787 | Writes a tab-separated value (TSV) file with the contents of a `Object` or `Struct`. The 788 | file contains two tab-delimited lines. The first line is the names of the members, and 789 | the second line is the corresponding values. Each line is terminated by the newline 790 | (`\n`) character. The ordering of the columns is unspecified. 791 | 792 | The member values must be serializable to strings, meaning that only primitive types are 793 | supported. Attempting to write a `Struct` or `Object` that has a compound member value 794 | results in an error. 795 | 796 | **Signatures** 797 | 798 | ```wdl 799 | File write_object(Struct|Object) 800 | ``` 801 | 802 | **Parameters** 803 | 804 | 1. **`Struct|Object`**: An object to write. 805 | 806 | **Returns** 807 | 808 | 1. A `File`. 809 | 810 | **Example** 811 | 812 | ```wdl 813 | struct Person { 814 | String name 815 | Int age 816 | } 817 | 818 | Person person = Person { 819 | name: "Jane Doe", 820 | age: 29, 821 | } 822 | 823 | File result = write_object(person) 824 | # `result` points to a file that contains the contents `"name\tage\nJane Doe\t29"`. 825 | ``` 826 | 827 | ## `write_objects` 828 | 829 | Writes a tab-separated value (TSV) file with the contents of a `Array[Struct]` or 830 | `Array[Object]`. All elements of the `Array` must have the same member names, or an 831 | error is raised. 832 | 833 | The file contains `N+1` tab-delimited lines, where `N` is the number of elements in the 834 | `Array`. The first line is the names of the `Struct`/`Object` members, and the 835 | subsequent lines are the corresponding values for each element. Each line is terminated 836 | by a newline (`\n`) character. The lines are written in the same order as the elements 837 | in the `Array`. The ordering of the columns is the same as the order in which the 838 | `Struct`'s members are defined; the column ordering for `Object`s is unspecified. If the 839 | `Array` is empty, an empty file is written. 840 | 841 | The member values must be serializable to strings, meaning that only primitive types are 842 | supported. Attempting to write a `Struct` or `Object` that has a compound member value 843 | results in an error. 844 | 845 | **Signatures** 846 | 847 | ```wdl 848 | File write_objects(Array[Struct|Object]) 849 | ``` 850 | 851 | **Parameters** 852 | 853 | 1. **`Array[Struct|Object]`**: An array of objects to write. 854 | 855 | **Returns** 856 | 857 | 1. A `File`. 858 | 859 | **Example** 860 | 861 | ```wdl 862 | struct Person { 863 | String name 864 | Int age 865 | } 866 | 867 | Array[Person] people = [ 868 | Person { 869 | name: "Jane Doe", 870 | age: 29, 871 | }, 872 | Person { 873 | name: "John Doe", 874 | age: 28, 875 | } 876 | ] 877 | 878 | File result = write_objects(people) 879 | # `result` points to a file that contains the contents 880 | # `"name\tage\nJane Doe\t29\nJohn Doe\t28"`. 881 | ``` 882 | -------------------------------------------------------------------------------- /reference/stdlib/numeric.md: -------------------------------------------------------------------------------- 1 | # Numeric Functions 2 | 3 | - [`floor`](#floor) 4 | - [`ceil`](#ceil) 5 | - [`round`](#round) 6 | - [`min`](#min) 7 | - [`max`](#max) 8 | 9 | ## `floor` 10 | 11 | Rounds a floating point number **down** to the next lowest integer. 12 | 13 | **Signatures** 14 | 15 | ```wdl 16 | Int floor(Float) 17 | ``` 18 | 19 | **Parameters** 20 | 21 | 1. **`Float`**: the number to round. 22 | 23 | **Returns** 24 | 25 | 1. An integer. 26 | 27 | **Example** 28 | 29 | ```wdl 30 | Int three = floor(3.14) 31 | # `three` now contains `3`. 32 | ``` 33 | 34 | ## `ceil` 35 | 36 | Rounds a floating point number **up** to the next highest integer. 37 | 38 | **Signatures** 39 | 40 | ```wdl 41 | Int ceil(Float) 42 | ``` 43 | 44 | **Parameters** 45 | 46 | 1. **`Float`**: the number to round. 47 | 48 | **Returns** 49 | 50 | 1. An integer. 51 | 52 | **Example** 53 | 54 | ```wdl 55 | Int four = ceil(3.14) 56 | # `four` now contains `4`. 57 | ``` 58 | 59 | ## `round` 60 | 61 | Rounds a floating point number to the nearest integer based on standard rounding rules 62 | ("round half up"). 63 | 64 | **Signatures** 65 | 66 | ```wdl 67 | Int round(Float) 68 | ``` 69 | 70 | **Parameters** 71 | 72 | 1. **`Float`**: the number to round. 73 | 74 | **Returns** 75 | 76 | 1. An integer. 77 | 78 | **Example** 79 | 80 | ```wdl 81 | Int three = round(3.14) 82 | # `three` now contains `3`. 83 | ``` 84 | 85 | ## `min` 86 | 87 | Returns the smaller of two values. If both values are `Int`s, the return value is an 88 | `Int`, otherwise it is a `Float`. 89 | 90 | **Signatures** 91 | 92 | ```wdl 93 | Int min(Int, Int) 94 | Float min(Int, Float) 95 | Float min(Float, Int) 96 | Float min(Float, Float) 97 | ``` 98 | 99 | **Parameters** 100 | 101 | 1. **`Int|Float`**: the first number to compare. 102 | 2. **`Int|Float`**: the second number to compare. 103 | 104 | **Returns** 105 | 106 | 1. The smaller of the two arguments. 107 | 108 | **Example** 109 | 110 | ```wdl 111 | Int value1 112 | Float value2 113 | 114 | Float result = min(value1, value2) 115 | # This is equivalent to `if value1 < value2 then value1 else value2`. 116 | ``` 117 | 118 | ## `max` 119 | 120 | Returns the larger of two values. If both values are `Int`s, the return value is an 121 | `Int`, otherwise it is a `Float`. 122 | 123 | **Signatures** 124 | 125 | ```wdl 126 | Int max(Int, Int) 127 | Float max(Int, Float) 128 | Float max(Float, Int) 129 | Float max(Float, Float) 130 | ``` 131 | 132 | **Parameters** 133 | 134 | 1. **`Int|Float`**: the first number to compare. 135 | 2. **`Int|Float`**: the second number to compare. 136 | 137 | **Returns** 138 | 139 | 1. The larger of the two arguments. 140 | 141 | **Example** 142 | 143 | ```wdl 144 | Int value1 145 | Float value2 146 | 147 | Float result = max(value1, value2) 148 | # This is equivalent to `if value1 > value2 then value1 else value2`. 149 | ``` 150 | -------------------------------------------------------------------------------- /reference/stdlib/string-array.md: -------------------------------------------------------------------------------- 1 | # String Array Functions 2 | 3 | - [`prefix`](#prefix) 4 | - [`suffix`](#suffix) 5 | - [`quote`](#quote) 6 | - [`squote`](#squote) 7 | - [`sep`](#sep) 8 | 9 | ## `prefix` 10 | 11 | Adds a prefix to each element of the input array of primitive values. Equivalent to 12 | evaluating `"~{prefix}~{array[i]}"` for each `i` in `range(length(array))`. 13 | 14 | **Signatures** 15 | 16 | ```wdl 17 | Array[String] prefix(String, Array[P]) 18 | ``` 19 | 20 | **Parameters** 21 | 22 | 1. **`String`**: The prefix to prepend to each element in the array. 23 | 2. **`Array[P]`**: Array with a primitive element type. 24 | 25 | **Returns** 26 | 27 | 1. An `Array[String]` with the prefixed elements of the input array. 28 | 29 | **Example** 30 | 31 | ```wdl 32 | Array[String] names = ["John", "Jane", "world"] 33 | String greetings = prefix("Hello, ", names) 34 | # `greetings` now contains `["Hello, John", "Hello, Jane", "Hello, world"]`. 35 | ``` 36 | 37 | ## `suffix` 38 | 39 | Adds a suffix to each element of the input array of primitive values. Equivalent to 40 | evaluating `"~{array[i]}~{suffix}"` for each `i` in `range(length(array))`. 41 | 42 | **Signatures** 43 | 44 | ```wdl 45 | Array[String] suffix(String, Array[P]) 46 | ``` 47 | 48 | **Parameters** 49 | 50 | 1. **`String`**: The suffix to append to each element in the array. 51 | 2. **`Array[P]`**: Array with a primitive element type. 52 | 53 | **Returns** 54 | 55 | 1. An `Array[String]` the suffixed elements of the input array. 56 | 57 | **Example** 58 | 59 | ```wdl 60 | Array[String] names = ["John", "Jane"] 61 | String responses = suffix(" says 'hi!'", names) 62 | # `responses` now contains `["John says 'hi!'", "Jane says 'hi!'"]`. 63 | ``` 64 | 65 | ## `quote` 66 | 67 | Adds double-quotes (`"`) around each element of the input array of primitive values. 68 | Equivalent to evaluating `'"~{array[i]}"'` for each `i` in `range(length(array))`. 69 | 70 | **Signatures** 71 | 72 | ```wdl 73 | Array[String] quote(Array[P]) 74 | ``` 75 | 76 | **Parameters** 77 | 78 | 1. **`Array[P]`**: Array with a primitive element type. 79 | 80 | **Returns** 81 | 82 | 1. An `Array[String]` the double-quoted elements of the input array. 83 | 84 | **Example** 85 | 86 | ```wdl 87 | Array[String] numbers = [1, 2, 3] 88 | String quoted = quote(numbers) 89 | # `quoted` now contains `["\"1\"", "\"2\"", "\"3\""]`. 90 | ``` 91 | 92 | ## `squote` 93 | 94 | Adds single-quotes (`'`) around each element of the input array of primitive values. 95 | Equivalent to evaluating `"'~{array[i]}'"` for each `i` in `range(length(array))`. 96 | 97 | **Signatures** 98 | 99 | ```wdl 100 | Array[String] squote(Array[P]) 101 | ``` 102 | 103 | **Parameters** 104 | 105 | 1. **`Array[P]`**: Array with a primitive element type. 106 | 107 | **Returns** 108 | 109 | 1. An `Array[String]` the single-quoted elements of the input array. 110 | 111 | **Example** 112 | 113 | ```wdl 114 | Array[String] numbers = [1, 2, 3] 115 | String quoted = squote(numbers) 116 | # `quoted` now contains `["'1'", "'2'", "'3'"]`. 117 | ``` 118 | 119 | ## `sep` 120 | 121 | Concatenates the elements of an array together into a string with the given separator 122 | between consecutive elements. There are always `N-1` separators in the output string, 123 | where `N` is the length of the input array. A separator is never added after the last 124 | element. Returns an empty string if the array is empty. 125 | 126 | **Signatures** 127 | 128 | ```wdl 129 | String sep(String, Array[P]) 130 | ``` 131 | 132 | **Parameters** 133 | 134 | 1. `String`: Separator string. 135 | 2. `Array[P]`: Array of strings to concatenate. 136 | 137 | **Returns** 138 | 139 | 1. A `String` with the concatenated elements of the array delimited by the separator 140 | string. 141 | 142 | **Example** 143 | 144 | ```wdl 145 | Array[String] letters = ["a", "b", "c", "d"] 146 | String letters_with_commas = sep(", ", letters) 147 | # `letters_with_commas` now contains `"a, b, c, d"`. 148 | ``` 149 | -------------------------------------------------------------------------------- /reference/stdlib/string.md: -------------------------------------------------------------------------------- 1 | # String Functions 2 | 3 | - [`find`](#find) 4 | - [`matches`](#matches) 5 | - [`sub`](#sub) 6 | 7 | ## `find` 8 | 9 | Given two `String` parameters `input` and `pattern`, searches for the occurrence of 10 | `pattern` within `input` and returns the first match or `None` if there are no matches. 11 | `pattern` is a [regular expression](https://en.wikipedia.org/wiki/Regular_expression) 12 | and is evaluated as a [POSIX Extended Regular Expression 13 | (ERE)](https://en.wikipedia.org/wiki/Regular_expression#POSIX_basic_and_extended). 14 | 15 | 16 | Note that regular expressions are written using regular WDL strings, so backslash 17 | characters need to be double-escaped. For example: 18 | 19 | ```wdl 20 | String? first_match = find("hello\tBob", "\\t") 21 | ``` 22 | 23 | **Signatures** 24 | 25 | ```wdl 26 | String? find(String, String) 27 | ``` 28 | 29 | **Parameters** 30 | 31 | 1. **`String`**: the input string to search. 32 | 2. **`String`**: the pattern to search for. 33 | 34 | **Returns** 35 | 36 | 1. The contents of the first match, or `None` if `pattern` does not match `input`. 37 | 38 | **Example** 39 | 40 | ```wdl 41 | String? match = find("Hello, world!", "e..o"); 42 | # `match` now contains `ello`. 43 | ``` 44 | 45 | ## `matches` 46 | 47 | Given two `String` parameters `input` and `pattern`, tests whether `pattern` matches 48 | `input` at least once. `pattern` is a [regular 49 | expression](https://en.wikipedia.org/wiki/Regular_expression) and is evaluated as a 50 | [POSIX Extended Regular Expression 51 | (ERE)](https://en.wikipedia.org/wiki/Regular_expression#POSIX_basic_and_extended). 52 | 53 | To test whether `pattern` matches the entire `input`, make sure to begin and end the 54 | pattern with anchors. For example: 55 | 56 | ```wdl 57 | Boolean full_match = matches("abc123", "^a.+3$") 58 | ``` 59 | 60 | Note that regular expressions are written using regular WDL strings, so backslash 61 | characters need to be double-escaped. For example: 62 | 63 | ```wdl 64 | Boolean has_tab = matches("hello\tBob", "\\t") 65 | ``` 66 | 67 | **Signatures** 68 | 69 | ```wdl 70 | Boolean matches(String, String) 71 | ``` 72 | 73 | **Parameters** 74 | 75 | 1. **`String`**: the input string to search. 76 | 2. **`String`**: the pattern to search for. 77 | 78 | **Returns** 79 | 80 | 1. `true` if `pattern` matches `input` at least once, otherwise `false`. 81 | 82 | **Example** 83 | 84 | ```wdl 85 | Boolean matches = matches("sample1234_R1.fastq", "_R1"); 86 | # `matches` now contains `true`. 87 | ``` 88 | 89 | ## `sub` 90 | 91 | Given three String parameters `input`, `pattern`, `replace`, this function replaces all 92 | non-overlapping occurrences of `pattern` in `input` by `replace`. `pattern` is a 93 | [regular expression](https://en.wikipedia.org/wiki/Regular_expression) and is evaluated 94 | as a [POSIX Extended Regular Expression 95 | (ERE)](https://en.wikipedia.org/wiki/Regular_expression#POSIX_basic_and_extended). 96 | Regular expressions are written using regular WDL strings, so backslash characters need 97 | to be double-escaped (e.g., `"\\t"`). 98 | 99 | 100 | **Signatures** 101 | 102 | ```wdl 103 | String sub(String, String, String) 104 | ``` 105 | 106 | **Parameters** 107 | 108 | 1. **`String`**: the input string. 109 | 2. **`String`**: the pattern to search for. 110 | 3. **`String`**: the replacement string. 111 | 112 | **Returns** 113 | 114 | 1. the input string, with all occurrences of the pattern replaced by the replacement 115 | string. 116 | 117 | **Example** 118 | 119 | ```wdl 120 | String chocolike = "I like chocolate when\nit's late" 121 | String chocolove = sub(chocolike, "like", "love") # 122 | 123 | # `chocolove` now contains `"I love chocolate when\nit's late"`. 124 | ``` 125 | -------------------------------------------------------------------------------- /reference/upgrade-guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: [1, 2] 3 | --- 4 | 5 | # Overview 6 | 7 | The Workflow Description Language has a number of **versions** that are 8 | constantly improving. This guide lists all major versions of the language—the 9 | major improvements for each version, common pitfalls when upgrading, and how to 10 | get help. 11 | 12 | If you're interested in learning more about how versioning works and how you can 13 | specify the version of your WDL documents, see the [Versioning section] within 14 | the Language Guide. 15 | 16 | ::: tip 17 | Changes are grouped in terms of their **impact**. The word "impact" here is a 18 | combination of "how important is the change" along with "how many existing WDL 19 | documents are likely to be affected by this change". They are subjective 20 | determinations made by the upgrade guide curator during the curator process, but 21 | they are often helpful in quickly scanning upgrade elements to see which might 22 | apply to your situation. 23 | ::: 24 | 25 | # WDL v1.2 26 | 27 | WDL v1.2 introduces a great deal of new syntax and changes to the specification. 28 | Notably, changes were backwards compatible with all previous `v1.x` releases. 29 | This sections only covers the high points related to upgrading—the full release 30 | notes can be found [here][wdl-v1.2-release-notes]. 31 | 32 | ### Checklist 33 | 34 | Use this checklist to ensure you hit all of the sections. 35 | 36 | #### Moderate impact changes 37 | 38 | New `Directory` type ([link](#new-directory-type)).
39 | Replacement of `runtime` section with `requirements` and `hints` sections ([link](#replacement-of-runtime-with-requirements-and-hints)).
40 | Deprecation of `runtime` section ([link](#deprecation-of-runtime-section)).
41 | New standard library functions 42 | ([link](#new-standard-library-functions)).
43 | Multi-line strings ([link](#multi-line-strings)).
44 | Optional `input:` statement ([link](#optional-input-statement)).
45 | 46 | #### Low impact changes 47 | 48 | Addition of workflow `hints` ([link](#addition-of-workflow-hints)).
49 | New requirements and hints keys ([link](#new-requirements-and-hints-keys)).
50 | Metadata sections for structs ([link](#metadata-sections-for-structs)).
51 | Exponentiation operator ([link](#exponentiation-operator)).
52 | 53 | ## Moderate impact changes 54 | 55 | ### New `Directory` type 56 | 57 | The `Directory` type was introduced in 58 | [#641](https://github.com/openwdl/wdl/pull/641) to better semantically indicate 59 | the use of a directory. If the intention of any of your arguments is to be used 60 | to refer to a directory on the filesystem, you are encouraged to update the 61 | parameters to a `Directory` type. 62 | 63 | ### Deprecation of `runtime` section 64 | 65 | The `runtime` section, which previously held both requirement constraints and 66 | hints to the execution engine, has now been split into the `requirements` 67 | ([#540](https://github.com/openwdl/wdl/issues/540)) section and `hints` 68 | ([#541](https://github.com/openwdl/wdl/issues/541)) section respectively. You 69 | should split out these keys based on the definitions in the 70 | specification[1](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-requirements-section), 71 | [2](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-hints-section). 72 | 73 | 🗑️ This change deprecates the `runtime` section, which will be removed in WDL v2.0. 74 | That being said, if desired, you can continue to use the `runtime` section in your WDL 75 | documents—it's just not recommended. 76 | 77 | ### New standard library functions 78 | 79 | The following are new standard library functions and their definitions. You are 80 | encouraged to read through them and replace any custom functionality that would 81 | now be duplicated in favor of these functions. 82 | 83 | - `contains_key`: whether or not a `Map` or `Object` contain a specific member 84 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-contains_key)). 85 | - `values`: get the values from a `Map` 86 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-values)). 87 | - `find`: search for a regular expression in a string 88 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-find)). 89 | - `matches`: whether a string match a regular expression 90 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-matches)). 91 | - `chunk`: split an array into sub-arrays 92 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-chunk)). 93 | - `join_paths`: join two or more paths 94 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-join_paths)). 95 | - `contains`: whether an array contains a specified value 96 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-contains)). 97 | 98 | 99 | ### Multi-line strings 100 | 101 | Multi-line strings were introduced with the following syntax. 102 | 103 | ```wdl 104 | String foo = <<< 105 | my 106 | multi-line 107 | string 108 | >>> 109 | ``` 110 | 111 | ### Optional `input:` statement 112 | 113 | As noted in [#524](https://github.com/openwdl/wdl/pull/524), the `input:` 114 | statement that precedes call bodies is unnecessary historical boilerplate. This 115 | statement is now optional in `call` bodies. You are encouraged to remove these 116 | from your `call` bodies. 117 | 118 | ## Low impact changes 119 | 120 | ### Addition of workflow `hints` 121 | 122 | Workflows gained a `hints` section in 123 | [#543](https://github.com/openwdl/wdl/issues/543). You are encouraged to go read 124 | the supported workflow 125 | hints[1](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#workflow-hints) 126 | and apply them to your workflow if any are relevant. 127 | 128 | ### New requirements and hints keys 129 | 130 | - The following keys were added to the task `requirements` section: `fpga` 131 | [1](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#hardware-accelerators-gpu-and--fpga). 132 | - The following keys were added to the task `hints` section: `disks` 133 | [1](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-disks), 134 | `gpu` 135 | [2](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-gpu-and--fpga), 136 | and `fpga` 137 | [2](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#-gpu-and--fpga). 138 | 139 | You are encouraged to examine these keys are determine if any of these should be 140 | specified for your tasks. 141 | 142 | ### Metadata sections for structs 143 | 144 | Similarly to tasks and workflows, structs now have `meta` and `parameter_meta` 145 | sections. You are encouraged to use these fields according to the definition in 146 | the 147 | specification[1](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#struct-definition). 148 | 149 | ### Exponentiation operator 150 | 151 | The exponentiation operator (`**`) was added in this release. You are encouraged 152 | to go and update any manual exponentiation to use this operator instead. 153 | 154 | You are encouraged to go read the specification section on this concept 155 | ([link](https://github.com/openwdl/wdl/blob/wdl-1.2/SPEC.md#multi-line-strings)) 156 | and use them where appropriate. 157 | 158 | # Prior WDL versions 159 | 160 | Versions of WDL prior to the ones outlined in this guide did not exist at the 161 | time the upgrade guide was created. As such, they are not included in the guide. 162 | 163 | [wdl-v1.2-release-notes]: https://github.com/openwdl/wdl/releases/tag/v1.2.0 164 | [Versioning section]: ../language-guide/versions.md 165 | --------------------------------------------------------------------------------