diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2754f1e..3d2208c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,8 +9,7 @@ jobs: ci: runs-on: ${{ matrix.os }} env: - #hardcode the coveralls token...it's not overly important to protect, and github actions won't allow forks to work with coveralls otherwise - COVERALLS_REPO_TOKEN: "fSZnZ2ciuSy219J8ohCWIj5rvJOZVb8JO" + NODE_OPTIONS: "--max-old-space-size=4096" strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] @@ -18,8 +17,7 @@ jobs: - uses: actions/checkout@master - uses: actions/setup-node@master with: - node-version: "14.19.0" + node-version: "22" architecture: 'x64' # fix for macos-latest - run: npm ci - run: npm run preversion - - run: npm run publish-coverage diff --git a/.github/workflows/create-package.yml b/.github/workflows/create-package.yml.disabled similarity index 100% rename from .github/workflows/create-package.yml rename to .github/workflows/create-package.yml.disabled diff --git a/.github/workflows/create-vsix.yml b/.github/workflows/create-vsix.yml.disabled similarity index 100% rename from .github/workflows/create-vsix.yml rename to .github/workflows/create-vsix.yml.disabled diff --git a/.github/workflows/initialize-release.yml b/.github/workflows/initialize-release.yml.disabled similarity index 100% rename from .github/workflows/initialize-release.yml rename to .github/workflows/initialize-release.yml.disabled diff --git a/.github/workflows/make-release-artifacts.yml b/.github/workflows/make-release-artifacts.yml.disabled similarity index 100% rename from .github/workflows/make-release-artifacts.yml rename to .github/workflows/make-release-artifacts.yml.disabled diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml.disabled similarity index 100% rename from .github/workflows/publish-release.yml rename to .github/workflows/publish-release.yml.disabled diff --git a/.github/workflows/xelp_shadow_release.yml b/.github/workflows/xelp_shadow_release.yml new file mode 100644 index 0000000..60918e7 --- /dev/null +++ b/.github/workflows/xelp_shadow_release.yml @@ -0,0 +1,105 @@ +name: Xelp Shadow Release + +on: + workflow_dispatch: + +jobs: + shadow-release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout xelp/main + uses: actions/checkout@v4 + with: + ref: xelp/main + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Calculate XelpShadow Version + id: version + run: | + CURRENT_VERSION=$(node -p "require('./package.json').version") + PACKAGE_NAME=$(node -p "require('./package.json').name") + echo "Current version: $CURRENT_VERSION" + echo "Package name: $PACKAGE_NAME" + echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + # Remove pre-release and build metadata + BASE_VERSION=$(echo "$CURRENT_VERSION" | sed 's/[-+].*//') + + # Split version into parts + IFS='.' read -r -a PARTS <<< "$BASE_VERSION" + if [ ${#PARTS[@]} -ne 3 ]; then + echo "Error: Version must be in MAJOR.MINOR.PATCH format" + exit 1 + fi + MAJOR="${PARTS[0]}" + MINOR="${PARTS[1]}" + PATCH="${PARTS[2]}" + + # Get build metadata + DATE=$(date +'%Y%m%d') + SHORT_HASH=$(git rev-parse --short HEAD) + + # Construct base version: MAJOR.MINOR.DATE + CLEAN_VERSION="$MAJOR.$MINOR.$DATE$PATCH" + + # Full version with metadata for the tag message/release notes + METADATA_VERSION="$CLEAN_VERSION+xelp-$SHORT_HASH" + + # Use clean version for package.json and git tag (no + or -) + PACKAGE_VERSION="$CLEAN_VERSION" + TAG_VERSION="$CLEAN_VERSION" + + echo "Clean version: $CLEAN_VERSION" + echo "Metadata version: $METADATA_VERSION" + + echo "package_version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT + echo "tag_version=$TAG_VERSION" >> $GITHUB_OUTPUT + echo "metadata_version=$METADATA_VERSION" >> $GITHUB_OUTPUT + - name: Install dependencies + run: npm ci + + - name: Update package.json version + run: | + npm version ${{ steps.version.outputs.package_version }} --no-git-tag-version + + - name: Build + run: npm run build + + - name: Commit and Push + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -e + git checkout -b xelp/dist + git add -f dist/ package.json package-lock.json + git commit -m "Release shadow version ${{ steps.version.outputs.package_version }}" + git tag -a "${{ steps.version.outputs.tag_version }}" -m "Shadow release ${{ steps.version.outputs.metadata_version }}" + git push origin xelp/dist --force + git push origin "${{ steps.version.outputs.tag_version }}" --force + + - name: Create Release + env: + GH_TOKEN: ${{ secrets.GH_PAT }} + run: | + gh release create "${{ steps.version.outputs.tag_version }}" \ + --repo ${{ github.repository }} \ + --title "Shadow Release ${{ steps.version.outputs.tag_version }}" \ + --notes "Shadow release build ${{ steps.version.outputs.metadata_version }} + + ## package.json + \`\`\`json + \"${{ steps.version.outputs.package_name }}\": \"https://github.com/${{ github.repository }}.git#${{ steps.version.outputs.tag_version }}\" + \`\`\`" \ + --prerelease diff --git a/README.md b/README.md index 6c03954..127f08d 100644 --- a/README.md +++ b/README.md @@ -83,13 +83,14 @@ All boolean, string, and integer [`bsfmt.json`](#bsfmtjson-options) options are |compositeKeywords| `"split", "combine", "original"`| `"split"` | Forces all composite keywords (i.e. `elseif`, `endwhile`, etc...) to be consistent. If `"split"`, they are split into their alternatives (`else if`, `end while`). If `"combine"`', they are combined (`elseif`, `endwhile`). If `"original"` or falsey, they are not modified. | |removeTrailingWhiteSpace|`boolean`|`true`| Remove (or don't remove) trailing whitespace at the end of each line | |[keywordCaseOverride](#keywordCaseOverride)| `object`| `undefined`| Provides a way to override keyword case at the individual TokenType level| -|[typeCaseOverride](#typeCaseOverride)|`object`|`undefined`| Provides a way to override type keyword case at the individual TokenType level.Types are defined as keywords that are preceeded by an `as` token.| -|formatInteriorWhitespace|`boolean`|`true`| All whitespace between items is reduced to exactly 1 space character and certain keywords and operators are padded with whitespace. This is a catchall property that will also disable the following rules: `insertSpaceBeforeFunctionParenthesis`, `insertSpaceBetweenEmptyCurlyBraces` `insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces`| +|[typeCaseOverride](#typeCaseOverride)|`object`|`undefined`| Provides a way to override type keyword case at the individual TokenType level.Types are defined as keywords that are preceded by an `as` token.| +|formatInteriorWhitespace|`boolean`|`true`| All whitespace between items is reduced to exactly 1 space character and certain keywords and operators are padded with whitespace. This is a catchall property that will also disable the following rules: `insertSpaceBeforeFunctionParenthesis`, `insertSpaceBetweenEmptyCurlyBraces`, `insertSpaceAroundParameterAssignment`, `insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces`| |insertSpaceBeforeFunctionParenthesis|`boolean`|`false`| If true, a space is inserted to the left of an opening function declaration parenthesis. (i.e. `function main ()` or `function ()`). If false, all spacing is removed (i.e. `function main()` or `function()`).| |insertSpaceBetweenEmptyCurlyBraces|`boolean`|`false`| If true, empty curly braces will contain exactly 1 whitespace char (i.e. `{ }`). If false, there will be zero whitespace chars between empty curly braces (i.e. `{}`) | +|insertSpaceAroundParameterAssignment|`boolean`|`true`| If true, insert spaces around assignment operators in function parameters. (i.e. `function main(a = true, b = false)` or `function(a = true, b = false)`). If false, assignments will be collapsed (i.e. `function main(a=true, b=false)` or `function(a=true, b=false)`).| |insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces|`boolean`|`true`| If true, ensure exactly 1 space after leading and before trailing curly braces. If false, REMOVE all whitespace after leading and before trailing curly braces (excluding beginning-of-line indentation spacing)| |insertSpaceBetweenAssociativeArrayLiteralKeyAndColon|`boolean`|`false`| If true, ensure exactly 1 space between an associative array literal key and its colon. If false, all space between the key and its colon will be removed | -|formatSingleLineCommentType|`"singlequote", "rem", "original"`| `"original"` | Forces all single-line comments to use the same style. If 'singlequote' or falsey, all comments are preceeded by a single quote. This is the default. If `"rem"`, all comments are preceeded by `rem`. If `"original"`, the comment type is unchanged| +|formatSingleLineCommentType|`"singlequote", "rem", "original"`| `"original"` | Forces all single-line comments to use the same style. If 'singlequote' or falsey, all comments are preceded by a single quote. This is the default. If `"rem"`, all comments are preceded by `rem`. If `"original"`, the comment type is unchanged| |formatMultiLineObjectsAndArrays|`boolean`| `true`|For multi-line objects and arrays, move everything after the `{` or `[` and everything before the `}` or `]` onto a new line.`| |sortImports|`boolean`| `false`|Sort imports alphabetically.`| diff --git a/bsfmt.schema.json b/bsfmt.schema.json index 1b4213c..33cbc61 100644 --- a/bsfmt.schema.json +++ b/bsfmt.schema.json @@ -543,7 +543,7 @@ }, "typeCaseOverride": { "type": "object", - "description": " Provides a way to override type keyword case at the individual TokenType level. Types are defined as keywords that are preceeded by an `as` token.", + "description": " Provides a way to override type keyword case at the individual TokenType level. Types are defined as keywords that are preceded by an `as` token.", "properties": { "boolean": { "type": "string", @@ -661,6 +661,11 @@ "default": false, "description": "If true, empty curly braces will contain exactly 1 whitespace char (i.e. `{ }`). If false, there will be zero whitespace chars between empty curly braces (i.e. `{}`)" }, + "insertSpaceAroundParameterAssignment": { + "type": "boolean", + "default": true, + "description": "If true, insert spaces around assignment operators in function parameters (i.e. `function main(a = true, b = false)` or `function(a = true, b = false)`). If false, assignments will be collapsed (i.e. `function main(a=true, b=false)` or `function(a=true, b=false)`)." + }, "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": { "type": "boolean", "default": true, diff --git a/package-lock.json b/package-lock.json index a68ccfe..6919603 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.7.20", "license": "MIT", "dependencies": { - "brighterscript": "^0.70.3", + "brighterscript": "https://github.com/plexinc/brighterscript.git#0.70.202511253", "glob-all": "^3.3.0", "jsonc-parser": "^3.0.0", "source-map": "^0.7.3", @@ -355,9 +355,10 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -632,6 +633,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz", "integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -645,6 +647,7 @@ "version": "4.1.3-postman.1", "resolved": "https://registry.npmjs.org/@postman/tough-cookie/-/tough-cookie-4.1.3-postman.1.tgz", "integrity": "sha512-txpgUqZOnWYnUHZpHjkfb0IwVH4qJmyq77pPnJLlfhMtdCLMFTEeQHlzQiK906aaNCe4NEB5fGJHo9uzGbFMeA==", + "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -659,6 +662,7 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.4.tgz", "integrity": "sha512-CJJlq8V7rNKhAw4sBfjixKpJW00SHqebqNUQKxMoepgeWZIbdPcD+rguRcivGhS4N12PymDcKgUgSD4rVC+RjQ==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -669,12 +673,14 @@ "node_modules/@rokucommunity/bslib": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@rokucommunity/bslib/-/bslib-0.1.1.tgz", - "integrity": "sha512-2ox6EUL+UTtccTbD4dbVjZK3QHa0PHCqpoKMF8lZz9ayzzEP3iVPF8KZR6hOi6bxsIcbGXVjqmtCVkpC4P9SrA==" + "integrity": "sha512-2ox6EUL+UTtccTbD4dbVjZK3QHa0PHCqpoKMF8lZz9ayzzEP3iVPF8KZR6hOi6bxsIcbGXVjqmtCVkpC4P9SrA==", + "license": "MIT" }, "node_modules/@rokucommunity/logger": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/@rokucommunity/logger/-/logger-0.3.11.tgz", "integrity": "sha512-yQWa+rRVYkZeEYFePHzNtB6/DL+wPjjL/xt9wM0gQPDugSl8kJZ3ywyUtrFS+y/wzY0Nc2M+1704GVx0vdOO9A==", + "license": "MIT", "dependencies": { "chalk": "^4.1.2", "date-fns": "^2.30.0", @@ -688,6 +694,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -702,6 +709,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -717,6 +725,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -727,12 +736,14 @@ "node_modules/@rokucommunity/logger/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/@rokucommunity/logger/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -741,6 +752,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -755,6 +767,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -766,6 +779,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -835,7 +849,8 @@ "node_modules/@types/caseless": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", - "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "license": "MIT" }, "node_modules/@types/chai": { "version": "4.2.22", @@ -892,6 +907,7 @@ "version": "2.48.13", "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", + "license": "MIT", "dependencies": { "@types/caseless": "*", "@types/node": "*", @@ -917,7 +933,8 @@ "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.4", @@ -1200,6 +1217,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==", + "license": "Apache-2.0", "dependencies": { "chevrotain": "7.1.1" } @@ -1208,6 +1226,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz", "integrity": "sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw==", + "license": "Apache-2.0", "dependencies": { "regexp-to-ast": "0.5.0" } @@ -1246,6 +1265,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", "engines": { "node": ">= 14" } @@ -1356,6 +1376,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-flat-polyfill/-/array-flat-polyfill-1.0.1.tgz", "integrity": "sha512-hfJmKupmQN0lwi0xG6FQ5U8Rd97RnIERplymOv/qpq8AoNKPPAnxJadjFA23FNWm88wykh9HmpLJUUwUtNU/iw==", + "license": "CC0-1.0", "engines": { "node": ">=6.0.0" } @@ -1373,6 +1394,7 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } @@ -1381,6 +1403,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "license": "MIT", "engines": { "node": ">=0.8" } @@ -1403,6 +1426,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "license": "Apache-2.0", "engines": { "node": "*" } @@ -1410,7 +1434,8 @@ "node_modules/aws4": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "license": "MIT" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -1421,6 +1446,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" } @@ -1436,7 +1462,8 @@ "node_modules/bluebird": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==" + "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", + "license": "MIT" }, "node_modules/brace-expansion": { "version": "1.1.12", @@ -1459,9 +1486,9 @@ } }, "node_modules/brighterscript": { - "version": "0.70.3", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.70.3.tgz", - "integrity": "sha512-R9r/AWvxDZioTfDvRZT50yO+PAHl/nElKA3SO9eWfmF43J88CBEtLT1dpLfFPfmPfdtxjcF58ZW87rmcqqYVyA==", + "version": "0.70.202511253", + "resolved": "https://github.com/plexinc/brighterscript.git#0cefe327d40abc09e0486c3e7a66874a55ab603a", + "license": "MIT", "dependencies": { "@rokucommunity/bslib": "^0.1.1", "@rokucommunity/logger": "^0.3.11", @@ -1511,6 +1538,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1534,6 +1562,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -1546,12 +1575,14 @@ "node_modules/brighterscript/node_modules/jsonc-parser": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", - "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==" + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "license": "MIT" }, "node_modules/brighterscript/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -1560,6 +1591,7 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -1627,6 +1659,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -1675,7 +1708,8 @@ "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "license": "Apache-2.0" }, "node_modules/chai": { "version": "4.3.4", @@ -1720,6 +1754,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.2.tgz", "integrity": "sha512-9bQsXVQ7UAvzMs7iUBBJ9Yv//exOy7bIR3PByOEk4M64vIE/LsiOiX7VIkMF/vEMlrSStwsaE884Bp9CpjtC5g==", + "license": "Apache-2.0", "dependencies": { "regexp-to-ast": "0.5.0" } @@ -1836,7 +1871,8 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/coveralls-next": { "version": "4.2.1", @@ -1898,7 +1934,8 @@ "node_modules/cross-platform-clear-console": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cross-platform-clear-console/-/cross-platform-clear-console-2.3.0.tgz", - "integrity": "sha512-To+sJ6plHHC6k5DfdvSVn6F1GRGJh/R6p76bCpLbyMyHEmbqFyuMAeGwDcz/nGDWH3HUcjFTTX9iUSCzCg9Eiw==" + "integrity": "sha512-To+sJ6plHHC6k5DfdvSVn6F1GRGJh/R6p76bCpLbyMyHEmbqFyuMAeGwDcz/nGDWH3HUcjFTTX9iUSCzCg9Eiw==", + "license": "MIT" }, "node_modules/cross-spawn": { "version": "4.0.2", @@ -1930,6 +1967,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" }, @@ -1941,6 +1979,7 @@ "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -1956,6 +1995,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "license": "MIT", "engines": { "node": "*" } @@ -1963,12 +2003,14 @@ "node_modules/dayjs": { "version": "1.11.19", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==" + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" }, "node_modules/debounce-promise": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/debounce-promise/-/debounce-promise-3.1.2.tgz", - "integrity": "sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==" + "integrity": "sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==", + "license": "MIT" }, "node_modules/debug": { "version": "4.3.3", @@ -2070,6 +2112,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -2083,6 +2126,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "license": "MIT", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -2115,6 +2159,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2123,6 +2168,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2131,6 +2177,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, @@ -2142,6 +2189,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -2552,12 +2600,14 @@ "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, "node_modules/extsprintf": { "version": "1.3.0", @@ -2565,7 +2615,8 @@ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" - ] + ], + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -2624,6 +2675,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2742,6 +2794,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "license": "Apache-2.0", "engines": { "node": "*" } @@ -2750,6 +2803,7 @@ "version": "2.5.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2779,7 +2833,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/fromentries": { "version": "1.3.2", @@ -2855,6 +2910,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2895,6 +2951,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -2927,6 +2984,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -2939,6 +2997,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" } @@ -3146,6 +3205,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3185,6 +3245,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3196,6 +3257,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, @@ -3235,6 +3297,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3261,6 +3324,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", @@ -3281,7 +3345,8 @@ "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -3332,9 +3397,10 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", "engines": { "node": ">= 12" } @@ -3435,7 +3501,8 @@ "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", @@ -3446,7 +3513,8 @@ "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "license": "MIT" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -3633,7 +3701,8 @@ "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", @@ -3650,7 +3719,8 @@ "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -3667,7 +3737,8 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" }, "node_modules/json5": { "version": "2.2.3", @@ -3690,6 +3761,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -3701,6 +3773,7 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -3712,6 +3785,7 @@ "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -3751,6 +3825,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", "dependencies": { "immediate": "~3.0.5" } @@ -3769,7 +3844,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.flattendeep": { "version": "4.4.0", @@ -3787,7 +3863,8 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead." + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -3894,6 +3971,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", "integrity": "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg==", + "license": "Apache-2.0", "engines": { "node": ">=0.6" } @@ -3902,6 +3980,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz", "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==", + "license": "MIT", "engines": { "node": ">=12" } @@ -3940,6 +4019,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -4225,6 +4305,7 @@ "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } @@ -4460,6 +4541,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "license": "Apache-2.0", "engines": { "node": "*" } @@ -4493,6 +4575,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "license": "MIT", "dependencies": { "p-try": "^1.0.0" }, @@ -4549,6 +4632,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reflect/-/p-reflect-1.0.0.tgz", "integrity": "sha512-rlngKS+EX3nvI7xIzA0xKNVEAguWdIqAZVbn02z1m73ehXBdX66aTdD0bCvIu0cDwbU3TK9w3RYrppKpO3EnKQ==", + "license": "MIT", "engines": { "node": ">=4" } @@ -4557,6 +4641,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-settle/-/p-settle-2.1.0.tgz", "integrity": "sha512-NHFIUYc+fQTFRrzzAugq0l1drwi57PB522smetcY8C/EoTYs6cU/fC6TJj0N3rq5NhhJJbhf0VGWziL3jZDnjA==", + "license": "MIT", "dependencies": { "p-limit": "^1.2.0", "p-reflect": "^1.0.0" @@ -4569,6 +4654,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "license": "MIT", "engines": { "node": ">=4" } @@ -4591,7 +4677,8 @@ "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" }, "node_modules/parent-module": { "version": "1.0.1", @@ -4609,6 +4696,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -4704,6 +4792,7 @@ "version": "2.88.1-postman.46", "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.46.tgz", "integrity": "sha512-gcDb2vzjPXRKulfXq3p04H6VJVnMMREK2Nk+eBMhHTC5PQ7PXDp3AejzNAbcpqYR+e9FU09yJ4mYImddNAGG3Q==", + "license": "Apache-2.0", "dependencies": { "@postman/form-data": "~3.1.1", "@postman/tough-cookie": "~4.1.3-postman.1", @@ -4734,6 +4823,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -4750,7 +4840,8 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" }, "node_modules/process-on-spawn": { "version": "1.0.0", @@ -4789,6 +4880,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, @@ -4808,6 +4900,7 @@ "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.6" } @@ -4815,7 +4908,8 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -4849,6 +4943,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -4873,12 +4968,14 @@ "node_modules/readline": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", - "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "license": "BSD" }, "node_modules/regexp-to-ast": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", + "license": "MIT" }, "node_modules/regexpp": { "version": "3.2.0", @@ -4920,12 +5017,14 @@ "node_modules/require-relative": { "version": "0.8.7", "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==" + "integrity": "sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==", + "license": "MIT" }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", @@ -4961,9 +5060,10 @@ } }, "node_modules/roku-deploy": { - "version": "3.14.4", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.14.4.tgz", - "integrity": "sha512-JWx+VetKadMPnGrc80cQCSaJSuTtR1tAA/3JiygFBJiK7gPYBCx8/2c9fq1wajuJ+t/0dqP7XYD/6v33nliFwA==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.15.0.tgz", + "integrity": "sha512-8RkGnW1a/Wwr0iiNMHQ2YHEL2Sposb8gcnmHaohkTFuynaQ7dkwL6Epd6zC7/Nj38uqfwX5cAgNrsMq38I7P2g==", + "license": "MIT", "dependencies": { "@types/request": "^2.47.0", "chalk": "^2.4.2", @@ -4991,6 +5091,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -5003,12 +5104,14 @@ "node_modules/roku-deploy/node_modules/jsonc-parser": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", - "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==" + "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", + "license": "MIT" }, "node_modules/roku-deploy/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -5043,17 +5146,20 @@ "node_modules/safe-json-stringify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", - "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==" + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "license": "BlueOak-1.0.0" }, "node_modules/semver": { "version": "7.7.3", @@ -5070,6 +5176,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", "dependencies": { "type-fest": "^0.13.1" }, @@ -5097,7 +5204,8 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -5178,6 +5286,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -5187,6 +5296,7 @@ "version": "2.8.7", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" @@ -5200,6 +5310,7 @@ "version": "8.0.5", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", @@ -5213,6 +5324,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -5228,7 +5340,8 @@ "node_modules/socks-proxy-agent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/source-map": { "version": "0.7.4", @@ -5299,6 +5412,7 @@ "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "license": "MIT", "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -5323,6 +5437,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==", + "license": "WTFPL", "dependencies": { "bluebird": "^2.6.2" } @@ -5331,6 +5446,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } @@ -5395,6 +5511,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", "engines": { "node": ">=8" } @@ -5422,7 +5539,8 @@ "node_modules/thenby": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", - "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==" + "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", + "license": "Apache-2.0" }, "node_modules/to-fast-properties": { "version": "2.0.0", @@ -5518,7 +5636,8 @@ "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" }, "node_modules/type-check": { "version": "0.4.0", @@ -5545,6 +5664,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -5589,6 +5709,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "license": "MIT", "engines": { "node": ">= 4.0.0" } @@ -5606,6 +5727,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -5614,7 +5736,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/uuid": { "version": "3.4.0", @@ -5639,6 +5762,7 @@ "engines": [ "node >=0.6.0" ], + "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -5648,12 +5772,14 @@ "node_modules/verror/node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "license": "MIT" }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -5662,6 +5788,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, @@ -5673,25 +5800,29 @@ "version": "3.17.5", "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" }, "node_modules/vscode-languageserver-types": { "version": "3.17.5", "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" }, "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "license": "MIT" }, "node_modules/which": { "version": "1.3.1", @@ -5792,6 +5923,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "license": "MIT", "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" @@ -5804,6 +5936,7 @@ "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", "engines": { "node": ">=4.0" } @@ -6134,9 +6267,9 @@ "dev": true }, "@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==" + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==" }, "@babel/template": { "version": "7.24.0", @@ -6970,9 +7103,8 @@ } }, "brighterscript": { - "version": "0.70.3", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.70.3.tgz", - "integrity": "sha512-R9r/AWvxDZioTfDvRZT50yO+PAHl/nElKA3SO9eWfmF43J88CBEtLT1dpLfFPfmPfdtxjcF58ZW87rmcqqYVyA==", + "version": "https://github.com/plexinc/brighterscript.git#0cefe327d40abc09e0486c3e7a66874a55ab603a", + "from": "brighterscript@https://github.com/plexinc/brighterscript.git#0.70.202511253", "requires": { "@rokucommunity/bslib": "^0.1.1", "@rokucommunity/logger": "^0.3.11", @@ -8363,9 +8495,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==" + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==" }, "is-binary-path": { "version": "2.1.0", @@ -9597,9 +9729,9 @@ } }, "roku-deploy": { - "version": "3.14.4", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.14.4.tgz", - "integrity": "sha512-JWx+VetKadMPnGrc80cQCSaJSuTtR1tAA/3JiygFBJiK7gPYBCx8/2c9fq1wajuJ+t/0dqP7XYD/6v33nliFwA==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.15.0.tgz", + "integrity": "sha512-8RkGnW1a/Wwr0iiNMHQ2YHEL2Sposb8gcnmHaohkTFuynaQ7dkwL6Epd6zC7/Nj38uqfwX5cAgNrsMq38I7P2g==", "requires": { "@types/request": "^2.47.0", "chalk": "^2.4.2", @@ -9666,9 +9798,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==" }, "semver": { "version": "7.7.3", @@ -10138,9 +10270,9 @@ } }, "vscode-languageserver-textdocument": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" }, "vscode-languageserver-types": { "version": "3.17.5", @@ -10148,9 +10280,9 @@ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, "vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==" }, "which": { "version": "1.3.1", diff --git a/package.json b/package.json index 5ab0159..da348bf 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "brighterscript-formatter": "dist/cli.js" }, "dependencies": { - "brighterscript": "^0.70.3", + "brighterscript": "https://github.com/plexinc/brighterscript.git#0.70.202511253", "glob-all": "^3.3.0", "jsonc-parser": "^3.0.0", "source-map": "^0.7.3", diff --git a/src/FormattingOptions.ts b/src/FormattingOptions.ts index 0ebec3d..9ff331e 100644 --- a/src/FormattingOptions.ts +++ b/src/FormattingOptions.ts @@ -48,7 +48,7 @@ export interface FormattingOptions { keywordCaseOverride?: Record; /** * Provides a way to override type keyword case at the individual TokenType level. - * Types are defined as keywords that are preceeded by an `as` token. + * Types are defined as keywords that are preceded by an `as` token. */ typeCaseOverride?: Record; /** @@ -56,6 +56,7 @@ export interface FormattingOptions { * and certain keywords and operators are padded with whitespace (i.e. `1+1` becomes `1 + 1`). * This is a catchall property that will also disable the following rules: * - insertSpaceBeforeFunctionParenthesis + * - insertSpaceAroundParameterAssignment * - insertSpaceBetweenEmptyCurlyBraces * - insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces * - insertSpaceAfterConditionalCompileSymbol @@ -74,6 +75,12 @@ export interface FormattingOptions { * @default false */ insertSpaceBetweenEmptyCurlyBraces?: boolean; + /** + * If true, a space is inserted to the left of an opening function assignment parenthesis. (i.e. `function main(a = true, b = false)` or `function(a = true, b = false)`). + * If false, assignments will be collapsed (i.e. `function main(a=true, b=false)` or `function(a=true, b=false)`). + * @default true + */ + insertSpaceAroundParameterAssignment?: boolean; /** * if true, conditional compile symbols will contain exactly 1 whitespace char (i.e. `# if true`) * if false, ensure there is no whitespace between the `#` and the keyword (i.e. `#if true`) @@ -94,8 +101,8 @@ export interface FormattingOptions { insertSpaceBetweenAssociativeArrayLiteralKeyAndColon?: boolean; /** * Forces all single-line comments to use the same style. - * If 'singlequote' or falsey, all comments are preceeded by a single quote. This is the default. - * If 'rem', all comments are preceeded by `rem` + * If 'singlequote' or falsey, all comments are preceded by a single quote. This is the default. + * If 'rem', all comments are preceded by `rem` * If 'original', the comment type is unchanged * @default "original" */ @@ -122,6 +129,7 @@ export function normalizeOptions(options: FormattingOptions) { keywordCaseOverride: {}, formatInteriorWhitespace: true, insertSpaceBeforeFunctionParenthesis: false, + insertSpaceAroundParameterAssignment: true, insertSpaceBetweenEmptyCurlyBraces: false, insertSpaceAfterConditionalCompileSymbol: false, insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true, diff --git a/src/constants.ts b/src/constants.ts index d11575b..daf1a57 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -45,6 +45,7 @@ export const BasicKeywords = [ TokenKind.Goto, TokenKind.Dim, TokenKind.Stop, + TokenKind.AtStop, TokenKind.Void, TokenKind.Boolean, TokenKind.Integer, @@ -156,6 +157,7 @@ export let NumericLiteralTokenKinds = [ * we can safely assume the minus sign is associated with a negative numeric literal */ export let TokensBeforeNegativeNumericLiteral = [ + TokenKind.QuestionLeftParen, TokenKind.Plus, TokenKind.Minus, TokenKind.Star, @@ -187,7 +189,8 @@ export let TokensBeforeNegativeNumericLiteral = [ TokenKind.While, TokenKind.Or, TokenKind.And, - TokenKind.Not + TokenKind.Not, + TokenKind.Newline ]; export const TypeTokens = [ diff --git a/src/formatters/IndentFormatter.spec.ts b/src/formatters/IndentFormatter.spec.ts index c145f91..088d0e5 100644 --- a/src/formatters/IndentFormatter.spec.ts +++ b/src/formatters/IndentFormatter.spec.ts @@ -1,6 +1,10 @@ import { expect } from 'chai'; import { expectTokens, lex } from '../testHelpers.spec'; +import { undent } from 'undent'; import { IndentFormatter } from './IndentFormatter'; +import { Lexer, Parser, ParseMode, TokenKind } from 'brighterscript'; +import { util } from '../util'; +import { normalizeOptions } from '../FormattingOptions'; describe('IndentFormatter', () => { let formatter: IndentFormatter; @@ -9,6 +13,18 @@ describe('IndentFormatter', () => { formatter = new IndentFormatter(); }); + function format(text: string) { + const options = normalizeOptions({}); + let { tokens } = Lexer.scan(text, { includeWhitespace: true }); + const parser = Parser.parse( + tokens.filter(x => x.kind !== TokenKind.Whitespace), + { mode: ParseMode.BrighterScript } + ); + util.dedupeWhitespace(tokens); + tokens = formatter.format(tokens, options, parser); + return tokens.map(x => x.text).join(''); + } + describe('ensureTokenIndentation', () => { it('does nothing for empty or invalid tokens', () => { expect( @@ -60,6 +76,22 @@ describe('IndentFormatter', () => { ['\t\t\t', 'speak', '(', ')'] ); }); + + it('handles single-line if with @stop inside #if block', () => { + const input = undent` + #if DEBUG + ' When a colorsUrl is provided, there should always be a valid colorsUrlOriginId + if data.blur.colorsUrl <> invalid and IsInvalidOrEmpty(data.blur.colorsUrlOriginId) then @stop + #end if + `; + const expected = undent` + #if DEBUG + ' When a colorsUrl is provided, there should always be a valid colorsUrlOriginId + if data.blur.colorsUrl <> invalid and IsInvalidOrEmpty(data.blur.colorsUrlOriginId) then @stop + #end if + `; + expect(format(input)).to.equal(expected); + }); }); describe('trimWhitespaceOnlyLines', () => { @@ -77,4 +109,208 @@ describe('IndentFormatter', () => { ); }); }); + + it('handles array indentation in else if block', () => { + const input = undent` + sub test() + if true then + print "true" + else if ArrayContains([ + "addToWatchlist", + "removeFromWatchlist", + "removeFromContinueWatching", + "markAsWatched", + "markAsUnwatched" + ], action.id) then + Metrics().ReportEvent(action.metrics?.click) + end if + end sub + `; + const expected = undent` + sub test() + if true then + print "true" + else if ArrayContains([ + "addToWatchlist", + "removeFromWatchlist", + "removeFromContinueWatching", + "markAsWatched", + "markAsUnwatched" + ], action.id) then + Metrics().ReportEvent(action.metrics?.click) + end if + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles object literal indentation after array access', () => { + const input = undent` + sub test() + m["mainGroupCurrentBasePosition"] = { + "x": 0, + "y": 0 + } + end sub + `; + const expected = undent` + sub test() + m["mainGroupCurrentBasePosition"] = { + "x": 0, + "y": 0 + } + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles indentation for })] with function call', () => { + const input = undent` + function GetOverflowActionFromMetadata(metadata as object) as object + if metadata._container.isLiveTV = true or metadata.type = "collection" then return [] + + return [API().CreateAction("pmsOverflow", "overflow-horizontal-alt", ltr("More"), { + "data": { + "originId": metadata._container._originId, + "ratingKey": metadata["ratingKey"], + "key": metadata["key"].Replace("/children", ""), + }, + })] + end function + `; + const expected = undent` + function GetOverflowActionFromMetadata(metadata as object) as object + if metadata._container.isLiveTV = true or metadata.type = "collection" then return [] + + return [API().CreateAction("pmsOverflow", "overflow-horizontal-alt", ltr("More"), { + "data": { + "originId": metadata._container._originId, + "ratingKey": metadata["ratingKey"], + "key": metadata["key"].Replace("/children", ""), + }, + })] + end function + `; + expect(format(input)).to.equal(expected); + }); + + it('prevents double indentation when closing and opening indentors on the same line', () => { + const input = undent` + sub test() + a = { + x: 1 + } : b = { + y: 2 + } + end sub + `; + const expected = undent` + sub test() + a = { + x: 1 + } : b = { + y: 2 + } + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles continue for loop', () => { + const input = undent` + sub main() + for i = 0 to 10 + if true then continue for + end for + end sub + `; + const expected = undent` + sub main() + for i = 0 to 10 + if true then continue for + end for + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles continue while loop', () => { + const input = undent` + sub main() + while true + if true then continue while + end while + end sub + `; + const expected = undent` + sub main() + while true + if true then continue while + end while + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles double un-indent with nested arrays on same line', () => { + const input = undent` + sub main() + a = [[ + 1 + ]] + end sub + `; + const expected = undent` + sub main() + a = [[ + 1 + ]] + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles double un-indent with nested objects on same line', () => { + const input = undent` + sub main() + a = [{ + k: 1 + }] + end sub + `; + const expected = undent` + sub main() + a = [{ + k: 1 + }] + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles EOF after outdent token', () => { + const input = undent` + sub main() + end sub`; + const expected = undent` + sub main() + end sub`; + expect(format(input)).to.equal(expected); + }); + + it('handles next followed by colon', () => { + const input = undent` + sub main() + for i = 0 to 1 + next : print "done" + end sub + `; + const expected = undent` + sub main() + for i = 0 to 1 + next : print "done" + end sub + `; + expect(format(input)).to.equal(expected); + }); }); diff --git a/src/formatters/IndentFormatter.ts b/src/formatters/IndentFormatter.ts index 5980cdb..689b74a 100644 --- a/src/formatters/IndentFormatter.ts +++ b/src/formatters/IndentFormatter.ts @@ -5,6 +5,17 @@ import { OutdentSpacerTokenKinds, IndentSpacerTokenKinds, CallableKeywordTokenKi import type { FormattingOptions } from '../FormattingOptions'; import { util } from '../util'; +interface IndentState { + kind: TokenKind; + causedIndent: boolean; +} + +const StructureIndentTokenKinds = [ + TokenKind.LeftSquareBracket, + TokenKind.LeftCurlyBrace, + TokenKind.QuestionLeftSquare +]; + export class IndentFormatter { /** * Handle indentation for an array of tokens @@ -19,7 +30,7 @@ export class IndentFormatter { //get a map of all if statements for easier lookups const ifStatements = this.getAllIfStatements(parser); - let parentIndentTokenKinds: TokenKind[] = []; + let parentIndentTokenKinds: IndentState[] = []; //the list of output tokens let result: Token[] = []; @@ -50,16 +61,21 @@ export class IndentFormatter { lineTokens: Token[], tokens: Token[], ifStatements: Map, - parentIndentTokenKinds: TokenKind[] + parentIndentTokenKinds: IndentState[] ): { currentLineOffset: number; nextLineOffset: number } { const getParentIndentTokenKind = () => { - const parentIndentTokenKind = parentIndentTokenKinds.length > 0 ? parentIndentTokenKinds[parentIndentTokenKinds.length - 1] : undefined; + const parentIndentTokenKind = parentIndentTokenKinds.length > 0 ? parentIndentTokenKinds[parentIndentTokenKinds.length - 1].kind : undefined; return parentIndentTokenKind; }; let currentLineOffset = 0; let nextLineOffset = 0; let foundIndentorThisLine = false; + // Track the number of open indentors created on this line. + // This is used to determine if we should suppress indentation for structure indentors (like `[` or `{`). + // We only suppress if there is an *active* indentor on this line (e.g. `if ArrayContains([`). + // If an indentor was closed (e.g. `m["key"] = {`), we should NOT suppress. + let activeIndentorsOnThisLine = 0; for (let i = 0; i < lineTokens.length; i++) { let token = lineTokens[i]; @@ -73,6 +89,10 @@ export class IndentFormatter { //if the previous token was `else` and this token is `if`, skip this token. (we used to have a single token for `elseif` but it got split out in an update of brighterscript) if (previousNonWhitespaceToken?.kind === TokenKind.Else && token.kind === TokenKind.If) { + foundIndentorThisLine = true; + // `else if` implies an indentor (the `if` condition), even though the `If` token is skipped. + // So we treat it as an active indentor for the purpose of suppression. + activeIndentorsOnThisLine++; continue; } @@ -82,7 +102,7 @@ export class IndentFormatter { //is not being used as a key in an AA literal nextNonWhitespaceToken && nextNonWhitespaceToken.kind !== TokenKind.Colon ) { - //skip indent for 'function'|'sub' used as type (preceeded by `as` keyword) + //skip indent for 'function'|'sub' used as type (preceded by `as` keyword) if ( CallableKeywordTokenKinds.includes(token.kind) && //the previous token will be Whitespace, so verify that previousPrevious is 'as' @@ -113,7 +133,7 @@ export class IndentFormatter { // check for specifically mentioned tokens to NOT indent const parentIndentTokenKind = getParentIndentTokenKind(); - const parentIndentTokenKindsContainsSubOrFunction = parentIndentTokenKinds.includes(TokenKind.Sub) || parentIndentTokenKinds.includes(TokenKind.Function); + const parentIndentTokenKindsContainsSubOrFunction = parentIndentTokenKinds.some(x => x.kind === TokenKind.Sub || x.kind === TokenKind.Function); const tokenKindIsClass = token.kind === TokenKind.Class; const tokenKindIsEnum = token.kind === TokenKind.Enum; @@ -135,9 +155,20 @@ export class IndentFormatter { continue; } - nextLineOffset++; + // Don't indent if this is a structure indentor (like `[` or `{`) and we've already found an indentor on this line. + // This prevents double indentation for things like `if ArrayContains([` or `[[` + let causedIndent = true; + if (activeIndentorsOnThisLine > 0 && StructureIndentTokenKinds.includes(token.kind)) { + causedIndent = false; + } + + if (causedIndent) { + nextLineOffset++; + activeIndentorsOnThisLine++; + } + foundIndentorThisLine = true; - parentIndentTokenKinds.push(token.kind); + parentIndentTokenKinds.push({ kind: token.kind, causedIndent: causedIndent }); //don't double indent if this is `[[...\n...]]` or `[{...\n...}]` if ( @@ -159,7 +190,7 @@ export class IndentFormatter { } } } else if (this.isOutdentToken(token, nextNonWhitespaceToken)) { - //do not un-indent if this is a `next` or `endclass` token preceeded by a period + //do not un-indent if this is a `next` or `endclass` token preceded by a period if ( [TokenKind.Next, TokenKind.EndClass, TokenKind.Namespace, TokenKind.EndNamespace, TokenKind.Catch, TokenKind.EndTry].includes(token.kind) && previousNonWhitespaceToken && previousNonWhitespaceToken.kind === TokenKind.Dot @@ -167,11 +198,37 @@ export class IndentFormatter { continue; } - nextLineOffset--; + const popped = parentIndentTokenKinds.pop(); + if (popped?.causedIndent) { + nextLineOffset--; + activeIndentorsOnThisLine--; + if (activeIndentorsOnThisLine < 0) { + activeIndentorsOnThisLine = 0; + } + } + if (foundIndentorThisLine === false) { - currentLineOffset--; + let shouldDecrement = true; + //if this didn't cause an indent, and there is another outdenter on this line, + //then we shouldn't outdent the current line because the next outdenter will handle it + if (!popped?.causedIndent) { + for (let j = i + 1; j < lineTokens.length; j++) { + let nextTok = lineTokens[j]; + if (nextTok.kind === TokenKind.Whitespace) { + continue; + } + let nextNextTok = util.getNextNonWhitespaceToken(lineTokens, j); + if (this.isOutdentToken(nextTok, nextNextTok)) { + shouldDecrement = false; + break; + } + } + } + + if (shouldDecrement) { + currentLineOffset--; + } } - parentIndentTokenKinds.pop(); //don't double un-indent if this is `[[...\n...]]` or `[{...\n...}]` if ( @@ -344,11 +401,27 @@ export class IndentFormatter { ( //is not a letter isSymbol || - //is not a symbol and is not being used as a key in an AA literal - ( - !isSymbol && - nextNonWhitespaceToken.kind !== TokenKind.Colon - ) + //is not a symbol and is not being used as a key in an AA literal + ( + !isSymbol && + ( + nextNonWhitespaceToken.kind !== TokenKind.Colon || + //allow these tokens to be followed by a colon (because they are valid statement separators) + [ + TokenKind.EndIf, + TokenKind.EndFor, + TokenKind.EndWhile, + TokenKind.EndSub, + TokenKind.EndFunction, + TokenKind.EndTry, + TokenKind.EndClass, + TokenKind.EndNamespace, + TokenKind.Next, + TokenKind.EndInterface, + TokenKind.EndEnum + ].includes(token.kind) + ) + ) ) && //is not a method call !( diff --git a/src/formatters/InteriorWhitespaceFormatter.spec.ts b/src/formatters/InteriorWhitespaceFormatter.spec.ts new file mode 100644 index 0000000..9128ed6 --- /dev/null +++ b/src/formatters/InteriorWhitespaceFormatter.spec.ts @@ -0,0 +1,259 @@ + +import { expect } from 'chai'; +import { undent } from 'undent'; +import { normalizeOptions } from '../FormattingOptions'; +import { Lexer, Parser, ParseMode, TokenKind } from 'brighterscript'; +import { util } from '../util'; +import { InteriorWhitespaceFormatter } from './InteriorWhitespaceFormatter'; +import type { FormattingOptions } from '../FormattingOptions'; + +describe('insertSpaceAroundParameterAssignment', () => { + let interiorWhitespaceFormatter: InteriorWhitespaceFormatter; + + beforeEach(() => { + interiorWhitespaceFormatter = new InteriorWhitespaceFormatter(); + }); + + function format(text: string, formattingOptions = {} as FormattingOptions) { + const options = normalizeOptions(formattingOptions); + let { tokens } = Lexer.scan(text, { includeWhitespace: true }); + const parser = Parser.parse( + tokens.filter(x => x.kind !== TokenKind.Whitespace), + { mode: ParseMode.BrighterScript } + ); + util.dedupeWhitespace(tokens); + tokens = interiorWhitespaceFormatter.format(tokens, parser, options); + return tokens.map(x => x.text).join(''); + } + + it('formats empty objects in function parameters correctly', () => { + const input = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions={} as object) + print "hello" + end sub + `; + const expected = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions = {} as object) + print "hello" + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('formats empty objects in function parameters correctly with explicit option false', () => { + const input = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions={} as object) + print "hello" + end sub + `; + const expected = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions = {} as object) + print "hello" + end sub + `; + expect(format(input, { insertSpaceBetweenEmptyCurlyBraces: false })).to.equal(expected); + }); + + it('formats empty objects in function parameters correctly with explicit option true', () => { + const input = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions={} as object) + print "hello" + end sub + `; + const expected = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions = { } as object) + print "hello" + end sub + `; + expect(format(input, { insertSpaceBetweenEmptyCurlyBraces: true })).to.equal(expected); + }); + + it('formats empty objects in function parameters correctly with insertSpaceAroundParameterAssignment: false', () => { + const input = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions = {} as object) + print "hello" + end sub + `; + const expected = undent` + sub PlaybackSession_MakeDecisionAndSetContent(decisionOptions={} as object) + print "hello" + end sub + `; + expect(format(input, { insertSpaceAroundParameterAssignment: false })).to.equal(expected); + }); + + it('handles nested parentheses in function parameters correctly', () => { + const input = undent` + sub foo(a = (1 + 2), b = 3) + print "hello" + end sub + `; + const expected = undent` + sub foo(a=(1 + 2), b=3) + print "hello" + end sub + `; + expect(format(input, { insertSpaceAroundParameterAssignment: false })).to.equal(expected); + }); + + it('handles simple assignments in function parameters correctly', () => { + const input = undent` + sub foo(a = 1, b = 3) + print "hello" + end sub + `; + const expected = undent` + sub foo(a=1, b=3) + print "hello" + end sub + `; + expect(format(input, { insertSpaceAroundParameterAssignment: false })).to.equal(expected); + }); + + it('handles optional chaining in default parameter values', () => { + const input = undent` + sub foo(a = m?.call?()) + print "hello" + end sub + `; + const expected = undent` + sub foo(a=m?.call?()) + print "hello" + end sub + `; + expect(format(input, { insertSpaceAroundParameterAssignment: false })).to.equal(expected); + }); + + it('handles AA literal with key and colon on same line', () => { + const input = undent` + sub main() + a = { + key: "value" + } + end sub + `; + expect(format(input)).to.equal(input); + }); + + it('handles ReplacementIdentifier', () => { + const input = undent` + sub main() + print @{chromaIcons.STOP} + end sub + `; + expect(format(input)).to.equal(input); + }); + + it('handles anonymous function with insertSpaceAroundParameterAssignment: false', () => { + const input = undent` + sub main() + a = sub(a=1) + end sub + end sub + `; + expect(format(input, { insertSpaceAroundParameterAssignment: false })).to.equal(input); + }); + + it('handles parameter assignment without spaces with insertSpaceAroundParameterAssignment: false', () => { + const input = undent` + sub main(a=1) + end sub + `; + expect(format(input, { insertSpaceAroundParameterAssignment: false })).to.equal(input); + }); + + it('handles sub with invalid next token', () => { + const input = undent` + sub = + `; + expect(format(input)).to.equal(input); + }); + + it('handles incomplete parameter assignment (EOF)', () => { + const input = undent` + sub main(a= + `; + const expected = undent` + sub main(a = + `; + expect(format(input)).to.equal(expected); + }); + + it('handles } followed by non-] token', () => { + const input = undent` + sub main() + a = { + k: 1 + } + b = 2 + end sub + `; + expect(format(input)).to.equal(input); + }); + + it('handles ]] on different lines', () => { + const input = undent` + sub main() + a = [ + [ + 1 + ] + ] + end sub + `; + expect(format(input)).to.equal(input); + }); + + it('handles unmatched brackets', () => { + const input = undent` + sub main() + a = [[ + 1 + ] + end sub + `; + expect(format(input)).to.equal(input); + }); + + it('handles nested arrays with content', () => { + const input = undent` + sub main() + a = [ 1, [2] ] + end sub + `; + const expected = undent` + sub main() + a = [1, [2]] + end sub + `; + expect(format(input)).to.equal(expected); + }); + + it('handles EOF after ]', () => { + const input = undent` + sub main() + a = [1]`; + expect(format(input)).to.equal(input); + }); + + it('handles sub at EOF', () => { + const input = 'sub'; + expect(format(input)).to.equal(input); + }); + + it('handles sub name at EOF', () => { + const input = 'sub main'; + expect(format(input)).to.equal(input); + }); + + it('handles sub main(=)', () => { + const input = 'sub main(=)'; + const expected = 'sub main( =)'; + expect(format(input)).to.equal(expected); + }); + + it('handles sub main =', () => { + const input = 'sub main ='; + expect(format(input)).to.equal(input); + }); +}); diff --git a/src/formatters/InteriorWhitespaceFormatter.ts b/src/formatters/InteriorWhitespaceFormatter.ts index 963e589..427c57f 100644 --- a/src/formatters/InteriorWhitespaceFormatter.ts +++ b/src/formatters/InteriorWhitespaceFormatter.ts @@ -64,7 +64,8 @@ export class InteriorWhitespaceFormatter { let removeRight = [ ...removeBoth, TokenKind.LeftSquareBracket, - TokenKind.LeftParen + TokenKind.LeftParen, + TokenKind.QuestionLeftParen ]; let isPastFirstTokenOfLine = false; @@ -82,6 +83,20 @@ export class InteriorWhitespaceFormatter { if (token.kind === TokenKind.Whitespace && isPastFirstTokenOfLine === false) { continue; } + // skip replacement identifiers during whitespace formatting + if (token.kind === TokenKind.ReplacementIdentifier) { + continue; + } + + // Don't modify when a ] starts the line + if (token.kind === TokenKind.RightSquareBracket) { + const previousToken = util.getPreviousNonWhitespaceToken(tokens, i, true); + // If the previous non-whitespace token is a newline (or doesn't exist), + // this ] starts the line - skip all formatting for it + if (!previousToken || previousToken.kind === TokenKind.Newline) { + continue; + } + } //normalize whitespace following conditional compile symbol #if, #else, #elseif, etc... if (ConditionalCompileTokenKinds.includes(token.kind)) { @@ -148,8 +163,8 @@ export class InteriorWhitespaceFormatter { //pad any of these tokens with a space to the left if ( addLeft.includes(token.kind) && - //don't add left for negative sign preceeded by a square brace or paren - !(token.kind === TokenKind.Minus && previousTokenType && [TokenKind.LeftSquareBracket, TokenKind.LeftParen].includes(previousTokenType)) + //don't add left for negative sign preceded by a square brace or paren + !(token.kind === TokenKind.Minus && previousTokenType && [TokenKind.LeftSquareBracket, TokenKind.LeftParen, TokenKind.QuestionLeftParen].includes(previousTokenType)) ) { //ensure a space token to the left if (previousTokenType && previousTokenType !== TokenKind.Whitespace) { @@ -207,6 +222,62 @@ export class InteriorWhitespaceFormatter { for (i; i < tokens.length; i++) { setIndex(i); + // Special handling for the interior of functions (spacing between function assignment operators) + // When insertSpaceAroundParameterAssignment is false, remove spaces around parameter assignment operators + /* istanbul ignore if (valid and tested, but missing some coverage and hard to test) */ + if (options.insertSpaceAroundParameterAssignment === false && (token.kind === TokenKind.Sub || token.kind === TokenKind.Function)) { + const nextToken = util.getNextNonWhitespaceToken(tokens, i); + let parenToken: Token | undefined; + + // Detect immediate '(' after keyword or function name + if (nextToken?.kind === TokenKind.LeftParen) { + parenToken = nextToken; + } else if (nextToken?.kind === TokenKind.Identifier) { + const afterNext = util.getNextNonWhitespaceToken(tokens, tokens.indexOf(nextToken)); + if (afterNext?.kind === TokenKind.LeftParen) { + parenToken = afterNext; + } + } + + if (parenToken) { + // Iterate tokens inside parentheses and trim whitespace around assignment operators + // Track nested parentheses to find the correct closing paren + let j = tokens.indexOf(parenToken) + 1; + let parenDepth = 1; + const indicesToRemove: number[] = []; + while (j < tokens.length && parenDepth > 0) { + const t = tokens[j]; + + // Track nested parentheses + if (t.kind === TokenKind.LeftParen || t.kind === TokenKind.QuestionLeftParen) { + parenDepth++; + } else if (t.kind === TokenKind.RightParen) { + parenDepth--; + if (parenDepth === 0) { + break; + } + } + + if (t.kind === TokenKind.Equal) { + // Remove left whitespace + if (j > 0 && tokens[j - 1].kind === TokenKind.Whitespace) { + indicesToRemove.push(j - 1); + } + // Remove right whitespace + if (j + 1 < tokens.length && tokens[j + 1].kind === TokenKind.Whitespace) { + indicesToRemove.push(j + 1); + } + } + + j++; + } + // Remove the tokens in reverse order to avoid index shifting issues + for (const index of indicesToRemove.sort((a, b) => b - a)) { + tokens.splice(index, 1); + } + } + } + //space to left of function parens? { let parenToken: Token | undefined; @@ -383,7 +454,7 @@ export class InteriorWhitespaceFormatter { if ( nextToken && //next non-Whitespace token is an identifier - nextToken.kind === TokenKind.Identifier && + (nextToken.kind === TokenKind.Identifier || nextToken.kind === TokenKind.ReplacementIdentifier) && previousToken && TokensBeforeNegativeNumericLiteral.includes(previousToken.kind) ) { diff --git a/src/formatters/KeywordCaseFormatter.ts b/src/formatters/KeywordCaseFormatter.ts index 2414744..d13f6b3 100644 --- a/src/formatters/KeywordCaseFormatter.ts +++ b/src/formatters/KeywordCaseFormatter.ts @@ -16,7 +16,7 @@ export class KeywordCaseFormatter { let keywordCase: FormattingOptions['keywordCase']; let lowerKind = token.kind.toLowerCase(); - //a token is a type if it's preceeded by an `as` token + //a token is a type if it's preceded by an `as` token if (this.isType(tokens, token)) { //options.typeCase is always set to options.keywordCase when not provided keywordCase = options.typeCase; @@ -85,7 +85,7 @@ export class KeywordCaseFormatter { } /** - * Determine if the token is a type keyword (meaing preceeded by `as` token) + * Determine if the token is a type keyword (meaning preceded by `as` token) * @param token */ public isType(tokens: Token[], token: Token) { diff --git a/src/formatters/MultiLineItemFormatter.spec.ts b/src/formatters/MultiLineItemFormatter.spec.ts new file mode 100644 index 0000000..3968d67 --- /dev/null +++ b/src/formatters/MultiLineItemFormatter.spec.ts @@ -0,0 +1,29 @@ + +import { expect } from 'chai'; +import { Formatter } from '../Formatter'; + +describe('MultiLineItemFormatter', () => { + let formatter: Formatter; + + beforeEach(() => { + formatter = new Formatter(); + }); + + it('preserves return array on same line', () => { + const inputSameLine = `sub foo()\n return [1, 2, 3]\nend sub`; + const expectedSameLine = `sub foo()\n return [1, 2, 3]\nend sub`; + expect(formatter.format(inputSameLine).trim()).to.equal(expectedSameLine.trim()); + }); + + it('preserves return object on same line (multi-line content)', () => { + const input = `sub foo()\n return {\n a: 1\n }\nend sub`; + const expected = `sub foo()\n return {\n a: 1\n }\nend sub`; + expect(formatter.format(input).trim()).to.equal(expected.trim()); + }); + + it('preserves return object starting on same line but multiline', () => { + const input = `sub foo()\n return { a: 1,\n b: 2\n }\nend sub`; + const expected = `sub foo()\n return { a: 1,\n b: 2\n }\nend sub`; + expect(formatter.format(input).trim()).to.equal(expected.trim()); + }); +}); diff --git a/src/formatters/MultiLineItemFormatter.ts b/src/formatters/MultiLineItemFormatter.ts index dcc279e..17faef5 100644 --- a/src/formatters/MultiLineItemFormatter.ts +++ b/src/formatters/MultiLineItemFormatter.ts @@ -31,7 +31,9 @@ export class MultiLineItemFormatter { //there is extra stuff on this line that is not the end of the file nextNonWhitespaceToken && nextNonWhitespaceToken.kind !== TokenKind.Eof && //is NOT array like `[[ ...\n ]]`, or `[{ ...\n }]`) - !this.isMatchingDoubleArrayOrArrayCurly(tokens, i) + !this.isMatchingDoubleArrayOrArrayCurly(tokens, i) && + //Don't reformat if the opening bracket or curly is on the same line as 'return' + !this.isReturnArrayOrCurlyOnSameLine(tokens, i) ) { tokens.splice(i + 1, 0, { kind: TokenKind.Newline, @@ -98,4 +100,35 @@ export class MultiLineItemFormatter { } } } + + /** + * Check if this is an array or object that starts on the same line as a 'return' statement + * We want to preserve: return [...] or return {...} + * Even if the contents span multiple lines + */ + private isReturnArrayOrCurlyOnSameLine(tokens: Token[], currentIndex: number): boolean { + let token = tokens[currentIndex]; + // Only check for arrays or objects + /* istanbul ignore if (should not happen, defensive programming) */ + if (token.kind !== TokenKind.LeftSquareBracket && token.kind !== TokenKind.LeftCurlyBrace) { + return false; + } + + // Look backwards to see if there's a 'return' on the same line + for (let i = currentIndex - 1; i >= 0; i--) { + let prevToken = tokens[i]; + + // If we hit a newline, there's no return on this line + if (prevToken.kind === TokenKind.Newline) { + return false; + } + + // If we find 'return', this array is part of a return statement on the same line + if (prevToken.kind === TokenKind.Return) { + return true; + } + } + + return false; + } }