diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..60d743f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,181 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# EditorConfig configuration file (see ). + +# Indicate that this file is a root-level configuration file: +root = true + +# Set properties for all files: +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# Set properties for JavaScript files: +[*.{js,js.txt}] +indent_style = tab + +# Set properties for JavaScript ES module files: +[*.{mjs,mjs.txt}] +indent_style = tab + +# Set properties for JavaScript CommonJS files: +[*.{cjs,cjs.txt}] +indent_style = tab + +# Set properties for JSON files: +[*.{json,json.txt}] +indent_style = space +indent_size = 2 + +# Set properties for `cli_opts.json` files: +[cli_opts.json] +indent_style = tab + +# Set properties for TypeScript files: +[*.ts] +indent_style = tab + +# Set properties for Python files: +[*.{py,py.txt}] +indent_style = space +indent_size = 4 + +# Set properties for Julia files: +[*.{jl,jl.txt}] +indent_style = tab + +# Set properties for R files: +[*.{R,R.txt}] +indent_style = tab + +# Set properties for C files: +[*.{c,c.txt}] +indent_style = tab + +# Set properties for C header files: +[*.{h,h.txt}] +indent_style = tab + +# Set properties for C++ files: +[*.{cpp,cpp.txt}] +indent_style = tab + +# Set properties for C++ header files: +[*.{hpp,hpp.txt}] +indent_style = tab + +# Set properties for Fortran files: +[*.{f,f.txt}] +indent_style = space +indent_size = 2 +insert_final_newline = false + +# Set properties for shell files: +[*.{sh,sh.txt}] +indent_style = tab + +# Set properties for AWK files: +[*.{awk,awk.txt}] +indent_style = tab + +# Set properties for HTML files: +[*.{html,html.txt}] +indent_style = tab +tab_width = 2 + +# Set properties for XML files: +[*.{xml,xml.txt}] +indent_style = tab +tab_width = 2 + +# Set properties for CSS files: +[*.{css,css.txt}] +indent_style = tab + +# Set properties for Makefiles: +[Makefile] +indent_style = tab + +[*.{mk,mk.txt}] +indent_style = tab + +# Set properties for Markdown files: +[*.{md,md.txt}] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = false + +# Set properties for `usage.txt` files: +[usage.txt] +indent_style = space +indent_size = 2 + +# Set properties for `repl.txt` files: +[repl.txt] +indent_style = space +indent_size = 4 + +# Set properties for `package.json` files: +[package.{json,json.txt}] +indent_style = space +indent_size = 2 + +# Set properties for `datapackage.json` files: +[datapackage.json] +indent_style = space +indent_size = 2 + +# Set properties for `manifest.json` files: +[manifest.json] +indent_style = space +indent_size = 2 + +# Set properties for `tsconfig.json` files: +[tsconfig.json] +indent_style = space +indent_size = 2 + +# Set properties for LaTeX files: +[*.{tex,tex.txt}] +indent_style = tab + +# Set properties for LaTeX Bibliography files: +[*.{bib,bib.txt}] +indent_style = tab + +# Set properties for YAML files: +[*.{yml,yml.txt}] +indent_style = space +indent_size = 2 + +# Set properties for GYP files: +[binding.gyp] +indent_style = space +indent_size = 2 + +[*.gypi] +indent_style = space +indent_size = 2 + +# Set properties for citation files: +[*.{cff,cff.txt}] +indent_style = space +indent_size = 2 diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..5f30286 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1 @@ +/* For the `eslint` rules of this project, consult the main repository at https://github.com/stdlib-js/stdlib */ diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1c88e69 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,66 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2017 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Configuration file which assigns attributes to pathnames. +# +# [1]: https://git-scm.com/docs/gitattributes + +# Automatically normalize the line endings of any committed text files: +* text=auto + +# Override line endings for certain files on checkout: +*.crlf.csv text eol=crlf + +# Denote that certain files are binary and should not be modified: +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.gz binary +*.zip binary +*.7z binary +*.mp3 binary +*.mp4 binary +*.mov binary + +# Override what is considered "vendored" by GitHub's linguist: +/lib/node_modules/** -linguist-vendored -linguist-generated + +# Configure directories which should *not* be included in GitHub language statistics: +/deps/** linguist-vendored +/dist/** linguist-generated +/workshops/** linguist-vendored + +benchmark/** linguist-vendored +docs/* linguist-documentation +etc/** linguist-vendored +examples/** linguist-documentation +scripts/** linguist-vendored +test/** linguist-vendored +tools/** linguist-vendored + +# Configure files which should *not* be included in GitHub language statistics: +Makefile linguist-vendored +*.mk linguist-vendored +*.jl linguist-vendored +*.py linguist-vendored +*.R linguist-vendored + +# Configure files which should be included in GitHub language statistics: +docs/types/*.d.ts -linguist-documentation diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..3f97802 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ + + +We are excited about your pull request, but unfortunately we are not accepting pull requests against this repository, as all development happens on the [main project repository](https://github.com/stdlib-js/stdlib). We kindly request that you submit this pull request against the [respective directory](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/mskput) of the main repository where we’ll review and provide feedback. + +If this is your first stdlib contribution, be sure to read the [contributing guide](https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md) which provides guidelines and instructions for submitting contributions. You may also consult the [development guide](https://github.com/stdlib-js/stdlib/blob/develop/docs/development.md) for help on developing stdlib. + +We look forward to receiving your contribution! :smiley: \ No newline at end of file diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 0000000..e4f10fe --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,64 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2021 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: benchmark + +# Workflow triggers: +on: + # Allow the workflow to be manually run: + workflow_dispatch: + +# Workflow jobs: +jobs: + + # Define a job to run benchmarks: + benchmark: + + # Define a display name: + name: 'Run benchmarks' + + # Define the type of virtual host machine: + runs-on: 'ubuntu-latest' + + # Define the sequence of job steps... + steps: + + # Checkout the repository: + - name: 'Checkout repository' + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + # Install Node.js: + - name: 'Install Node.js' + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Install dependencies: + - name: 'Install production and development dependencies' + run: | + npm install || npm install || npm install + timeout-minutes: 15 + + # Run benchmarks: + - name: 'Run benchmarks' + run: | + npm run benchmark diff --git a/.github/workflows/cancel.yml b/.github/workflows/cancel.yml new file mode 100644 index 0000000..b5291db --- /dev/null +++ b/.github/workflows/cancel.yml @@ -0,0 +1,57 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2021 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: cancel + +# Workflow triggers: +on: + # Allow the workflow to be manually run: + workflow_dispatch: + +# Workflow jobs: +jobs: + + # Define a job to cancel existing workflow runs: + cancel: + + # Define a display name: + name: 'Cancel workflow runs' + + # Define the type of virtual host machine: + runs-on: 'ubuntu-latest' + + # Time limit: + timeout-minutes: 3 + + # Define the sequence of job steps... + steps: + + # Cancel existing workflow runs: + - name: 'Cancel existing workflow runs' + # Pin action to full length commit SHA + uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # v0.12.1 + with: + workflow_id: >- + benchmark.yml, + examples.yml, + test.yml, + test_coverage.yml, + test_install.yml, + publish.yml + access_token: ${{ github.token }} diff --git a/.github/workflows/close_pull_requests.yml b/.github/workflows/close_pull_requests.yml new file mode 100644 index 0000000..3454987 --- /dev/null +++ b/.github/workflows/close_pull_requests.yml @@ -0,0 +1,54 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2021 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: close_pull_requests + +# Workflow triggers: +on: + pull_request_target: + types: [opened] + +# Workflow jobs: +jobs: + + # Define job to close all pull requests: + run: + + # Define the type of virtual host machine on which to run the job: + runs-on: ubuntu-latest + + # Define the sequence of job steps... + steps: + + # Close pull request + - name: 'Close pull request' + # Pin action to full length commit SHA corresponding to v3.1.2 + uses: superbrothers/close-pull-request@9c18513d320d7b2c7185fb93396d0c664d5d8448 + with: + comment: | + Thank you for submitting a pull request. :raised_hands: + + We greatly appreciate your willingness to submit a contribution. However, we are not accepting pull requests against this repository, as all development happens on the [main project repository](https://github.com/stdlib-js/stdlib). + + We kindly request that you submit this pull request against the [respective directory](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/mskput) of the main repository where we’ll review and provide feedback. If this is your first stdlib contribution, be sure to read the [contributing guide](https://github.com/stdlib-js/stdlib/blob/develop/CONTRIBUTING.md) which provides guidelines and instructions for submitting contributions. + + Thank you again, and we look forward to receiving your contribution! :smiley: + + Best, + The stdlib team \ No newline at end of file diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 0000000..2984901 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,64 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2021 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: examples + +# Workflow triggers: +on: + # Allow the workflow to be manually run: + workflow_dispatch: + +# Workflow jobs: +jobs: + + # Define a job to run the package examples... + examples: + + # Define display name: + name: 'Run examples' + + # Define the type of virtual host machine on which to run the job: + runs-on: ubuntu-latest + + # Define the sequence of job steps... + steps: + + # Checkout repository: + - name: 'Checkout repository' + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + # Install Node.js: + - name: 'Install Node.js' + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Install dependencies: + - name: 'Install production and development dependencies' + run: | + npm install || npm install || npm install + timeout-minutes: 15 + + # Run examples: + - name: 'Run examples' + run: | + npm run examples diff --git a/.github/workflows/npm_downloads.yml b/.github/workflows/npm_downloads.yml new file mode 100644 index 0000000..eaf4492 --- /dev/null +++ b/.github/workflows/npm_downloads.yml @@ -0,0 +1,112 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2022 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: npm_downloads + +# Workflow triggers: +on: + # Run this workflow weekly: + schedule: + # cron: ' ' + - cron: '37 13 * * 2' + + # Allow the workflow to be manually run: + workflow_dispatch: + +# Workflow jobs: +jobs: + + # Define a job for retrieving npm download counts... + npm_downloads: + + # Define display name: + name: 'Retrieve npm download counts' + + # Define the type of virtual host machine on which to run the job: + runs-on: ubuntu-latest + + # Define the sequence of job steps... + steps: + # Checkout the repository: + - name: 'Checkout repository' + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + timeout-minutes: 10 + + # Install Node.js: + - name: 'Install Node.js' + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Resolve package name: + - name: 'Resolve package name' + id: package_name + run: | + name=`node -e 'console.log(require("./package.json").name)' | tr -d '\n'` + echo "package_name=$name" >> $GITHUB_OUTPUT + timeout-minutes: 5 + + # Fetch download data: + - name: 'Fetch data' + id: download_data + run: | + url="https://api.npmjs.org/downloads/range/$(date --date='1 year ago' '+%Y-%m-%d'):$(date '+%Y-%m-%d')/${{ steps.package_name.outputs.package_name }}" + echo "$url" + data=$(curl "$url") + mkdir ./tmp + echo "$data" > ./tmp/npm_downloads.json + echo "data=$data" >> $GITHUB_OUTPUT + timeout-minutes: 5 + + # Print summary of download data: + - name: 'Print summary' + run: | + echo "| Date | Downloads |" >> $GITHUB_STEP_SUMMARY + echo "|------|------------|" >> $GITHUB_STEP_SUMMARY + cat ./tmp/npm_downloads.json | jq -r ".downloads | .[-14:] | to_entries | map(\"| \(.value.day) | \(.value.downloads) |\") |.[]" >> $GITHUB_STEP_SUMMARY + + # Upload the download data: + - name: 'Upload data' + # Pin action to full length commit SHA + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + # Define a name for the uploaded artifact (ensuring a unique name for each job): + name: npm_downloads + + # Specify the path to the file to upload: + path: ./tmp/npm_downloads.json + + # Specify the number of days to retain the artifact (default is 90 days): + retention-days: 90 + timeout-minutes: 10 + if: success() + + # Send data to events server: + - name: 'Post data' + # Pin action to full length commit SHA + uses: distributhor/workflow-webhook@48a40b380ce4593b6a6676528cd005986ae56629 # v3.0.3 + env: + webhook_url: ${{ secrets.STDLIB_NPM_DOWNLOADS_URL }} + webhook_secret: ${{ secrets.STDLIB_WEBHOOK_SECRET }} + data: '{ "downloads": ${{ steps.download_data.outputs.data }} }' + timeout-minutes: 5 + if: success() diff --git a/.github/workflows/productionize.yml b/.github/workflows/productionize.yml new file mode 100644 index 0000000..f92a6c5 --- /dev/null +++ b/.github/workflows/productionize.yml @@ -0,0 +1,794 @@ +#/ +# @license Apache-2.0 +# +# Copyright (c) 2022 The Stdlib Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#/ + +# Workflow name: +name: productionize + +# Workflow triggers: +on: + # Run workflow when a new commit is pushed to the main branch: + push: + branches: + - main + + # Allow the workflow to be manually run: + workflow_dispatch: + inputs: + require-passing-tests: + description: 'Require passing tests for creating bundles' + type: boolean + default: true + + # Run workflow upon completion of `publish` workflow run: + workflow_run: + workflows: ["publish"] + types: [completed] + + +# Concurrency group to prevent multiple concurrent executions: +concurrency: + group: productionize + cancel-in-progress: true + +# Workflow jobs: +jobs: + + # Define a job to create a production build... + productionize: + + # Define display name: + name: 'Productionize' + + # Define the type of virtual host machine: + runs-on: 'ubuntu-latest' + + # Define the sequence of job steps... + steps: + # Checkout main branch of repository: + - name: 'Checkout main branch' + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + ref: main + + # Install Node.js: + - name: 'Install Node.js' + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Create production branch: + - name: 'Create production branch' + run: | + git checkout -b production + + # Transform error messages: + - name: 'Transform error messages' + id: transform-error-messages + uses: stdlib-js/transform-errors-action@main + + # Change `@stdlib/string-format` to `@stdlib/error-tools-fmtprodmsg` in package.json if the former is a dependency, otherwise insert it as a dependency: + - name: 'Update dependencies in package.json' + run: | + PKG_VERSION=$(npm view @stdlib/error-tools-fmtprodmsg version) + if grep -q '"@stdlib/string-format"' package.json; then + sed -i "s/\"@stdlib\/string-format\": \"^.*\"/\"@stdlib\/error-tools-fmtprodmsg\": \"^$PKG_VERSION\"/g" package.json + else + node -e "var pkg = require( './package.json' ); pkg.dependencies[ '@stdlib/error-tools-fmtprodmsg' ] = '^$PKG_VERSION'; require( 'fs' ).writeFileSync( 'package.json', JSON.stringify( pkg, null, 2 ) );" + fi + + # Configure git: + - name: 'Configure git' + run: | + git config --local user.email "noreply@stdlib.io" + git config --local user.name "stdlib-bot" + + # Commit changes: + - name: 'Commit changes' + run: | + git add -A + git commit -m "Transform error messages" + + # Push changes: + - name: 'Push changes' + run: | + SLUG=${{ github.repository }} + echo "Pushing changes to $SLUG..." + git push "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$SLUG.git" production --force + + # Define a job for running tests of the productionized code... + test: + + # Define a display name: + name: 'Run Tests' + + # Define the type of virtual host machine: + runs-on: 'ubuntu-latest' + + # Indicate that this job depends on the prior job finishing: + needs: productionize + + # Run this job regardless of the outcome of the prior job: + if: always() + + # Define the sequence of job steps... + steps: + + # Checkout the repository: + - name: 'Checkout repository' + if: ${{ github.event.inputs.require-passing-tests == 'true' }} + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + # Use the `production` branch: + ref: production + + # Install Node.js: + - name: 'Install Node.js' + if: ${{ github.event.inputs.require-passing-tests == 'true' }} + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Install dependencies: + - name: 'Install production and development dependencies' + if: ${{ github.event.inputs.require-passing-tests == 'true' }} + id: install + run: | + npm install || npm install || npm install + timeout-minutes: 15 + + # Build native add-on if present: + - name: 'Build native add-on (if present)' + if: ${{ github.event.inputs.require-passing-tests == 'true' }} + run: | + if [ -f "binding.gyp" ]; then + npm install node-gyp --no-save && ./node_modules/.bin/node-gyp rebuild + fi + + # Run tests: + - name: 'Run tests' + if: ${{ github.event.inputs.require-passing-tests == 'true' }} + id: tests + run: | + npm test || npm test || npm test + + # Define job to create a bundle for use in Deno... + deno: + + # Define display name: + name: 'Create Deno bundle' + + # Define the type of virtual host machine on which to run the job: + runs-on: ubuntu-latest + + # Indicate that this job depends on the test job finishing: + needs: test + + # Define the sequence of job steps... + steps: + # Checkout the repository: + - name: 'Checkout repository' + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + # Configure git: + - name: 'Configure git' + run: | + git config --local user.email "noreply@stdlib.io" + git config --local user.name "stdlib-bot" + + # Check if remote `deno` branch exists: + - name: 'Check if remote `deno` branch exists' + id: deno-branch-exists + continue-on-error: true + run: | + git fetch --all + git ls-remote --exit-code --heads origin deno + if [ $? -eq 0 ]; then + echo "remote-exists=true" >> $GITHUB_OUTPUT + else + echo "remote-exists=false" >> $GITHUB_OUTPUT + fi + + # If `deno` exists, delete everything in branch and merge `production` into it + - name: 'If `deno` exists, delete everything in branch and merge `production` into it' + if: steps.deno-branch-exists.outputs.remote-exists + run: | + git checkout -b deno origin/deno + + find . -type 'f' | grep -v -e ".git/" -e "package.json" -e "README.md" -e "LICENSE" -e "CONTRIBUTORS" -e "NOTICE" | xargs -r rm + find . -mindepth 1 -type 'd' | grep -v -e ".git" | xargs -r rm -rf + + git add -A + git commit -m "Remove files" --allow-empty + + git config merge.theirs.name 'simulate `-s theirs`' + git config merge.theirs.driver 'cat %B > %A' + GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge origin/production --allow-unrelated-histories + + # Copy files from `production` branch if necessary: + git checkout origin/production -- . + if [ -n "$(git status --porcelain)" ]; then + git add -A + git commit -m "Auto-generated commit" + fi + + # If `deno` does not exist, create `deno` branch: + - name: 'If `deno` does not exist, create `deno` branch' + if: ${{ steps.deno-branch-exists.outputs.remote-exists == false }} + run: | + git checkout production + git checkout -b deno + + # Copy files to deno directory: + - name: 'Copy files to deno directory' + run: | + mkdir -p deno + cp README.md LICENSE CONTRIBUTORS NOTICE ./deno + + # Copy TypeScript definitions to deno directory: + if [ -d index.d.ts ]; then + cp index.d.ts ./deno/index.d.ts + fi + if [ -e ./docs/types/index.d.ts ]; then + cp ./docs/types/index.d.ts ./deno/mod.d.ts + fi + + # Install Node.js: + - name: 'Install Node.js' + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Install dependencies: + - name: Install production and development dependencies + id: install + run: | + npm install || npm install || npm install + timeout-minutes: 15 + + # Bundle package for use in Deno: + - name: 'Bundle package for Deno' + id: deno-bundle + uses: stdlib-js/bundle-action@main + with: + target: 'deno' + + # Rewrite file contents: + - name: 'Rewrite file contents' + run: | + # Replace links to other packages with links to the deno branch: + find ./deno -type f -name '*.md' -print0 | xargs -0 sed -Ei "/\/tree\/main/b; /^\[@stdlib[^:]+: https:\/\/github.com\/stdlib-js\// s/(.*)/\\1\/tree\/deno/"; + + # Replace reference to `@stdlib/types` with CDN link: + find ./deno -type f -name '*.ts' -print0 | xargs -0 -r sed -Ei "s/\/\/\/ /\/\/\/ /g" + + # Change wording of project description to avoid reference to JavaScript and Node.js: + find ./deno -type f -name '*.md' -print0 | xargs -0 sed -Ei "s/a standard library for JavaScript and Node.js, /a standard library /g" + + # Rewrite all `require()`s to use jsDelivr links: + find ./deno -type f -name '*.md' -print0 | xargs -0 sed -Ei "/require\( '@stdlib\// { + s/(var|let|const)\s+([a-z0-9_]+)\s+=\s*require\( '([^']+)' \);/import \2 from \'\3\';/i + s/@stdlib/https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js/ + s/';/@deno\/mod.js';/ + }" + + # Rewrite first `import` to show importing of named exports if available: + exports=$(cat lib/index.js | \ + grep -E 'setReadOnly\(.*,.*,.*\)' | \ + sed -E 's/setReadOnly\((.*),(.*),(.*)\);/\2/' | \ + sed -E "s/'//g" | \ + sort) + if [ -n "$exports" ]; then + find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\`\`\`javascript\nimport\s+([a-zA-Z0-9_]+)\s+from\s*'([^']+)';\n\`\`\`/\`\`\`javascript\nimport \1 from '\2';\n\`\`\`\n\nYou can also import the following named exports from the package:\n\n\`\`\`javascript\nimport { $(echo $exports | sed -E 's/ /, /g') } from '\2';\n\`\`\`/" + fi + + # Remove `installation`, `cli`, and `c` sections: + find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/
[^<]+<\/section>//g;" + find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?
[\s\S]+<\!\-\- \/.cli \-\->//g" + find ./deno -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?
[\s\S]+<\!\-\- \/.c \-\->//g" + + # Create package.json file for deno branch: + jq --indent 2 '{"name": .name, "version": .version, "description": .description, "license": .license, "type": "module", "main": "./mod.js", "homepage": .homepage, "repository": .repository, "bugs": .bugs, "keywords": .keywords, "funding": .funding}' package.json > ./deno/package.json + + # Delete everything in current directory aside from deno folder: + - name: 'Delete everything in current directory aside from deno folder' + run: | + find . -type 'f' | grep -v -e "deno" -e ".git/" | xargs -r rm + find . -mindepth 1 -type 'd' | grep -v -e "deno" -e ".git" | xargs -r rm -rf + + # Move deno directory to root: + - name: 'Move deno directory to root' + run: | + mv ./deno/* . + rmdir ./deno + + # Commit changes: + - name: 'Commit changes' + run: | + git add -A + git commit -m "Auto-generated commit" + + # Push changes to `deno` branch: + - name: 'Push changes to `deno` branch' + run: | + SLUG=${{ github.repository }} + echo "Pushing changes to $SLUG..." + git push "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$SLUG.git" deno + + # Send status to Slack channel if job fails: + - name: 'Send status to Slack channel in case of failure' + # Pin action to full length commit SHA + uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 # v3.16.2 + with: + status: ${{ job.status }} + channel: '#npm-ci' + if: failure() + + # Define job to create a UMD bundle... + umd: + + # Define display name: + name: 'Create UMD bundle' + + # Define the type of virtual host machine on which to run the job: + runs-on: ubuntu-latest + + # Indicate that this job depends on the test job finishing: + needs: test + + # Define the sequence of job steps... + steps: + # Checkout the repository: + - name: 'Checkout repository' + # Pin action to full length commit SHA + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + # Configure git: + - name: 'Configure git' + run: | + git config --local user.email "noreply@stdlib.io" + git config --local user.name "stdlib-bot" + + # Check if remote `umd` branch exists: + - name: 'Check if remote `umd` branch exists' + id: umd-branch-exists + continue-on-error: true + run: | + git fetch --all + git ls-remote --exit-code --heads origin umd + if [ $? -eq 0 ]; then + echo "remote-exists=true" >> $GITHUB_OUTPUT + else + echo "remote-exists=false" >> $GITHUB_OUTPUT + fi + + # If `umd` exists, delete everything in branch and merge `production` into it + - name: 'If `umd` exists, delete everything in branch and merge `production` into it' + if: steps.umd-branch-exists.outputs.remote-exists + run: | + git checkout -b umd origin/umd + + find . -type 'f' | grep -v -e ".git/" -e "package.json" -e "README.md" -e "LICENSE" -e "CONTRIBUTORS" -e "NOTICE" | xargs -r rm + find . -mindepth 1 -type 'd' | grep -v -e ".git" | xargs -r rm -rf + + git add -A + git commit -m "Remove files" --allow-empty + + git config merge.theirs.name 'simulate `-s theirs`' + git config merge.theirs.driver 'cat %B > %A' + GIT_CONFIG_PARAMETERS="'merge.default=theirs'" git merge origin/production --allow-unrelated-histories + + # Copy files from `production` branch if necessary: + git checkout origin/production -- . + if [ -n "$(git status --porcelain)" ]; then + git add -A + git commit -m "Auto-generated commit" + fi + + # If `umd` does not exist, create `umd` branch: + - name: 'If `umd` does not exist, create `umd` branch' + if: ${{ steps.umd-branch-exists.outputs.remote-exists == false }} + run: | + git checkout production + git checkout -b umd + + # Copy files to umd directory: + - name: 'Copy files to umd directory' + run: | + mkdir -p umd + cp README.md LICENSE CONTRIBUTORS NOTICE ./umd + + # Install Node.js + - name: 'Install Node.js' + # Pin action to full length commit SHA + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + with: + node-version: 20 + timeout-minutes: 5 + + # Install dependencies: + - name: 'Install production and development dependencies' + id: install + run: | + npm install || npm install || npm install + timeout-minutes: 15 + + # Extract alias: + - name: 'Extract alias' + id: extract-alias + run: | + alias=$(grep -E 'require\(' README.md | head -n 1 | sed -E 's/^var ([a-zA-Z0-9_]+) = .+/\1/') + echo "alias=${alias}" >> $GITHUB_OUTPUT + + # Create Universal Module Definition (UMD) Node.js bundle: + - name: 'Create Universal Module Definition (UMD) Node.js bundle' + id: umd-bundle-node + uses: stdlib-js/bundle-action@main + with: + target: 'umd-node' + alias: ${{ steps.extract-alias.outputs.alias }} + + # Create Universal Module Definition (UMD) browser bundle: + - name: 'Create Universal Module Definition (UMD) browser bundle' + id: umd-bundle-browser + uses: stdlib-js/bundle-action@main + with: + target: 'umd-browser' + alias: ${{ steps.extract-alias.outputs.alias }} + + # Rewrite file contents: + - name: 'Rewrite file contents' + run: | + + # Replace links to other packages with links to the umd branch: + find ./umd -type f -name '*.md' -print0 | xargs -0 sed -Ei "/\/tree\/main/b; /^\[@stdlib[^:]+: https:\/\/github.com\/stdlib-js\// s/(.*)/\\1\/tree\/umd/"; + + # Remove `installation`, `cli`, and `c` sections: + find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/
[^<]+<\/section>//g;" + find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?
[\s\S]+<\!\-\- \/.cli \-\->//g" + find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/(\* \* \*\n+)?
[\s\S]+<\!\-\- \/.c \-\->//g" + + # Rewrite first `require()` to show consumption of the UMD bundle in Observable and via a `script` tag: + find ./umd -type f -name '*.md' -print0 | xargs -0 perl -0777 -i -pe "s/\`\`\`javascript\n(var|let|const)\s+([a-zA-Z0-9_]+)\s+=\s*require\( '\@stdlib\/([^']+)' \);\n\`\`\`/To use in Observable,\n\n\`\`\`javascript\n\2 = require\( 'https:\/\/cdn.jsdelivr.net\/gh\/stdlib-js\/\3\@umd\/browser.js' \)\n\`\`\`\n\nTo vendor stdlib functionality and avoid installing dependency trees for Node.js, you can use the UMD server build:\n\n\`\`\`javascript\nvar \2 = require\( 'path\/to\/vendor\/umd\/\3\/index.js' \)\n\`\`\`\n\nTo include the bundle in a webpage,\n\n\`\`\`html\n