From 1edc72a63789c1ccfdebe903d70bd59cf1e5e13b Mon Sep 17 00:00:00 2001 From: Adedoyin Ogunjobi Date: Thu, 30 Apr 2026 08:38:48 -0400 Subject: [PATCH] Adding tunables to wizard. If this is acceptable will add variables in the same manner adding variables Bump fast-xml-parser from 5.5.9 to 5.7.2 Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 5.5.9 to 5.7.2. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.9...v5.7.2) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 5.7.2 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Bump @vscode/vsce from 3.7.1 to 3.9.1 Bumps [@vscode/vsce](https://github.com/Microsoft/vsce) from 3.7.1 to 3.9.1. - [Release notes](https://github.com/Microsoft/vsce/releases) - [Commits](https://github.com/Microsoft/vsce/compare/v3.7.1...v3.9.1) --- updated-dependencies: - dependency-name: "@vscode/vsce" dependency-version: 3.9.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Bump actions/setup-node from 6.3.0 to 6.4.0 Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.3.0 to 6.4.0. - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/53b83947a5a98c8d113130e565377fae1a50d02f...48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e) --- updated-dependencies: - dependency-name: actions/setup-node dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Bump actions/github-script from 8.0.0 to 9.0.0 Bumps [actions/github-script](https://github.com/actions/github-script) from 8.0.0 to 9.0.0. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/ed597411d8f924073f98dfc5c65a23a2325f34cd...3a2844b7e9c422d3c10d287c895573f7108da1b3) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: 9.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Changed wording in CI to match PR template Documentation Variable and Tunable Configuration Added sections on Variable and Tunable Configuration with usage instructions and references. Fix copy mechanism Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> copilot recommendations copilot recommendations copilot recs. Last one --- .github/workflows/CI.yml | 6 +- .github/workflows/documentaion.yml | 6 +- .github/workflows/licenses.yml | 4 +- .github/workflows/nightly.yml | 2 +- .github/workflows/release-candidate.yml | 2 +- doc/Wiki.md | 31 ++++++ package.json | 4 +- src/classes/vscode-launch.ts | 2 + src/launchWizard/launchWizard.ts | 44 +++++++- src/launchWizard/script.js | 138 +++++++++++++++++++++++- yarn.lock | 62 ++++++----- 11 files changed, 263 insertions(+), 38 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ccf981f3e..bf0dc5d1f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check Single Commit - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: script: | const commits = await github.rest.pulls.listCommits({ @@ -80,7 +80,7 @@ jobs: java-version: ${{ matrix.java_version }} - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node }} cache: yarn @@ -154,7 +154,7 @@ jobs: uses: sbt/setup-sbt@508b753e53cb6095967669e0911487d2b9bc9f41 # v1 - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node }} cache: yarn diff --git a/.github/workflows/documentaion.yml b/.github/workflows/documentaion.yml index d82e14ee6..c38a2f70c 100644 --- a/.github/workflows/documentaion.yml +++ b/.github/workflows/documentaion.yml @@ -35,13 +35,13 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check required confirmation checkbox - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v7 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v7 with: script: | const prBody = context.payload.pull_request.body || ""; const checkbox1Text = "- [x] I have determined that no documentation updates are needed for these changes"; - const checkbox2Text = "- [x] I have added following documentation for these changes"; - + const checkbox2Text = "- [x] I have added the following documentation for these changes"; + if (!prBody.includes(checkbox1Text) && !prBody.includes(checkbox2Text)) { core.setFailed("❌ Required documentation checkbox not checked. Please check one of the the box before merging."); } else { diff --git a/.github/workflows/licenses.yml b/.github/workflows/licenses.yml index b9aea3d0a..5ef19467c 100644 --- a/.github/workflows/licenses.yml +++ b/.github/workflows/licenses.yml @@ -83,7 +83,7 @@ jobs: fetch-depth: 0 - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node }} cache: yarn @@ -121,7 +121,7 @@ jobs: fetch-depth: 0 - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node }} cache: yarn diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b959fbdee..22785e91d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -80,7 +80,7 @@ jobs: java-version: ${{ matrix.java_version }} - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node }} diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index 3c5601522..4c0ef140c 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -59,7 +59,7 @@ jobs: java-version: 17 - name: Install Node.js - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4.4.0 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4.4.0 with: node-version: 20 cache: yarn diff --git a/doc/Wiki.md b/doc/Wiki.md index 33de4d37b..e01504b03 100644 --- a/doc/Wiki.md +++ b/doc/Wiki.md @@ -332,6 +332,37 @@ Referenced Links: * https://sematext.com/blog/logging-levels/ * https://www.crowdstrike.com/en-us/cybersecurity-101/next-gen-siem/logging-levels/ +## Variable Configuration + +Variables are configured using **Key** and **Value** fields in the launch configuration wizard. + +- **Key**: The variable name +- **Value**: The value assigned to the variable + +Use the **“+ Add Variable”** button to add additional entries. Each row can be removed using the **“X”** button. + +variables_gui + +variables_launchjson + +## Tunable Configuration + +Tunables are configured using **Key** and **Value** fields in the launch configuration wizard. + +- **Key**: The tunable name +- **Value**: The value assigned to the tunable + +Use the **“+ Add Tunable”** button to add additional entries. Each row can be removed using the **“X”** button. + +Tunables control runtime behavior and performance characteristics. Most tunables have default values, so you only need to specify a value if you want to override them. + +tunables_gui + +tunables_launchjson + +### Reference +- https://daffodil.apache.org/tunables/ + ## Root element and namespace auto suggestions/finding In the launch.json file, there's a new suggestion mode that gives you suggestions to fill in for the rootname. If you specify the specific schema path, and then save the file, and reopen it. Go to rootname and delete whatever value is set-- it will show you various suggestions. diff --git a/package.json b/package.json index 005ba782c..7285454fa 100644 --- a/package.json +++ b/package.json @@ -82,13 +82,13 @@ "@types/vscode-webview": "^1.57.5", "@vscode/debugadapter-testsupport": "1.68.0", "@vscode/test-electron": "2.5.2", - "@vscode/vsce": "^3.5.0", + "@vscode/vsce": "^3.9.1", "chai": "^6.0.1", "cli-progress": "^3.12.0", "concurrently": "^9.2.1", "css-loader": "^7.1.2", "esbuild": "^0.25.10", - "fast-xml-parser": "^5.5.9", + "fast-xml-parser": "^5.7.2", "glob": "13.0.0", "mocha": "11.5.0", "picocolors": "^1.1.1", diff --git a/src/classes/vscode-launch.ts b/src/classes/vscode-launch.ts index e53e7fd36..5f8a1d0f9 100644 --- a/src/classes/vscode-launch.ts +++ b/src/classes/vscode-launch.ts @@ -35,6 +35,8 @@ export interface VSCodeLaunchConfigArgs { stopOnEntry: boolean useExistingServer: boolean trace: boolean + tunables?: Record + variables?: Record openDataEditor: boolean openInfosetView: boolean openInfosetDiffView: boolean diff --git a/src/launchWizard/launchWizard.ts b/src/launchWizard/launchWizard.ts index 4ca675302..72c6ab08f 100644 --- a/src/launchWizard/launchWizard.ts +++ b/src/launchWizard/launchWizard.ts @@ -754,7 +754,50 @@ class LaunchWizard {

TDML File Path:

+ +
+

Tunables:

+

Key/value configuration options

+ + + + + + + + + + + + +
KeyValue
+ + +
+
+

Variables:

+

Key/value configuration options

+ + + + + + + + + + + + +
KeyValue
+ + +

Data Editor Settings:

@@ -769,7 +812,6 @@ class LaunchWizard { ${dataEditorLogLevelSelect}
-
diff --git a/src/launchWizard/script.js b/src/launchWizard/script.js index c7356db55..20b5ed095 100644 --- a/src/launchWizard/script.js +++ b/src/launchWizard/script.js @@ -41,6 +41,8 @@ function getConfigIndex() { } function getConfigValues() { + const tunables = getTunablesFromTable() + const variables = getVariablesFromTable() var configSelectionBox = document.getElementById('configSelected') var configSelectedValue = configSelectionBox.options[configSelectionBox.selectedIndex].value @@ -94,7 +96,6 @@ function getConfigValues() { : document.getElementById('rootNamespace').value const daffodilDebugClasspath = getDaffodilDebugClasspathArray() - return { name, data, @@ -122,6 +123,8 @@ function getConfigValues() { daffodilDebugClasspath, rootName, rootNamespace, + tunables, + variables, } } @@ -275,6 +278,8 @@ function save() { configSelectedValue === 'New Config' ? 'create' : 'update' const configValues = getConfigValues() + const tunables = getTunablesFromTable() + const variables = getVariablesFromTable() var obj = { version: '0.2.0', @@ -295,6 +300,8 @@ function save() { type: configValues.infosetOutputType, path: configValues.infosetOutputFilePath, }, + tunables: tunables, + variables: variables, tdmlConfig: { action: configValues.tdmlAction, // Additional fields are added below @@ -346,6 +353,115 @@ function save() { updateOrCreate: updateOrCreate, }) } +// Function for adding row to tunables table +function addTunableRow() { + const tableBody = document.getElementById('tunablesTableBody') + + const row = document.createElement('tr') + + row.innerHTML = ` + + + + ` + + tableBody.appendChild(row) +} + +function getTunablesFromTable() { + const rows = document.querySelectorAll('#tunablesTableBody tr') + const tunables = {} + + rows.forEach((row) => { + const key = row.children[0].querySelector('input')?.value?.trim() + const value = row.children[1].querySelector('input')?.value + + if (!key) return + + tunables[key] = value + }) + + return tunables +} + +function escapeHtml(str) { + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') +} + +// function to pull tunables from config and render them in the tunables table, if there are any +function renderTunables(tunables = {}) { + const tableBody = document.getElementById('tunablesTableBody') + tableBody.innerHTML = '' + + Object.entries(tunables).forEach(([key, value]) => { + const row = document.createElement('tr') + + row.innerHTML = ` + + + + ` + + tableBody.appendChild(row) + }) +} + +// Function for adding row to variables table +function addVariableRow() { + const tableBody = document.getElementById('variablesTableBody') + + const row = document.createElement('tr') + + row.innerHTML = ` + + + + ` + + tableBody.appendChild(row) +} + +function getVariablesFromTable() { + const rows = document.querySelectorAll('#variablesTableBody tr') + const variables = {} + + rows.forEach((row) => { + const key = row.children[0].querySelector('input')?.value?.trim() + const value = row.children[1].querySelector('input')?.value + + if (!key) return + + variables[key] = value + }) + + return variables +} + +// function to pull variables from config and render them in the tunables table, if there are any. + +function renderVariables(variables = {}) { + const tableBody = document.getElementById('variablesTableBody') + + // Clear existing UI + tableBody.innerHTML = '' + + Object.entries(variables).forEach(([key, value]) => { + const row = document.createElement('tr') + + row.innerHTML = ` + + + + ` + + tableBody.appendChild(row) + }) +} // Function to copy selected config function copyConfig() { @@ -370,6 +486,8 @@ function copyConfig() { type: configValues.infosetOutputType, path: configValues.infosetOutputFilePath, }, + tunables: configValues.tunables, + variables: configValues.variables, tdmlConfig: { action: configValues.tdmlAction, name: configValues.tdmlName, @@ -465,6 +583,8 @@ async function updateConfigValues(config) { document.getElementById('dfdlDebuggerLogLevel').value = config.dfdlDebugger.logging.level + renderTunables(config.tunables || {}) + renderVariables(config.variables || {}) updateInfosetOutputType() updateTDMLAction() @@ -508,4 +628,20 @@ async function updateDaffodilDebugClasspath(message) { break } }) + + // Wait for the webview to signal readiness before sending config. + // Prevents the initial config message from being lost, ensuring launch.json + // values are rendered on load. + window.addEventListener('DOMContentLoaded', () => { + // vscode is injected by extension + if (typeof vscode !== 'undefined') { + const configIndex = getConfigIndex() + vscode.postMessage({ + command: 'updateConfigValue', + configIndex: configIndex, + }) + } else { + console.error('vscode API not found') + } + }) })() diff --git a/yarn.lock b/yarn.lock index 89d0a4d36..ae65f1fe2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -506,6 +506,11 @@ dependencies: exenv-es6 "^1.1.1" +"@nodable/entities@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@nodable/entities/-/entities-2.1.0.tgz#f543e5c6446720d4cf9e498a83019dd159973bc2" + integrity sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1299,10 +1304,10 @@ optionalDependencies: keytar "^7.7.0" -"@vscode/vsce@^3.5.0": - version "3.7.1" - resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-3.7.1.tgz#55a88ae40e9618fea251e373bc6b23c128915654" - integrity sha512-OTm2XdMt2YkpSn2Nx7z2EJtSuhRHsTPYsSK59hr3v8jRArK+2UEoju4Jumn1CmpgoBLGI6ReHLJ/czYltNUW3g== +"@vscode/vsce@^3.9.1": + version "3.9.1" + resolved "https://registry.yarnpkg.com/@vscode/vsce/-/vsce-3.9.1.tgz#cf273fe0895a14fe8a5e7fd88630bb5a5876ad6a" + integrity sha512-MPn5p+DoudI+3GfJSpAZZraE1lgLv0LcwbH3+xy7RgEhty3UIkmUMUA+5jPTDaxXae00AnX5u77FxGM8FhfKKA== dependencies: "@azure/identity" "^4.1.0" "@secretlint/node" "^10.1.2" @@ -1331,7 +1336,7 @@ typed-rest-client "^1.8.4" url-join "^4.0.1" xml2js "^0.5.0" - yauzl "^2.3.1" + yauzl "^3.2.1" yazl "^2.2.2" optionalDependencies: keytar "^7.7.0" @@ -2348,21 +2353,22 @@ fast-uri@^3.0.1: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== -fast-xml-builder@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz#0c407a1d9d5996336c0cd76f7ff785cac6413017" - integrity sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg== +fast-xml-builder@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz#50188e1452a5fa095f415d3e63dcac0a1dbcbf11" + integrity sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA== dependencies: path-expression-matcher "^1.1.3" -fast-xml-parser@^5.5.9: - version "5.5.9" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.5.9.tgz#e59637abebec3dbfbb4053b532d787af6ea11527" - integrity sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g== +fast-xml-parser@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.7.2.tgz#fecd0b054c6c132fc03dab994a413da781e0eb9f" + integrity sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w== dependencies: - fast-xml-builder "^1.1.4" - path-expression-matcher "^1.2.0" - strnum "^2.2.2" + "@nodable/entities" "^2.1.0" + fast-xml-builder "^1.1.5" + path-expression-matcher "^1.5.0" + strnum "^2.2.3" fastq@^1.6.0: version "1.19.1" @@ -3687,10 +3693,10 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-expression-matcher@^1.1.3, path-expression-matcher@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.2.0.tgz#9bdae3787f43b0857b0269e9caaa586c12c8abee" - integrity sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ== +path-expression-matcher@^1.1.3, path-expression-matcher@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz#3b98545dc88ffebb593e2d8458d0929da9275f4a" + integrity sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ== path-is-absolute@^1.0.0: version "1.0.1" @@ -4519,10 +4525,10 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -strnum@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.2.tgz#f11fd94ab62b536ba2ecc615858f3747c2881b3f" - integrity sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA== +strnum@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.2.3.tgz#0119fce02749a11bb126a4d686ac5dbdf6e57586" + integrity sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg== structured-source@^4.0.0: version "4.0.0" @@ -5208,6 +5214,14 @@ yauzl@^2.3.1: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yauzl@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-3.3.0.tgz#5be5e287b9a8112941c177734a34bf61a3e11bb4" + integrity sha512-PtGEvEP30p7sbIBJKUBjUnqgTVOyMURc4dLo9iNyAJnNIEz9pm88cCXF21w94Kg3k6RXkeZh5DHOGS0qEONvNQ== + dependencies: + buffer-crc32 "~0.2.3" + pend "~1.2.0" + yazl@^2.2.2: version "2.5.1" resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"