diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4efdeb9db..7466f8475 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,20 +1,14 @@ -# derived from -# https://github.com/actions/starter-workflows/blob/main/ci/node.js.yml -# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions +# this workflow will run nodejs coverages and tests and +# upload build-artifacts to branch-gh-pages name: CI on: push: branches: - - alpha - - beta - - master - - sandbox - # - none - # - pull_request: - # branches: - # - alpha - # - beta + - alpha + - beta + - master + - sandbox +# shCiBase - start jobs: build: runs-on: ${{ matrix.os }} @@ -43,9 +37,13 @@ jobs: architecture: ${{ matrix.architecture }} # fetch ci.sh from trusted source - run: git fetch origin alpha && git checkout origin/alpha ci.sh - - run: sh ci.sh shGithubCi + # run nodejs coverages and tests + - run: sh ci.sh shCiBase +# shCiBase - end + # fetch ci.sh from trusted source - run: git fetch origin alpha && git checkout origin/alpha ci.sh - - run: sh ci.sh shGithubArtifactUpload + # upload build-artifacts to branch-gh-pages + - run: sh ci.sh shCiArtifactUpload env: CI_NODE_VERSION_ARCH_PLATFORM: v14.x64.linux GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml new file mode 100644 index 000000000..9274873fc --- /dev/null +++ b/.github/workflows/on_pull_request.yml @@ -0,0 +1,36 @@ +# this workflow will run nodejs coverages and tests +name: on_pull_request +on: + - pull_request +# shCiBase - start +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + architecture: + # - arm64 + - x64 + # - x86 + node_version: + - 12 + - 14 + - 16 + os: + - macos-latest + - ubuntu-latest + - windows-latest + name: node . v${{ matrix.node_version }} . ${{ matrix.architecture }} . ${{ matrix.os }} + steps: + # https://github.com/actions/checkout + - uses: actions/checkout@v2 + # https://github.com/actions/setup-node + - uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node_version }} + architecture: ${{ matrix.architecture }} + # fetch ci.sh from trusted source + - run: git fetch origin alpha && git checkout origin/alpha ci.sh + # run nodejs coverages and tests + - run: sh ci.sh shCiBase +# shCiBase - end diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..3eee5b2f6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,29 @@ +# Changelog + +## Todo +- doc - add svg package-listing. +- ci - continue addng regression tests and improve code-coverage. +- none + +## v9999.99.99 +- none + +## v2021.5.21 +- this ci-release does not change any core-functionality of file jslint.js +- doc - add file CHANGELOG.md +- ci - begin addng regression tests and improve code-coverage. +- ci - allow pull-requests to run restricted-ci (cannot upload artifacts). +- gh-pages - fix missing assets and insecure http-links. +- gh-pages - merge file jslint.css into index.html. +- gh-pages - add files image-jslint-xxx.png. +- gh-pages - cleanup asset naming-convention. +- fix missing fonts in function.html and help.html. +- add files .gitconfig, Daley-Bold.woff2, Programma-Bold.woff2, icon-folder-open-solid.svg, icon-window-maximize-regular.svg. +- ci - fix http-links after moving to jslint-org. +- doc - migrate file README to README.md with embedded ci links and screenshots. +- ci - add macos and windows to ci-matrix. +- ci - ci now fails if jslint-check fails for any of the files in branches. +- ci - add github-workflows to generate code-coverage for jslint.js. + +## v2020.11.6 +- vestigial diff --git a/README.md b/README.md index fe68c7169..31ba717c7 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,20 @@ Douglas Crockford douglas@crockford.com -2020-11-06 +## v2021.5.21 ## Status | Branch | [master](https://github.com/jslint-org/jslint/tree/master) | [beta](https://github.com/jslint-org/jslint/tree/beta) | [alpha](https://github.com/jslint-org/jslint/tree/alpha)| |--:|:--:|:--:|:--:| | CI | [![ci](https://github.com/jslint-org/jslint/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/jslint-org/jslint/actions?query=branch%3Amaster) | [![ci](https://github.com/jslint-org/jslint/actions/workflows/ci.yml/badge.svg?branch=beta)](https://github.com/jslint-org/jslint/actions?query=branch%3Abeta) | [![ci](https://github.com/jslint-org/jslint/actions/workflows/ci.yml/badge.svg?branch=alpha)](https://github.com/jslint-org/jslint/actions?query=branch%3Aalpha)| | Coverage | [![coverage](https://jslint-org.github.io/jslint/branch.master/.build/coverage/coverage-badge.svg)](https://jslint-org.github.io/jslint/branch.master/.build/coverage/index.html) | [![coverage](https://jslint-org.github.io/jslint/branch.beta/.build/coverage/coverage-badge.svg)](https://jslint-org.github.io/jslint/branch.beta/.build/coverage/index.html) | [![coverage](https://jslint-org.github.io/jslint/branch.alpha/.build/coverage/coverage-badge.svg)](https://jslint-org.github.io/jslint/branch.alpha/.build/coverage/index.html)| -| Demo | [](https://jslint-org.github.io/jslint/branch.master/index.html) | [](https://jslint-org.github.io/jslint/branch.beta/index.html) | [](https://jslint-org.github.io/jslint/branch.alpha/index.html)| -| Artifacts | [](https://github.com/jslint-org/jslint/tree/gh-pages/branch.master/.build) | [](https://github.com/jslint-org/jslint/tree/gh-pages/branch.beta/.build) | [](https://github.com/jslint-org/jslint/tree/gh-pages/branch.alpha/.build)| +| Demo | [](https://jslint-org.github.io/jslint/branch.master/index.html) | [](https://jslint-org.github.io/jslint/branch.beta/index.html) | [](https://jslint-org.github.io/jslint/branch.alpha/index.html)| +| Artifacts | [](https://github.com/jslint-org/jslint/tree/gh-pages/branch.master/.build) | [](https://github.com/jslint-org/jslint/tree/gh-pages/branch.beta/.build) | [](https://github.com/jslint-org/jslint/tree/gh-pages/branch.alpha/.build)| ## Live Web Demo - [https://jslint-org.github.io/jslint/index.html](https://jslint-org.github.io/jslint/index.html) -[![screenshot](https://jslint-org.github.io/jslint/branch.master/.build/screenshot.browser.%252Findex.html.png)](https://jslint-org.github.io/jslint/index.html) +[![screenshot](https://jslint-org.github.io/jslint/branch.master/.build/screenshot.browser._2findex.html.png)](https://jslint-org.github.io/jslint/index.html) ## Description `jslint.js` contains the jslint function. It parses and analyzes a source file, @@ -51,18 +51,3 @@ This applies to programming as well. Conforming to a consistent style improves readability, and frees you to express yourself in ways that matter. JSLint here plays the part of a stern but benevolent editor, helping you to get the style right so that you can focus your creative energy where it is most needed. - -## Changelog Since v2020.11.6 -- add files .gitconfig, Daley-Bold.woff2, Programma-Bold.woff2, icon-folder-open-solid.svg, icon-window-maximize-regular.svg -- ci - fix http-links after moving to jslint-org -- doc - migrate file README to README.md with embedded ci links and screenshots. -- ci - add macos and windows to ci-matrix. -- ci - ci now fails if jslint-check fails for any of the files in branches. -- ci - add github-workflows to generate code-coverage for jslint.js. -- none - -## Todo -- ci - allow pr to run ci -- doc - add svg package-listing. -- ci - add regression tests and improve code-coverage. -- none diff --git a/ci.sh b/ci.sh index b9eec48ea..25a56e3d1 100755 --- a/ci.sh +++ b/ci.sh @@ -4,7 +4,8 @@ ' shBrowserScreenshot() {(set -e -# this function will screenshot url "$1" with headless-chrome +# this function will run headless-chrome to screenshot url $1 with +# window-size $2 node -e ' // init debugInline if (!globalThis.debugInline) { @@ -41,7 +42,9 @@ if (!globalThis.debugInline) { if (String(file + "/").indexOf(process.cwd() + "/") === 0) { file = file.replace(process.cwd(), ""); } - file = ".build/screenshot.browser." + encodeURIComponent(file); + file = ".build/screenshot.browser." + encodeURIComponent(file).replace(( + /%/g + ), "_").toLowerCase(); process.on("exit", function (exitCode) { if (typeof exitCode === "object" && exitCode) { console.error(exitCode); @@ -67,7 +70,7 @@ if (!globalThis.debugInline) { "--incognito", "--timeout=30000", "--user-data-dir=/dev/null", - "--window-size=800x600", + "--window-size=" + (process.argv[2] || "800x600"), ( extname === ".html" ? "--dump-dom" @@ -112,7 +115,172 @@ if (!globalThis.debugInline) { ); }); }()); -' "$1" # ' +' "$@" # "' +)} + +shCiArtifactUpload() {(set -e +# this function will upload build-artifacts to branch-gh-pages + node -e ' +process.exit( + `${process.version.split(".")[0]}.${process.arch}.${process.platform}` !== + process.env.CI_NODE_VERSION_ARCH_PLATFORM +); +' || return 0 + local BRANCH + # init $BRANCH + BRANCH="$(git rev-parse --abbrev-ref HEAD)" + # init .git/config + git config --local user.email "github-actions@users.noreply.github.com" + git config --local user.name "github-actions" + # update README.md with $GITHUB_REPOSITORY + sed -i \ + -e "s|\bjslint-org/jslint\b|$GITHUB_REPOSITORY|g" \ + -e "s|\bjslint-org\.github\.io/jslint\b|$( + printf "$GITHUB_REPOSITORY" | sed -e "s|/|.github.io/|" + )|g" \ + README.md + # add dir .build + git add -f .build + git commit -am "add dir .build" + # checkout branch-gh-pages + git checkout -b gh-pages + git fetch origin gh-pages + git reset --hard origin/gh-pages + # update dir branch.$BRANCH + rm -rf "branch.$BRANCH" + mkdir "branch.$BRANCH" + (set -e + cd "branch.$BRANCH" + git init -b branch1 + git pull --depth=1 .. "$BRANCH" + rm -rf .git + git add -f . + ) + # update root-dir with branch-master + if [ "$BRANCH" = master ] + then + git rm -rf .build + git checkout master . + fi + git status + git commit -am "update dir branch.$BRANCH" || true + # if branch-gh-pages has more than 100 commits, + # then backup and squash commits + if [ "$(git rev-list --count gh-pages)" -gt 100 ] + then + # backup + shGitCmdWithGithubToken push origin -f gh-pages:gh-pages.backup + # squash commits + git checkout --orphan squash1 + git commit --quiet -am squash || true + # reset branch-gh-pages to squashed-commit + git push . -f squash1:gh-pages + git checkout gh-pages + # force-push squashed-commit + shGitCmdWithGithubToken push origin -f gh-pages + fi + # list files + shGitLsTree + # push branch-gh-pages + shGitCmdWithGithubToken push origin gh-pages + # validate http-links + (set -e + cd "branch.$BRANCH" + sleep 15 + shDirHttplinkValidate + ) +)} + +shCiBase() {(set -e +# this function will run github-ci + # jslint all files + shJslintCli . + # run test with coverage-report + shRunWithCoverage node test.js + # screenshot live-web-demo + shBrowserScreenshot index.html +)} + +shDirHttplinkValidate() {(set -e +# this function will validate http-links embedded in .html and .md files + node -e ' +(function () { + "use strict"; + let dict = {}; + require("fs").readdirSync(".").forEach(async function (file) { + if (!( + /.\.html$|.\.md$/m + ).test(file)) { + return; + } + let data = await require("fs").promises.readFile(file, "utf8"); + data.replace(( + /\bhttps?:\/\/.*?(?:[")\]]|$)/gm + ), function (match0) { + match0 = match0.slice(0, -1).replace(( + /[\u0022\u0027]/g + ), "").replace(( + /\/branch\.\w+?\//g + ), "/branch.alpha/").replace(( + /\bjslint-org\/jslint\b/g + ), process.env.GITHUB_REPOSITORY || "jslint-org/jslint").replace(( + /\bjslint-org\.github\.io\/jslint\b/g + ), String( + process.env.GITHUB_REPOSITORY || "jslint-org/jslint" + ).replace("/", ".github.io/")); + if (match0.indexOf("http://") === 0) { + throw new Error( + "shDirHttplinkValidate - insecure link " + match0 + ); + } + // ignore duplicate-link + if (dict.hasOwnProperty(match0)) { + return ""; + } + dict[match0] = true; + let req = require("https").request(require("url").parse( + match0 + ), function (res) { + console.error( + "shDirHttplinkValidate " + res.statusCode + " " + match0 + ); + if (!(res.statusCode < 400)) { + throw new Error( + "shDirHttplinkValidate - " + file + + " - unreachable link " + match0 + ); + } + req.abort(); + res.destroy(); + }); + req.setTimeout(30000); + req.end(); + return ""; + }); + data.replace(( + /(?:\bhref=|\bsrc=|\burl\().(.*?)(?:[")\]]|$)/gm + ), function (ignore, match1) { + if (!( + /^https?|^mailto:|^[#\/]/m + ).test(match1)) { + require("fs").stat(match1, function (ignore, exists) { + console.error( + "shDirHttplinkValidate " + Boolean(exists) + " " + + match1 + ); + if (!exists) { + throw new Error( + "shDirHttplinkValidate - " + file + + " - unreachable link " + match1 + ); + } + }); + } + return ""; + }); + }); +}()); +' # "' )} shGitCmdWithGithubToken() {(set -e @@ -209,82 +377,7 @@ shGitLsTree() {(set -e }).join("")); }); }()); -' # ' -)} - -shGithubCi() {(set -e -# this function will run github-ci - # jslint all files - shJslintCli . - # create coverage-report - shRunWithCoverage shJslintCli jslint.js - # screenshot live-web-demo - shBrowserScreenshot https://jslint.com/index.html -)} - -shGithubArtifactUpload() {(set -e -# this function will upload build-artifacts to branch-gh-pages - node -e ' -process.exit( - `${process.version.split(".")[0]}.${process.arch}.${process.platform}` !== - process.env.CI_NODE_VERSION_ARCH_PLATFORM -); -' || return 0 - local BRANCH - # init $BRANCH - BRANCH="$(git rev-parse --abbrev-ref HEAD)" - # init .git/config - git config --local user.email "github-actions@users.noreply.github.com" - git config --local user.name "github-actions" - # add dir .build - git add -f .build/ - git commit -am "add dir .build" - # checkout branch-gh-pages - git checkout -b gh-pages - git fetch origin gh-pages - git reset --hard origin/gh-pages - # update dir branch.$BRANCH - rm -rf "branch.$BRANCH" - mkdir "branch.$BRANCH" - (set -e - cd "branch.$BRANCH" - git init -b branch1 - git pull --depth=1 .. "$BRANCH" - rm -rf .git - git add -f . - ) - # update root-dir with branch-master - if [ "$BRANCH" = master ] - then - git checkout master . - fi - git status - git commit -am "update dir branch.$BRANCH" || true - # if branch-gh-pages has more than 100 commits, - # then backup and squash commits - if [ "$(git rev-list --count gh-pages)" -gt 100 ] - then - # backup - shGitCmdWithGithubToken push origin -f gh-pages:gh-pages.backup - # squash commits - git checkout --orphan squash1 - git commit --quiet -am squash || true - # reset branch-gh-pages to squashed-commit - git push . -f squash1:gh-pages - git checkout gh-pages - # force-push squashed-commit - shGitCmdWithGithubToken push origin -f gh-pages - fi - # list files - shGitLsTree - # push branch-gh-pages - shGitCmdWithGithubToken push origin gh-pages - # validate http-links in README.md - (set -e - cd "branch.$BRANCH" - sleep 15 - shReadmeLinkValidate - ) +' # "' )} shJslintCli() {(set -e @@ -607,63 +700,11 @@ async function jslint2({ } process.exit(exitCode); }()); -' --input-type=module "$@" # ' -)} - -shReadmeLinkValidate() {(set -e -# this function will validate http-links embedded in README.md - node -e ' -(function () { - "use strict"; - let dict = {}; - require("fs").readFileSync("README.md", "utf8").replace(( - /[(\[]https?:\/\/.*?[)\]]/g - ), function (match0) { - if (match0.indexOf("http://") === 0) { - throw new Error("shReadmeLinkValidate - insecure link " + match0); - } - match0 = match0.slice(1, -1).replace(( - /[\u0022\u0027]/g - ), "").replace(( - /\/branch\.\w+?\//g - ), "/branch.alpha/").replace(( - /\bjslint-org\/jslint\b/g - ), process.env.GITHUB_REPOSITORY); - // ignore private-link - if ( - process.env.npm_package_private && - match0.indexOf("https://github.com/") === 0 - ) { - return; - } - // ignore duplicate-link - if (dict.hasOwnProperty(match0)) { - return; - } - dict[match0] = true; - let req = require("https").request(require("url").parse( - match0 - ), function (res) { - console.log( - "shReadmeLinkValidate " + res.statusCode + " " + match0 - ); - if (!(res.statusCode < 400)) { - throw new Error( - "shReadmeLinkValidate - unreachable link " + match0 - ); - } - req.abort(); - res.destroy(); - }); - req.setTimeout(30000); - req.end(); - }); -}()); -' # ' +' --input-type=module "$@" # "' )} shRunWithCoverage() {(set -e -# this function will run nodejs command "$@" with v8-coverage and +# this function will run nodejs command $@ with v8-coverage and # create coverage-report .build/coverage/index.html export DIR_COVERAGE=.build/coverage/ rm -rf "$DIR_COVERAGE" @@ -720,7 +761,7 @@ if (!globalThis.debugInline) { ), "&$1"); } html = ""; - html += ` + html += `