From c26414749b2900258f8d010d3db2d2e67c5ff33e Mon Sep 17 00:00:00 2001 From: Alan North Date: Fri, 6 Oct 2023 23:46:58 -0300 Subject: [PATCH] deps: updated template and deps - refactored and remoed path aliases - moved demo to use vite - added github action step for demo --- .eslintrc.cjs | 41 +++ .eslintrc.js | 50 ---- .github/workflows/build-only.yml | 29 +- .github/workflows/build.yml | 12 +- .github/workflows/docs.yml | 25 +- .github/workflows/pull-request.yml | 75 +++++ .github/workflows/release.yml | 85 ++++++ .husky/pre-commit | 2 +- README.md | 2 + demo/.gitignore | 24 ++ demo/index.html | 13 + demo/package.json | 34 +-- demo/{demo.js => src/main.ts} | 22 +- demo/{styles.css => src/style.css} | 0 demo/src/vite-env.d.ts | 1 + demo/tsconfig.json | 23 ++ demo/vite.config.ts | 51 ++++ demo/webpack.config.js | 38 --- docs-src/DEVELOPMENT.md | 10 +- jest.config.js | 38 --- package.json | 264 +++++++++--------- src/ast/builders/array.ts | 16 +- src/ast/builders/condition.ts | 19 +- src/ast/builders/delim.ts | 5 +- src/ast/builders/error.ts | 6 +- src/ast/builders/expression.ts | 19 +- src/ast/builders/group.ts | 20 +- src/ast/builders/index.ts | 22 +- src/ast/builders/isFullPos.ts | 2 +- src/ast/builders/pos.ts | 7 +- src/ast/builders/token.ts | 9 +- src/ast/builders/type.ts | 4 +- src/ast/builders/variable.ts | 34 ++- src/ast/classes/ArrayNode.ts | 16 +- src/ast/classes/Condition.ts | 4 + src/ast/classes/ConditionNode.ts | 25 +- src/ast/classes/ErrorToken.ts | 17 +- src/ast/classes/Expression.ts | 7 +- src/ast/classes/ExpressionNode.ts | 19 +- src/ast/classes/GroupNode.ts | 19 +- src/ast/classes/Node.ts | 21 +- src/ast/classes/Token.ts | 24 +- src/ast/classes/ValidToken.ts | 20 +- src/ast/classes/VariableNode.ts | 21 +- src/ast/classes/index.ts | 22 +- src/ast/handlers.ts | 18 +- src/ast/index.ts | 6 +- src/examples/advancedValueComparer.ts | 2 +- src/examples/shortcutContextParser.ts | 11 +- src/global.d.ts | 2 +- src/grammar/ParserBase.ts | 114 ++++---- src/grammar/createTokens.ts | 10 +- src/grammar/index.ts | 4 +- src/helpers/errors.ts | 13 +- src/helpers/general/applyPrefix.ts | 2 +- .../general/defaultConditionNormalizer.ts | 6 +- src/helpers/general/defaultKeyParser.ts | 4 +- src/helpers/general/defaultPrefixApplier.ts | 4 +- src/helpers/general/defaultValueComparer.ts | 4 +- src/helpers/general/index.ts | 12 +- src/helpers/index.ts | 6 +- src/helpers/parser/assignParents.ts | 10 +- src/helpers/parser/checkParserOpts.ts | 10 +- src/helpers/parser/extractPosition.ts | 2 +- .../parser/getUnclosedRightParenCount.ts | 4 +- src/helpers/parser/index.ts | 16 +- src/helpers/parser/parseParserOptions.ts | 8 +- src/helpers/parser/seal.ts | 7 +- src/index.ts | 10 +- src/methods/autocomplete.ts | 10 +- src/methods/autoreplace.ts | 4 +- src/methods/autosuggest.ts | 25 +- src/methods/evaluate.ts | 10 +- src/methods/getIndexes.ts | 8 +- src/methods/index.ts | 16 +- src/methods/normalize.ts | 23 +- src/methods/validate.ts | 21 +- src/package.js | 1 - src/parser.ts | 44 ++- src/types/ast.ts | 13 +- src/types/autocomplete.ts | 4 +- src/types/errors.ts | 4 +- src/types/index.ts | 9 +- src/types/parser.ts | 6 +- src/utils/extractTokens.ts | 12 +- src/utils/getCursorInfo.ts | 13 +- src/utils/getOppositeDelimiter.ts | 15 +- src/utils/getSurroundingErrors.ts | 8 +- src/utils/index.ts | 18 +- src/utils/isBracket.ts | 2 +- src/utils/isDelimiter.ts | 2 +- src/utils/isParen.ts | 2 +- src/utils/isQuote.ts | 2 +- src/utils/prettyAst.ts | 8 +- tests/{.eslintrc.js => .eslintrc.cjs} | 8 +- tests/array values.spec.ts | 12 +- tests/chai.ts | 8 - ...tosuggest-autocomplete-autoreplace.spec.ts | 16 +- tests/escaping.spec.ts | 12 +- tests/evaluate-validate.spec.ts | 27 +- tests/examples.spec.ts | 6 +- tests/groups.spec.ts | 10 +- tests/helpers.spec.ts | 9 +- tests/indexes.spec.ts | 10 +- tests/negations.spec.ts | 144 +++++----- tests/newFile.ts | 25 ++ tests/optional whitespace.spec.ts | 94 +++---- tests/prefixable values.spec.ts | 10 +- tests/property operators.spec.ts | 18 +- tests/regex values.spec.ts | 11 +- tests/simple expressions.spec.ts | 92 +++--- tests/template.ts | 8 +- tests/utils.spec.ts | 10 +- tests/utils.ts | 19 +- tsconfig.eslint.json | 13 + tsconfig.json | 34 +-- tsconfig.types.json | 21 +- typedoc.config.cjs | 49 ++++ typedoc.config.js | 26 -- vite.config.ts | 70 +++++ 120 files changed, 1511 insertions(+), 1033 deletions(-) create mode 100644 .eslintrc.cjs delete mode 100644 .eslintrc.js create mode 100644 .github/workflows/pull-request.yml create mode 100644 .github/workflows/release.yml create mode 100644 demo/.gitignore create mode 100644 demo/index.html rename demo/{demo.js => src/main.ts} (91%) rename demo/{styles.css => src/style.css} (100%) create mode 100644 demo/src/vite-env.d.ts create mode 100644 demo/tsconfig.json create mode 100644 demo/vite.config.ts delete mode 100644 demo/webpack.config.js delete mode 100644 jest.config.js rename tests/{.eslintrc.js => .eslintrc.cjs} (52%) delete mode 100644 tests/chai.ts create mode 100644 tests/newFile.ts create mode 100644 tsconfig.eslint.json create mode 100644 typedoc.config.cjs delete mode 100644 typedoc.config.js create mode 100644 vite.config.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..e03a6cb --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,41 @@ +/** @type {import('@typescript-eslint/utils').TSESLint.Linter.Config} */ +module.exports = { + root: true, + extends: [ + // https://github.com/AlansCodeLog/eslint-config + "@alanscodelog/eslint-config", + ], + // for vscode, so it doesn't try to lint files in here when we open them + ignorePatterns: [ + "coverage", + "dist", + "docs", + ], + rules: { + }, + settings: { + jsdoc: { + mode: "typescript", + }, + }, + parserOptions: { + project: "./tsconfig.eslint.json", + }, + overrides: [ + { + files: ["./*.{js,cjs,ts,vue}"], + rules: { + "@typescript-eslint/explicit-function-return-type": "off", + } + } + // Eslint: https://eslint.org/docs/rules/ + // Typescript: https://typescript-eslint.io/rules/ + // Vue: https://eslint.vuejs.org/rules/ + // { + // files: ["**/*.js", "**/*.ts", "**/*.vue"], + // rules: { + // }, + // }, + ], +} + diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 0d3c072..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,50 +0,0 @@ -module.exports = { - root: true, - extends: [ - // https://github.com/AlansCodeLog/my-eslint-config - // extends: - // ./node_modules/@alanscodelog/eslint-config/js.js - // prev + ./node_modules/@alanscodelog/eslint-config/typescript.js (default) - "@alanscodelog/eslint-config", - ], - // for vscode, so it doesn't try to lint files in here when we open them - ignorePatterns: [ - "coverage", - "dist", - "docs", - ], - rules: { - }, - // 🟠 - I like to toggle these on occasionally, but otherwise keep off - overrides: [ - // Eslint: https://eslint.org/docs/rules/ - { files: ["bin/*.js"], parserOptions: { sourceType: "script" } }, - { - files: ["**/*.js", "**/*.ts"], - rules: { - // "import/no-unused-modules": [ "warn", { unusedExports: true, missingExports: false }] // 🟠 - // CAREFUL: the auto fix for this one is dangerous and can remove documentation if just added to a project that has errors for it - // "jsdoc/empty-tags": "warn", // 🟠 - }, - }, - // Typescript: https://github.com/typescript-eslint/typescript-eslint/master/packages/eslint-plugin#supported-rules - { - files: ["**/*.ts"], - rules: { - // "@typescript-eslint/strict-boolean-expressions": ["warn", {allowNullableBoolean: true}], // 🟠 - // "@typescript-eslint/no-unnecessary-condition": "warn", // 🟠 - // "@typescript-eslint/no-confusing-void-expression": "warn", // 🟠 - "@typescript-eslint/typedef": ["warn", { - arrowParameter: false, - arrayDestructuring: false, - objectDestructuring: false, - variableDeclaration: false, - variableDeclarationIgnoreFunction: false, - memberVariableDeclaration: true, - parameter: false, - propertyDeclaration: true, - }], - }, - }, - ], -} diff --git a/.github/workflows/build-only.yml b/.github/workflows/build-only.yml index c7f6d73..3928183 100644 --- a/.github/workflows/build-only.yml +++ b/.github/workflows/build-only.yml @@ -3,16 +3,16 @@ name: Build-Only # does not use cache env: - USE_LOCKFILE: false + USE_LOCKFILE: ${{ secrets.USE_LOCKFILE }} on: push: - branches: [ build ] + branches: [ build, experimental ] repository_dispatch: types: [ build-only ] jobs: - build-only: + build: runs-on: ubuntu-latest strategy: matrix: @@ -33,18 +33,35 @@ jobs: id: pnpm-install with: version: latest + + - name: Get Pnpm Cache Path + id: pnpm-cache + run: | + echo "::set-output name=dir::$(pnpm store path)" + + - uses: actions/cache@v3 + name: pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - run: "echo Cache Key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}" + - run: "echo Cache Restore-Keys: ${{ runner.os }}-pnpm-store-" + - run: "echo Pnpm Cache Hit: ${{ steps.pnpm-cache.outputs.cache-hit }}" # regionend # region Steps - run: pnpm install --frozen-lockfile if: "env.USE_LOCKFILE == 'true'" - - run: pnpm install - if: "env.USE_LOCKFILE == 'false'" + - run: pnpm install --no-lockfile + if: "env.USE_LOCKFILE != 'true'" - run: pnpm build - - run: pnpm lint:eslint # test command will lint types + - run: pnpm lint - run: pnpm test # regionend diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d53e876..304b9c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,7 @@ name: Build # not technically necessary because release also runs tests but this way the build badge is separate env: - USE_LOCKFILE: false + USE_LOCKFILE: ${{ secrets.USE_LOCKFILE }} on: push: @@ -35,13 +35,11 @@ jobs: version: latest - name: Get Pnpm Cache Path - if: "env.USE_LOCKFILE == 'true'" id: pnpm-cache run: | echo "::set-output name=dir::$(pnpm store path)" - uses: actions/cache@v3 - if: "env.USE_LOCKFILE == 'true'" name: pnpm cache with: path: ${{ steps.pnpm-cache.outputs.dir }} @@ -58,14 +56,12 @@ jobs: - run: pnpm install --frozen-lockfile if: "env.USE_LOCKFILE == 'true'" - - run: pnpm install - if: "env.USE_LOCKFILE == 'false'" - - - run: pnpm install + - run: pnpm install --no-lockfile + if: "env.USE_LOCKFILE != 'true'" - run: pnpm build - - run: pnpm lint:eslint # test command will lint types + - run: pnpm lint - run: pnpm test # regionend diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d101ba7..983da1d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,7 +1,8 @@ name: Docs env: - USE_LOCKFILE: false + USE_LOCKFILE: ${{ secrets.USE_LOCKFILE }} + ENABLE_DOCS: ${{ secrets.ENABLE_DOCS }} on: push: @@ -34,13 +35,11 @@ jobs: version: latest - name: Get Pnpm Cache Path - if: "env.USE_LOCKFILE == 'true'" id: pnpm-cache run: | echo "::set-output name=dir::$(pnpm store path)" - uses: actions/cache@v3 - if: "env.USE_LOCKFILE == 'true'" name: pnpm cache with: path: ${{ steps.pnpm-cache.outputs.dir }} @@ -53,23 +52,35 @@ jobs: - run: "echo Pnpm Cache Hit: ${{ steps.pnpm-cache.outputs.cache-hit }}" # regionend - # region Steps - run: pnpm install --frozen-lockfile if: "env.USE_LOCKFILE == 'true'" - - run: pnpm install + - run: pnpm install --no-lockfile + if: "env.USE_LOCKFILE != 'true'" - run: pnpm build + - run: pnpm lint + + - run: pnpm test + + - run: pnpm install --frozen-lockfile + working-directory: demo + + - run: pnpm demo:build + - run: pnpm doc - name: Documentation - # TOCONFIGURE - if: "env.REMOVE_LINE_TO_ENABLE == 'true'" + if: "env.ENABLE_DOCS == 'true'" uses: crazy-max/ghaction-github-pages@v2 with: + jekyll: false target_branch: gh-pages build_dir: docs env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - run: echo "env.ENABLE_DOCS is ${{ env.ENABLE_DOCS }}, no documentation can be published" && exit 1 + if: "env.ENABLE_DOCS != 'true'" # regionend diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000..7ca0b72 --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,75 @@ +name: Pull Request Checks + +env: + USE_LOCKFILE: ${{ secrets.USE_LOCKFILE }} + +on: + pull_request: + branches: [ master, alpha, beta ] + +jobs: + pull-request: + if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')" + runs-on: ubuntu-latest + strategy: + matrix: + node-version: ["lts/*", "latest"] + + steps: + + # region Setup + - uses: actions/checkout@v2 + + - name: Setting Up Node.js (${{ matrix.node-version }}) + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - uses: pnpm/action-setup@v2.0.1 + name: Install pnpm + id: pnpm-install + with: + version: latest + + - name: Get Pnpm Cache Path + id: pnpm-cache + run: | + echo "::set-output name=dir::$(pnpm store path)" + + - uses: actions/cache@v3 + name: pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - run: "echo Cache Key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}" + - run: "echo Cache Restore-Keys: ${{ runner.os }}-pnpm-store-" + - run: "echo Pnpm Cache Hit: ${{ steps.pnpm-cache.outputs.cache-hit }}" + # regionend + + # region Steps + - run: pnpm install --frozen-lockfile + if: "env.USE_LOCKFILE == 'true'" + + - run: pnpm install --no-lockfile + if: "env.USE_LOCKFILE != 'true'" + + - name: Commits to Lint + run: git log ${{github.event.pull_request.base.sha}}..${{github.event.pull_request.head.sha}} --graph --abbrev-commit --decorate --format=format:'%h%d%n%s (%cr) - %an (%ae)%n%b' + + - name: Lint Commits + run: yarn commitlint --from ${{github.event.pull_request.base.sha}} --to ${{github.event.pull_request.head.sha}} + + - run: pnpm build + + - run: pnpm lint + + - run: pnpm coverage + + - name: Coverage + uses: romeovs/lcov-reporter-action@v0.2.16 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + # regionend diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..229cf46 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,85 @@ +name: Release + +env: + USE_LOCKFILE: ${{ secrets.USE_LOCKFILE }} + ENABLE_RELEASE: ${{ secrets.ENABLE_RELEASE }} + +on: + push: + branches: [ master, alpha, beta ] + repository_dispatch: + types: [ release ] + +jobs: + release: + if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]') && ! contains(toJSON(github.event.commits.*.message), '(no-release)')" + runs-on: ubuntu-latest + strategy: + matrix: + node-version: ["lts/*"] + + steps: + + # region Setup + - uses: actions/checkout@v2 + + - name: Setting Up Node.js (${{ matrix.node-version }}) + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + + - uses: pnpm/action-setup@v2.0.1 + name: Install pnpm + id: pnpm-install + with: + version: latest + + - name: Get Pnpm Cache Path + id: pnpm-cache + run: | + echo "::set-output name=dir::$(pnpm store path)" + + - uses: actions/cache@v3 + name: pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - run: "echo Cache Key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}" + - run: "echo Cache Restore-Keys: ${{ runner.os }}-pnpm-store-" + - run: "echo Pnpm Cache Hit: ${{ steps.pnpm-cache.outputs.cache-hit }}" + # regionend + + # region Steps + - run: pnpm install --frozen-lockfile + if: "env.USE_LOCKFILE == 'true'" + + - run: pnpm install + if: "env.USE_LOCKFILE != 'true'" + + - run: pnpm build + + - run: pnpm lint:eslint # test command will lint types + + - run: pnpm test + + - name: Release + if: "env.ENABLE_RELEASE == 'true'" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release + + - name: Release Dry Run + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release --dry-run + if: "env.ENABLE_RELEASE != 'true'" + + + - run: echo "env.ENABLE_RELEASE is ${{ env.ENABLE_RELEASE }}, no release can be published" && exit 1 + if: "env.ENABLE_RELEASE != 'true'" + # regionend diff --git a/.husky/pre-commit b/.husky/pre-commit index f9aeed5..6e05f77 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -3,4 +3,4 @@ echo "Running pre-commit hook" -npm run build && npm run lint && npm run test -- --no-cache +npm run build && npm run lint && npm run test diff --git a/README.md b/README.md index ece7f55..ff962ce 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Expressit is blazing fast, customizable, error-tolerant expression parser that creates safe to eval expressions + a few other goodies. # [Docs](https://alanscodelog.github.io/expressit) +# [Demo](https://alanscodelog.github.io/expressit/demo) + # Features - **Error Recovery** - The parser is designed to recover from ALL errors, even **multiple** errors, making it easy to provide things like syntax highlighting. diff --git a/demo/.gitignore b/demo/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/demo/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..44a9335 --- /dev/null +++ b/demo/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + TS + + +
+ + + diff --git a/demo/package.json b/demo/package.json index 5925748..f756e3b 100644 --- a/demo/package.json +++ b/demo/package.json @@ -1,19 +1,19 @@ { - "name": "demo", - "version": "0.0.0", - "description": "", - "private": "true", - "main": "demo.js", - "scripts": { - "dev": "npx webpack-cli serve --mode development" - }, - "devDependencies": { - "css-loader": "^5.0.1", - "html-webpack-plugin": "^4.5.1", - "mini-css-extract-plugin": "^1.3.4", - "style-loader": "^2.0.0", - "webpack": "^5.15.0", - "webpack-cli": "^4.3.1", - "webpack-dev-server": "^3.11.2" - } + "name": "demo2", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.0.2", + "vite": "^4.4.5", + "expressit": "file:../" + }, + "dependencies": { + "@alanscodelog/utils": "4.0.0-beta.11" + } } diff --git a/demo/demo.js b/demo/src/main.ts similarity index 91% rename from demo/demo.js rename to demo/src/main.ts index a0a0179..d9f0c77 100644 --- a/demo/demo.js +++ b/demo/src/main.ts @@ -1,12 +1,12 @@ /* eslint-disable no-eval */ /* eslint-disable no-restricted-imports */ -import "./styles.css" +import "./style.css" -import { crop } from "../../UTILS/my-utils/dist" -import { parseParserOptions } from "../dist/helpers/parser" -import { prettyAst } from "../dist/utils" +import { crop } from "@alanscodelog/utils" +import { parseParserOptions } from "expressit/helpers/parser/index.js" +import { prettyAst } from "expressit/utils" -import { Parser } from ".." +import { Parser } from "expressit" const body = document.body @@ -128,11 +128,10 @@ function onKeyboardInput(e, force = false) {
${entry.type}
${entry.isError ? `
${entry.isError}
` : "
"} -
${ - typeof entry.range === "string" +
${typeof entry.range === "string" ? entry.range - : `[${entry.range.start}, ${entry.range.end}]` - }
+ : `[${entry.range.start}, ${entry.range.end}]` + }
`) .join("\n") @@ -160,8 +159,7 @@ function onKeyboardInput(e, force = false) { const str = typeof replacement === "string" ? replacement : `${escapeHtml(replacement.replacement.slice(0, replacement.cursor)) - }|${ - escapeHtml(replacement.replacement.slice(replacement.cursor))}` + }|${escapeHtml(replacement.replacement.slice(replacement.cursor))}` const res = crop`
@@ -170,7 +168,7 @@ function onKeyboardInput(e, force = false) {
` return res -}).join("\n") + }).join("\n") els.completion.innerHTML = str2 } } diff --git a/demo/styles.css b/demo/src/style.css similarity index 100% rename from demo/styles.css rename to demo/src/style.css diff --git a/demo/src/vite-env.d.ts b/demo/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/demo/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/demo/tsconfig.json b/demo/tsconfig.json new file mode 100644 index 0000000..e338064 --- /dev/null +++ b/demo/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/demo/vite.config.ts b/demo/vite.config.ts new file mode 100644 index 0000000..9781aa0 --- /dev/null +++ b/demo/vite.config.ts @@ -0,0 +1,51 @@ + +// import vue from "@vitejs/plugin-vue" +import tsconfigPaths from "vite-tsconfig-paths" +import { defineConfig } from "vitest/config" + +// import postcss from "./postcss.config.js" + +import pkg from "../package.json" + +// https://vitejs.dev/config/ +export default async ({ mode }: { mode: string }) => defineConfig({ + plugins: [ + // tsconfigPaths(), + // vue({ + // script: { + // defineModel: true, + // }, + // }), + ], + base: `/${pkg.name}/demo`, + build: { + outDir: "dist", + ...(mode === "production" ? { + minify: true, + } : { + minify: false, + sourcemap: "inline", + }), + }, + resolve: { + // getting duplicate imports otherwise i think because of pnpm + // https://vitejs.dev/config/shared-options.html#resolve-dedupevite + dedupe: ["@alanscodelog/utils"], + }, + + server: { + // for locally linked repos when using vite server (i.e. not needed for libraries) + fs: { + allow: [...(process.env.CODE_PROJECTS ?? [])!], + }, + watch: { + // for pnpm + followSymlinks: true, + // watch changes in linked repos + ignored: ["!**/node_modules/@alanscodelog/**"], + }, + }, + css: { + // postcss, + }, +}) diff --git a/demo/webpack.config.js b/demo/webpack.config.js deleted file mode 100644 index 426d083..0000000 --- a/demo/webpack.config.js +++ /dev/null @@ -1,38 +0,0 @@ -const HtmlWebpackPlugin = require("html-webpack-plugin") -const MiniCssExtractPlugin = require("mini-css-extract-plugin") -const path = require("path") -const webpack = require("webpack") - - -module.exports = { - entry: "./demo.js", - devServer: { - contentBase: "./dist", - host: "0.0.0.0", - }, - output: { - filename: "[name].bundle.js", - path: path.resolve(__dirname, "dist"), - // see https://github.com/webpack/webpack/issues/11660 - chunkLoading: false, - wasmLoading: false, - }, - plugins: [ - new HtmlWebpackPlugin(), - ], - resolve: { - fallback: { - util: false, - child_process: false, - path: false, - }, - }, - module: { - rules: [ - { - test: /\.css$/i, - use: ["style-loader", "css-loader"], - }, - ], - }, -} diff --git a/docs-src/DEVELOPMENT.md b/docs-src/DEVELOPMENT.md index 7c6c327..005edb7 100644 --- a/docs-src/DEVELOPMENT.md +++ b/docs-src/DEVELOPMENT.md @@ -8,7 +8,7 @@ Every function normally has it's own file and there should only be one export pe The only exception is the handlers for the parser rules. These are internal, short, easier to maintain in one file, and used like `import * as handle`. -``` +```text src ┣ ast ┃ ┣ builders - used to quickly build ast classes for testing @@ -30,15 +30,7 @@ src ┣ package.js - see file for explanation ┗ parser.ts - the root / main export of the project. all it's longer methods are in the ./methods folder tests - ┣ chai.ts - imports & re-exports retyped chai + plugins ┣ template.ts - the template to use for tests, just copy and rename to the name of the test + `.spec.ts` ┗ utils.ts - contains even shorter (one letter) versions of the ast/builders for the most common uses ``` -## Building - -Run `yarn build` to build the library and the types. If you don't need to build the types you can use the `build:babel` or `build:babel:watch` commands. - -# Other - -`@utils/*` imports are an alias to my utils library [`@alanscodelog/utils`](https://github.com/AlansCodeLog/my-utils). diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 190ec72..0000000 --- a/jest.config.js +++ /dev/null @@ -1,38 +0,0 @@ -// https://jestjs.io/docs/en/configuration.html - - -/** @type {import('@jest/types').Config.InitialOptions} */ -module.exports = { - // this will remove jsdom, which has an issue with node 10 (https://github.com/jsdom/jsdom/issues/2961) - // it also makes tests faster - testEnvironment: "node", - moduleFileExtensions: [ - "ts", - "js", - "json", - ], - transform: { - "^.+\\.(ts|js)$": "babel-jest", - }, - transformIgnorePatterns: [ - "/node_modules/", - ], - testMatch: [ - "**/tests/**/*.spec.(js|ts)|**/__tests__/*.(js|ts)", - ], - testEnvironmentOptions: { - url: "http://localhost/", - }, - watchPlugins: [ - "jest-watch-typeahead/filename", - "jest-watch-typeahead/testname", - ], - collectCoverageFrom: [ - "**/src/**/*.ts", - "!**/node_modules/**", - ], - coveragePathIgnorePatterns: [ - ".*?/index.ts", - ], - coverageDirectory: "coverage", -} diff --git a/package.json b/package.json index d89ae34..4463406 100644 --- a/package.json +++ b/package.json @@ -1,125 +1,139 @@ -{ - "name": "expressit", - "description": "A blazing fast, customizable, error-tolerant expression parser that creates safe to eval expressions + a few other goodies.", - "version": "0.0.0-semantically-released", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "scripts": { - "babel:run": "babel-node --extensions \".ts,.js\" --", - "babel:run:dev": "onchange -i \"src/**/*.ts\" -- babel-node --extensions \".ts,.js\" --", - - "build:babel": "babel --extensions \".ts,.js\" src --out-dir dist --source-maps inline", - "build:watch": "npm run build:babel -- --watch", - "build:clean": "rm -rf dist && npm run build", - "build:types": "tsc -p tsconfig.types.json && dts-alias -p tsconfig.types.json", - "build": "npm run build:babel && npm run build:types", - - "demo:serve": "cd demo && npx webpack-cli serve --mode development", - - "lint:eslint": "npx eslint \"{src,tests}/**/*.{js,ts}\" \"*.{js,ts}\" --max-warnings=0 --report-unused-disable-directives", - "lint:types": "tsc --noEmit --pretty", - "lint:commits": "commitlint --from $(git rev-list HEAD --not --remotes | tail -1)^ --to HEAD --verbose", - "lint": "npm run lint:types && npm run lint:eslint", - - "coverage": "npm run test -- --coverage", - "coverage:dev": "concurrently \"http-server coverage/lcov-report --port=5000\" \"onchange -k -i \\\"src/**/*.ts\\\" \\\"jest.config.js\\\" -- npm run coverage -- --watch\"", - - "test": "npm run lint:types && jest test --verbose", - "test:debug": "node --inspect-brk node_modules/jest/bin/jest --verbose", - - "doc": "typedoc --options typedoc.config.js", - "doc:build": "onchange -i \"src/**/*.ts\" \"typedoc.config.js\" -- npm run doc", - "doc:serve": "http-server docs --port=5001", - "doc:dev": "concurrently \"npm run doc:build\" \"npm run doc:serve\"", - "doc:check-invalid": "typedoc --options typedoc.config.js --listInvalidSymbolLinks", - "doc:check-missing": "rg \"@packageDocumentation @module\" --files-without-match -g \"*.ts\" -g \"!*.spec.ts\" -g \"!tests/**/*\" -g \"!src/index.ts\"", - - "actions:debug": "act -r -v -j build-only", - - "gen:exports": "npx indexit update -i src/package.js src/functions/ast/handlers.ts **.d.ts", - - "prepare": "npm run build && husky install" - }, - "husky": { - "hooks": { - "pre-commit": "npm run build && npm run lint && npm run test -- --no-cache", - "pre-push": "npm run lint:commits" - } - }, - "dependencies": { - "@alanscodelog/utils": "^3.2.0", - - "core-js": "^3.22.5", - "chevrotain":"^10.1.2" - }, - "devDependencies": { - "@types/node": "^17.0.33", - - "semantic-release": "^19.0.2", - "@semantic-release/changelog": "^6.0.1", - "@semantic-release/commit-analyzer": "^9.0.2", - "@semantic-release/github": "^8.0.4", - "@semantic-release/npm": "^9.0.1", - "@semantic-release/release-notes-generator": "^10.0.3", - "conventional-changelog-conventionalcommits": "^4.6.3", - "@alanscodelog/semantic-release-config": "^2.0.0", - "@alanscodelog/commitlint-config": "^2.0.0", - "commitlint": "^16.3.0", - - "@babel/cli": "^7.17.10", - "@babel/core": "^7.17.10", - "@babel/node": "^7.17.10", - "@babel/preset-env": "^7.17.10", - "@babel/preset-typescript": "^7.16.7", - "@babel/plugin-proposal-export-namespace-from": "^7.16.7", - "@babel/plugin-proposal-class-properties": "^7.16.7", - "babel-plugin-module-resolver": "^4.1.0", - "@alanscodelog/babel-preset": "^2.0.0", - - "eslint": "^8.15.0", - "eslint-import-resolver-typescript": "^2.7.1", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-simple-import-sort": "^7.0.0", - "eslint-plugin-jsdoc":"^39.2.9", - "@typescript-eslint/eslint-plugin": "^5.23.0", - "@typescript-eslint/parser": "^5.23.0", - "@alanscodelog/eslint-config": "^3.0.1", - - "chai": "^4.3.6", - "jest": "^28.1.0", - "jest-watch-typeahead": "^1.1.0", - "@types/chai": "^4.3.1", - "@types/jest": "^27.5.1", - "typedoc": "^0.22.15", - - "typescript": "^4.6.4", - "@alanscodelog/tsconfigs": "^3.0.0", - "dts-alias": "^1.0.5", - - "husky": "^8.0.1", - "indexit": "^2.0.1", - "onchange": "^7.1.0", - "concurrently": "^7.1.0", - "http-server": "^14.1.0" - }, - "author": "Alan ", - "repository": "https://github.com/alanscodelog/boolean-expressions-parser", - "license": "MIT", - "files": [ - "src", - "dist" - ], - "release": { "extends": [ "@alanscodelog/semantic-release-config" ] }, - "commitlint": { "extends": [ "@alanscodelog" ] }, - "babel": { "presets": [ "@alanscodelog" ] }, - "browserslist":"> 0.5%, last 2 versions, not dead, not < 0.25%, not IE > 0, maintained node versions", - "engines": { "node": ">=14.0.0" }, - "@comments": { - "scripts": { - "lint:commits": "Lints all unpushed commits in the active branch.", - "prepare": "Needed so that if we pull the package from git it will get built and installed properly.", - "actions:debug": "For debugging github build action locally with nektos/act. Requires act and docker. Note: Cache will never work locally because of https://github.com/nektos/act/issues/285" - } - }, - "private": true -} +{ + "name": "expressit", + "description": "A blazing fast, customizable, error-tolerant expression parser that creates safe to eval expressions + a few other goodies.", + "version": "0.0.0-semantically-released", + "types": "./dist/index.d.ts", + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./ast": { + "types": "./dist/ast/index.d.ts", + "import": "./dist/ast/index.js" + }, + "./grammar": { + "types": "./dist/grammar/index.d.ts", + "import": "./dist/grammar/index.js" + }, + "./helpers": { + "types": "./dist/helpers/index.d.ts", + "import": "./dist/helpers/index.js" + }, + "./methods": { + "types": "./dist/methods/index.d.ts", + "import": "./dist/methods/index.js" + }, + "./types": { + "types": "./dist/types/index.d.ts", + "import": "./dist/types/index.js" + }, + "./utils": { + "types": "./dist/utils/index.d.ts", + "import": "./dist/utils/index.js" + }, + "./examples": { + "types": "./dist/examples/index.d.ts", + "import": "./dist/examples/index.js" + }, + "./*": { + "types": "./dist/*", + "import": "./dist/*" + } + }, + "scripts": { + "debug": "ts-node -r tsconfig-paths/register -T --esm", + "build": "vite build", + "build:dev": "vite build --mode development", + "build:watch": "vite build --watch --mode production", + "build:types": "tsc --emitDeclarationOnly -p tsconfig.types.json && npm run build:types:fix", + "build:types:fix": "tsc-alias -p tsconfig.types.json --debug", + "lint:eslint": "eslint \"{src,tests,bin}/**/*.{cjs,js,ts}\" \"*.{cjs,js,ts}\" --max-warnings=0 --report-unused-disable-directives", + "lint:types": "tsc --noEmit --pretty", + "lint:commits": "commitlint --from $(git rev-list --max-parents=0 HEAD) --to HEAD --verbose", + "lint:imports": "madge --circular --extensions ts ./src", + "lint": "npm run lint:types && npm run lint:eslint", + "coverage": "vitest --coverage", + "coverage:dev": "vitest --watch --coverage", + "test": "npm run lint:types && vitest run", + "test:watch": "vitest --watch", + "test:inspect-errors": "cross-env INSPECT_ERRORS=true npm run test", + "doc": "typedoc --options typedoc.config.cjs", + "doc:watch": "onchange -i \"src/**/*.ts\" \"typedoc.config.cjs\" -- npm run doc", + "doc:serve": "http-server docs --port=5001", + "doc:dev": "concurrently \"npm run doc:watch\" \"npm run doc:serve\"", + "doc:check-invalid": "typedoc --options typedoc.config.cjs --listInvalidSymbolLinks", + "actions:debug": "act -r -v -j build", + "gen:exports": "indexit update -o '${path}.js' -i **/*.d.ts", + "prepare": "husky install && npm run build" + }, + "dependencies": { + "@alanscodelog/utils": "^4.0.0-beta.11", + "chevrotain": "^11.0.3" + }, + "devDependencies": { + "@alanscodelog/commitlint-config": "^2.0.0", + "@alanscodelog/eslint-config": "^4.0.3", + "@alanscodelog/semantic-release-config": "^3.0.0", + "@alanscodelog/tsconfigs": "^3.2.0", + "@knodes/typedoc-plugin-pages": "^0.23.4", + "@types/node": "^20.4.1", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "@vitest/coverage-c8": "^0.33.0", + "commitlint": "^17.6.6", + "concurrently": "^8.2.0", + "cross-env": "^7.0.3", + "eslint": "^8.44.0", + "eslint-import-resolver-typescript": "^3.5.5", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jsdoc": "^46.4.3", + "eslint-plugin-simple-import-sort": "^10.0.0", + "fast-glob": "^3.3.1", + "http-server": "^14.1.1", + "husky": "^8.0.3", + "indexit": "2.1.0-beta.3", + "madge": "^6.1.0", + "onchange": "^7.1.0", + "semantic-release": "^22.0.5", + "ts-node": "^10.9.1", + "tsc-alias": "^1.8.7", + "typedoc": "~0.23.1", + "typescript": "~5.0.0", + "vite": "^4.4.2", + "vite-plugin-externalize-deps": "^0.7.0", + "vite-tsconfig-paths": "^4.2.0", + "vitest": "^0.34.6" + }, + "author": "Alan ", + "repository": "https://github.com/alanscodelog/expressit", + "license": "MIT", + "files": [ + "src", + "dist" + ], + "release": { + "extends": [ + "@alanscodelog/semantic-release-config" + ] + }, + "commitlint": { + "extends": [ + "@alanscodelog" + ] + }, + "browserslist": "defaults and supports es6-module,maintained node versions", + "engines": { + "node": ">=18.0.0" + }, + "@comments": { + "scripts": { + "test": "Runs `lint:types` before (so that flags can be passed to the test command) so that we can test type assertions. See expect_type function in @alanscodelog/utils.", + "lint:commits": "Lints all unpushed commits in the active branch.", + "prepare": "Needed so that if we pull the package from git it will get built and installed properly.", + "actions:debug": "For debugging github build action locally with nektos/act. Requires act and docker. Note: Cache will never work locally because of https://github.com/nektos/act/issues/285" + } + }, + "private": true +} diff --git a/src/ast/builders/array.ts b/src/ast/builders/array.ts index 0e8af8f..ef6ca65 100644 --- a/src/ast/builders/array.ts +++ b/src/ast/builders/array.ts @@ -1,10 +1,10 @@ -import type { Mutable } from "@utils/types" +import type { Mutable } from "@alanscodelog/utils" -import { token } from "./token" +import { token } from "./token.js" -import type { VariableNode } from "@/ast/classes" -import { ArrayNode } from "@/ast/classes/ArrayNode" -import { AST_TYPE, Position, TOKEN_TYPE } from "@/types" +import { AST_TYPE, type Position, TOKEN_TYPE } from "../../types/ast.js" +import { ArrayNode } from "../classes/ArrayNode.js" +import type { VariableNode } from "../classes/VariableNode.js" export function array( @@ -24,8 +24,8 @@ export function array( const end = values[values.length - 1]?.end ?? parenRightPos?.start ?? parenLeftPos?.end - parenLeftPos = parenLeftPos ?? (start !== undefined ? { start: start - 1, end: start } : undefined) - parenRightPos = parenRightPos ?? (end !== undefined ? { start: end, end: end + 1 } : undefined) + parenLeftPos ??= (start !== undefined ? { start: start - 1, end: start } : undefined) + parenRightPos ??= (end !== undefined ? { start: end, end: end + 1 } : undefined) // is always valid for now node.bracket!.left = token(TOKEN_TYPE.BRACKETL, "[", parenLeftPos) @@ -33,7 +33,7 @@ export function array( if (bracket?.right) { node.bracket!.right = token(TOKEN_TYPE.BRACKETR, "]", parenRightPos) } else { - if (parenRightPos) {parenRightPos.end = parenRightPos.start} + if (parenRightPos) { parenRightPos.end = parenRightPos.start } node.bracket!.right = token(TOKEN_TYPE.BRACKETR, undefined, parenRightPos) } diff --git a/src/ast/builders/condition.ts b/src/ast/builders/condition.ts index eb0ca42..6b6b0f0 100644 --- a/src/ast/builders/condition.ts +++ b/src/ast/builders/condition.ts @@ -1,8 +1,12 @@ -import { pos } from "./pos" - -import { ArrayNode, ConditionNode, ErrorToken, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import { AnyToken, AST_TYPE, TOKEN_TYPE } from "@/types" +import { pos } from "./pos.js" +import { type AnyToken, type Position, type TOKEN_TYPE } from "../../types/ast.js" +import type { ArrayNode } from "../classes/ArrayNode.js" +import { ConditionNode } from "../classes/ConditionNode.js" +import type { ErrorToken } from "../classes/ErrorToken.js" +import type { GroupNode } from "../classes/GroupNode.js" +import type { ValidToken } from "../classes/ValidToken.js" +import type { VariableNode } from "../classes/VariableNode.js" /** * Creates a @see ConditionNode @@ -27,12 +31,11 @@ export function condition( propertyOperator?: AnyToken, { right, left }: Partial>> = { } ): ConditionNode { - const position = pos(value) + const position = pos(value satisfies Position) const notStart = not === true ? undefined : not.start position.start = notStart ?? property?.start ?? propertyOperator?.start ?? position.start - const node: Partial = { - type: AST_TYPE.CONDITION, + const node: Partial[0]> = { property, value, propertyOperator, @@ -40,11 +43,9 @@ export function condition( } if (not !== true) { - // @ts-expect-error ignore readonly node.operator = not } if (right || left) { - // @ts-expect-error ignore readonly node.sep = {} if (right) node.sep.right = right if (left) node.sep.left = left diff --git a/src/ast/builders/delim.ts b/src/ast/builders/delim.ts index ccfb100..e0e35b6 100644 --- a/src/ast/builders/delim.ts +++ b/src/ast/builders/delim.ts @@ -1,7 +1,6 @@ -import { type } from "./type" - -import { ExtractTokenType, TOKEN_TYPE } from "@/types" +import { type } from "./type.js" +import { type ExtractTokenType, TOKEN_TYPE } from "../../types/ast.js" /** * Faster way, more intuitive way to generate the options for matching delimiters (e.g. quotes and parens) for functions like @see variable and @see group . diff --git a/src/ast/builders/error.ts b/src/ast/builders/error.ts index 9cb731f..eaa363d 100644 --- a/src/ast/builders/error.ts +++ b/src/ast/builders/error.ts @@ -1,7 +1,7 @@ -import { type } from "./type" +import { type } from "./type.js" -import { ErrorToken } from "@/ast/classes" -import { TOKEN_TYPE } from "@/types" +import { TOKEN_TYPE } from "../../types/ast.js" +import { ErrorToken } from "../classes/ErrorToken.js" /** diff --git a/src/ast/builders/expression.ts b/src/ast/builders/expression.ts index 95ebf5b..51853cc 100644 --- a/src/ast/builders/expression.ts +++ b/src/ast/builders/expression.ts @@ -1,8 +1,11 @@ -import { pos } from "./pos" -import { token } from "./token" +import { pos } from "./pos.js" +import { token } from "./token.js" -import { ConditionNode, ErrorToken, ExpressionNode, GroupNode } from "@/ast/classes" -import { AnyToken, AST_TYPE, EmptyObj, Position, TOKEN_TYPE, TokenBooleanTypes } from "@/types" +import { type AnyToken, type Position, TOKEN_TYPE, type TokenBooleanTypes } from "../../types/ast.js" +import type { ConditionNode } from "../classes/ConditionNode.js" +import type { ErrorToken } from "../classes/ErrorToken.js" +import { ExpressionNode } from "../classes/ExpressionNode.js" +import type { GroupNode } from "../classes/GroupNode.js" /** @@ -10,7 +13,6 @@ import { AnyToken, AST_TYPE, EmptyObj, Position, TOKEN_TYPE, TokenBooleanTypes } * * Also automatically sets the correct start/end positions from valid tokens (e.g. for start, searching left to right for a valid token and vice versa) assuming at least one is defined. */ - export function expression( left: ConditionNode | @@ -38,7 +40,7 @@ export function expression( left?.end - const position = pos({ start, end } as Position | EmptyObj) + const position = pos({ start, end } as Position) if (left === undefined) { left = token(TOKEN_TYPE.VALUE, undefined, { start: position.start }) @@ -52,14 +54,13 @@ export function expression( right = token(TOKEN_TYPE.VALUE, undefined, { start: op.end }) } - const node: Partial = { - type: AST_TYPE.EXPRESSION, + const node: ConstructorParameters[0] = { left, operator: op, right, ...position, } - const instance = new ExpressionNode(node as any) + const instance = new ExpressionNode(node) return instance } diff --git a/src/ast/builders/group.ts b/src/ast/builders/group.ts index 862289a..682e96a 100644 --- a/src/ast/builders/group.ts +++ b/src/ast/builders/group.ts @@ -1,10 +1,11 @@ -import type { Mutable } from "@utils/types" - -import { token } from "./token" - -import { ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken } from "@/ast/classes" -import { AST_TYPE, Position, TOKEN_TYPE } from "@/types" +import { token } from "./token.js" +import { type Position, TOKEN_TYPE } from "../../types/ast.js" +import type { ConditionNode } from "../classes/ConditionNode.js" +import type { ErrorToken } from "../classes/ErrorToken.js" +import type { ExpressionNode } from "../classes/ExpressionNode.js" +import { GroupNode } from "../classes/GroupNode.js" +import type { ValidToken } from "../classes/ValidToken.js" /** * Creates a group. @@ -37,8 +38,7 @@ export function group( expression = token(TOKEN_TYPE.VALUE, undefined, prefix?.end !== undefined ? { start: prefix.end } : undefined) } - const node: Mutable> = { - type: AST_TYPE.GROUP, + const node: Partial[0]> = { expression, } if (prefix) { @@ -54,8 +54,8 @@ export function group( const start = expression.start const end = expression.end - parenLeftPos = parenLeftPos ?? (start !== undefined ? { start: start - 1, end: start } : undefined) - parenRightPos = parenRightPos ?? (end !== undefined ? { start: end, end: end + 1 } : undefined) + parenLeftPos ??= (start !== undefined ? { start: start - 1, end: start } : undefined) + parenRightPos ??= (end !== undefined ? { start: end, end: end + 1 } : undefined) if (paren?.left) { node.paren!.left = token(TOKEN_TYPE.PARENL, "(", parenLeftPos) diff --git a/src/ast/builders/index.ts b/src/ast/builders/index.ts index 8f7c651..6a04ab3 100644 --- a/src/ast/builders/index.ts +++ b/src/ast/builders/index.ts @@ -1,13 +1,13 @@ /* Autogenerated Index */ -export { array } from "./array" -export { condition } from "./condition" -export { delim } from "./delim" -export { error } from "./error" -export { expression } from "./expression" -export { group } from "./group" -export { isFullPos } from "./isFullPos" -export { pos } from "./pos" -export { token } from "./token" -export { type } from "./type" -export { variable } from "./variable" +export { array } from "./array.js" +export { condition } from "./condition.js" +export { delim } from "./delim.js" +export { error } from "./error.js" +export { expression } from "./expression.js" +export { group } from "./group.js" +export { isFullPos } from "./isFullPos.js" +export { pos } from "./pos.js" +export { token } from "./token.js" +export { type } from "./type.js" +export { variable } from "./variable.js" diff --git a/src/ast/builders/isFullPos.ts b/src/ast/builders/isFullPos.ts index d1b7c3e..43e3cbe 100644 --- a/src/ast/builders/isFullPos.ts +++ b/src/ast/builders/isFullPos.ts @@ -1,4 +1,4 @@ -import type { Position } from "@/types" +import type { Position } from "../../types/ast.js" /** * @internal diff --git a/src/ast/builders/pos.ts b/src/ast/builders/pos.ts index 0c0bb3c..3e0426a 100644 --- a/src/ast/builders/pos.ts +++ b/src/ast/builders/pos.ts @@ -1,8 +1,7 @@ -import { isFullPos } from "./isFullPos" - -import type { Node } from "@/ast/classes" -import type { AnyToken, AST_TYPE, EmptyObj, Position, TOKEN_TYPE } from "@/types" +import { isFullPos } from "./isFullPos.js" +import type { AnyToken, AST_TYPE, EmptyObj, Position, TOKEN_TYPE } from "../../types/ast.js" +import type { Node } from "../classes/Node.js" /** * Can either: diff --git a/src/ast/builders/token.ts b/src/ast/builders/token.ts index bf39fb7..6c316d6 100644 --- a/src/ast/builders/token.ts +++ b/src/ast/builders/token.ts @@ -1,9 +1,10 @@ -import { isArray } from "@utils/utils" +import { isArray } from "@alanscodelog/utils" -import { pos } from "./pos" +import { pos } from "./pos.js" -import { ErrorToken, ValidToken } from "@/ast/classes" -import type { AnyToken, EmptyObj, Position, TOKEN_TYPE } from "@/types" +import type { AnyToken, EmptyObj, Position, TOKEN_TYPE } from "../../types/ast.js" +import { ErrorToken } from "../classes/ErrorToken.js" +import { ValidToken } from "../classes/ValidToken.js" /** diff --git a/src/ast/builders/type.ts b/src/ast/builders/type.ts index a5abfaf..f5e95bb 100644 --- a/src/ast/builders/type.ts +++ b/src/ast/builders/type.ts @@ -1,9 +1,7 @@ -import { ExtractTokenType, TOKEN_TYPE } from "@/types" - +import { type ExtractTokenType, TOKEN_TYPE } from "../../types/ast.js" /** * Given a the string value of an operator or single delimiter token, returns the corresponding @see ValidToken_TYPE . */ - export function type( operatorSymbol: T ): ExtractTokenType { diff --git a/src/ast/builders/variable.ts b/src/ast/builders/variable.ts index 3824e44..627e3b2 100644 --- a/src/ast/builders/variable.ts +++ b/src/ast/builders/variable.ts @@ -1,21 +1,10 @@ -import type { Mutable } from "@utils/types" +import { pos } from "./pos.js" +import { token } from "./token.js" -import { pos } from "./pos" -import { token } from "./token" +import { type AnyToken, type EmptyObj, type Position, TOKEN_TYPE, type TokenQuoteTypes } from "../../types/ast.js" +import type { ValidToken } from "../classes/ValidToken.js" +import { VariableNode } from "../classes/VariableNode.js" -import { ValidToken, VariableNode } from "@/ast/classes" -import { AnyToken, AST_TYPE, EmptyObj, Position, TOKEN_TYPE, TokenQuoteTypes } from "@/types" - - -function quoteFromType(type: TokenQuoteTypes | undefined): string { - switch (type) { - case TOKEN_TYPE.BACKTICK: return "`" - case TOKEN_TYPE.DOUBLEQUOTE: return "\"" - case TOKEN_TYPE.SINGLEQUOTE: return "'" - case TOKEN_TYPE.REGEX: return "/" - case undefined: return "" - } -} /** * Creates an @see VariableNode . @@ -37,8 +26,7 @@ export function variable( position = pos(value) - const node: Mutable> = { - type: AST_TYPE.VARIABLE, + const node: Partial[0]> = { value, prefix, } @@ -89,3 +77,13 @@ export function variable( const instance = new VariableNode(node as any) return instance } + +function quoteFromType(type: TokenQuoteTypes | undefined): string { + switch (type) { + case TOKEN_TYPE.BACKTICK: return "`" + case TOKEN_TYPE.DOUBLEQUOTE: return "\"" + case TOKEN_TYPE.SINGLEQUOTE: return "'" + case TOKEN_TYPE.REGEX: return "/" + case undefined: return "" + } +} diff --git a/src/ast/classes/ArrayNode.ts b/src/ast/classes/ArrayNode.ts index b5d1a7f..2281d2c 100644 --- a/src/ast/classes/ArrayNode.ts +++ b/src/ast/classes/ArrayNode.ts @@ -1,26 +1,32 @@ -import type { ConditionNode } from "./ConditionNode" -import { Node } from "./Node" -import { ValidToken } from "./ValidToken" -import type { VariableNode } from "./VariableNode" +import type { ConditionNode } from "./ConditionNode.js" +import { Node } from "./Node.js" +import { ValidToken } from "./ValidToken.js" +import type { VariableNode } from "./VariableNode.js" -import { AST_TYPE, NodeDelimiters, TOKEN_TYPE } from "@/types" +import { AST_TYPE, type NodeDelimiters, type TOKEN_TYPE } from "../../types/ast.js" export class ArrayNode< TValid extends boolean = boolean, > extends Node { readonly values: VariableNode[] + readonly bracket: NodeDelimiters + #parent: any + #setParent: boolean = false + get parent(): ConditionNode | undefined { return this.#parent } + set parent(value: ConditionNode | undefined) { if (this.#setParent) { throw new Error("parent property is readonly") } this.#parent = value this.#setParent = true } + constructor({ values, bracket, start, end }: { values: ArrayNode["values"] bracket: ArrayNode["bracket"] diff --git a/src/ast/classes/Condition.ts b/src/ast/classes/Condition.ts index bef7c80..5db580c 100644 --- a/src/ast/classes/Condition.ts +++ b/src/ast/classes/Condition.ts @@ -1,8 +1,12 @@ export class Condition { readonly value: TValue + readonly operator?: TOp + readonly property: string[] + readonly negate: boolean + constructor({ property, operator, value, negate }: { property: Condition["property"] operator: Condition["operator"] diff --git a/src/ast/classes/ConditionNode.ts b/src/ast/classes/ConditionNode.ts index be9dd49..a1488ef 100644 --- a/src/ast/classes/ConditionNode.ts +++ b/src/ast/classes/ConditionNode.ts @@ -1,12 +1,12 @@ -import type { ArrayNode } from "./ArrayNode" -import type { ErrorToken } from "./ErrorToken" -import type { ExpressionNode } from "./ExpressionNode" -import type { GroupNode } from "./GroupNode" -import { Node } from "./Node" -import { ValidToken } from "./ValidToken" -import { VariableNode } from "./VariableNode" +import type { ArrayNode } from "./ArrayNode.js" +import type { ErrorToken } from "./ErrorToken.js" +import type { ExpressionNode } from "./ExpressionNode.js" +import type { GroupNode } from "./GroupNode.js" +import { Node } from "./Node.js" +import { ValidToken } from "./ValidToken.js" +import { VariableNode } from "./VariableNode.js" -import { AnyToken, AST_TYPE, TOKEN_TYPE } from "@/types" +import { type AnyToken, AST_TYPE, type TOKEN_TYPE } from "../../types/ast.js" /** @@ -32,10 +32,12 @@ export class ConditionNode< | ArrayNode | GroupNode | (TValid extends false ? ErrorToken : never) + /** * If the condition was negated, contains the "not" token, @see ValidToken , the condition was negated with. */ readonly operator?: ValidToken + /** * If condition property operators are used, this will contain the property (as a variable), or an error token if it was missing (but some separator or operator was passed). * @@ -44,6 +46,7 @@ export class ConditionNode< * See the corresponding @see ParserOptions for more details. */ readonly property?: VariableNode | (TValid extends false ? ErrorToken : never) + /** * If condition property operators are used, this will contain the operator. * @@ -54,6 +57,7 @@ export class ConditionNode< * See the corresponding @see ParserOptions for more details. */ readonly propertyOperator?: AnyToken + /** * If "long/expanded" form condition property operators are used, this will contain the separators, otherwise it is undefined. * @@ -69,13 +73,17 @@ export class ConditionNode< left?: AnyToken right?: AnyToken } + #parent: any + #setParent: boolean = false + get parent(): GroupNode | ExpressionNode | undefined { return this.#parent } + set parent(value: GroupNode | ExpressionNode | undefined @@ -84,6 +92,7 @@ export class ConditionNode< this.#parent = value this.#setParent = true } + constructor({ property, propertyOperator, sep, value, start, end, operator }: { operator?: TOperator property?: ConditionNode["property"] diff --git a/src/ast/classes/ErrorToken.ts b/src/ast/classes/ErrorToken.ts index 281af44..e9fb0a5 100644 --- a/src/ast/classes/ErrorToken.ts +++ b/src/ast/classes/ErrorToken.ts @@ -1,11 +1,10 @@ -import type { ConditionNode } from "./ConditionNode" -import type { ExpressionNode } from "./ExpressionNode" -import type { GroupNode } from "./GroupNode" -import { Token } from "./Token" -import type { VariableNode } from "./VariableNode" - -import type { TOKEN_TYPE } from "@/types" +import type { ConditionNode } from "./ConditionNode.js" +import type { ExpressionNode } from "./ExpressionNode.js" +import type { GroupNode } from "./GroupNode.js" +import { Token } from "./Token.js" +import type { VariableNode } from "./VariableNode.js" +import type { TOKEN_TYPE } from "../../types/ast.js" /** * The class for invalid recovery tokens. @@ -20,13 +19,16 @@ export class ErrorToken< TExpected extends TOKEN_TYPE = TOKEN_TYPE, > extends Token { readonly expected: TExpected[] + #parent: any + get parent(): VariableNode | GroupNode | ExpressionNode | ConditionNode { return this.#parent } + set parent(value: VariableNode | GroupNode | ExpressionNode | @@ -35,6 +37,7 @@ export class ErrorToken< if (this.#parent) {throw new Error("parent property is readonly")} this.#parent = value } + constructor({ expected, start, end }: { expected: TExpected[] start: number diff --git a/src/ast/classes/Expression.ts b/src/ast/classes/Expression.ts index 5e49e7e..688276c 100644 --- a/src/ast/classes/Expression.ts +++ b/src/ast/classes/Expression.ts @@ -1,16 +1,19 @@ -import type { Condition } from "./Condition" +import type { Condition } from "./Condition.js" -import type { TokenBooleanTypes } from "@/types" +import type { TokenBooleanTypes } from "../../types/ast.js" export class Expression { readonly left: | Expression | Condition + readonly right: | Expression | Condition + readonly operator: TokenBooleanTypes + constructor({ operator, left, right }: { operator: Expression["operator"] right: Expression["right"] diff --git a/src/ast/classes/ExpressionNode.ts b/src/ast/classes/ExpressionNode.ts index 366e56c..36e7937 100644 --- a/src/ast/classes/ExpressionNode.ts +++ b/src/ast/classes/ExpressionNode.ts @@ -1,10 +1,10 @@ -import type { ConditionNode } from "./ConditionNode" -import type { ErrorToken } from "./ErrorToken" -import type { GroupNode } from "./GroupNode" -import { Node } from "./Node" -import { ValidToken } from "./ValidToken" +import type { ConditionNode } from "./ConditionNode.js" +import type { ErrorToken } from "./ErrorToken.js" +import type { GroupNode } from "./GroupNode.js" +import { Node } from "./Node.js" +import { ValidToken } from "./ValidToken.js" -import { AnyToken, AST_TYPE, TOKEN_TYPE, TokenBooleanTypes } from "@/types" +import { type AnyToken, AST_TYPE, type TOKEN_TYPE, type TokenBooleanTypes } from "../../types/ast.js" export class ExpressionNode< @@ -12,26 +12,33 @@ export class ExpressionNode< > extends Node { readonly operator: AnyToken + readonly left: | ExpressionNode | ConditionNode | GroupNode | (TValid extends false ? ErrorToken : never) + readonly right: | ExpressionNode | ConditionNode | GroupNode | (TValid extends false ? ErrorToken : never) + #parent: any + #setParent: boolean = false + get parent(): GroupNode | undefined { return this.#parent } + set parent(value: GroupNode | undefined) { if (this.#setParent) {throw new Error("parent property is readonly")} this.#parent = value this.#setParent = true } + constructor({ operator, left, right, start, end }: { operator: ExpressionNode["operator"] right: ExpressionNode["right"] diff --git a/src/ast/classes/GroupNode.ts b/src/ast/classes/GroupNode.ts index eaf209a..447321b 100644 --- a/src/ast/classes/GroupNode.ts +++ b/src/ast/classes/GroupNode.ts @@ -1,10 +1,10 @@ -import type { ConditionNode } from "./ConditionNode" -import type { ErrorToken } from "./ErrorToken" -import type { ExpressionNode } from "./ExpressionNode" -import { Node } from "./Node" -import { ValidToken } from "./ValidToken" +import type { ConditionNode } from "./ConditionNode.js" +import type { ErrorToken } from "./ErrorToken.js" +import type { ExpressionNode } from "./ExpressionNode.js" +import { Node } from "./Node.js" +import { ValidToken } from "./ValidToken.js" -import { AST_TYPE, NodeDelimiters, TOKEN_TYPE } from "@/types" +import { AST_TYPE, type NodeDelimiters, type TOKEN_TYPE } from "../../types/ast.js" /** @@ -65,25 +65,32 @@ export class GroupNode< * See examples at @see GroupNode . */ readonly prefix: TPrefix + expression: | ConditionNode | GroupNode | ExpressionNode | (TValid extends false ? ErrorToken : never) + /** * The parenthesis tokens, @see ValidToken . These will always be defined (although not necessarily with valid tokens). */ readonly paren: NodeDelimiters + #parent: any + #setParent: boolean = false + get parent(): ExpressionNode | undefined { return this.#parent } + set parent(value: ExpressionNode | undefined) { if (this.#setParent) {throw new Error("parent property is readonly")} this.#parent = value this.#setParent = true } + constructor({ prefix, expression, paren, start, end }: { prefix: TPrefix expression: GroupNode["expression"] diff --git a/src/ast/classes/Node.ts b/src/ast/classes/Node.ts index 1bb157c..d7d1c67 100644 --- a/src/ast/classes/Node.ts +++ b/src/ast/classes/Node.ts @@ -1,12 +1,11 @@ -import type { ArrayNode } from "./ArrayNode" -import type { ConditionNode } from "./ConditionNode" -import type { ExpressionNode } from "./ExpressionNode" -import type { GroupNode } from "./GroupNode" - -import { BooleanParserLibraryError } from "@/helpers/errors" -import type { AST_TYPE } from "@/types" -import { ERROR_CODES } from "@/types/errors" +import type { ArrayNode } from "./ArrayNode.js" +import type { ConditionNode } from "./ConditionNode.js" +import type { ExpressionNode } from "./ExpressionNode.js" +import type { GroupNode } from "./GroupNode.js" +import { BooleanParserLibraryError } from "../../helpers/errors.js" +import type { AST_TYPE } from "../../types/ast.js" +import { ERROR_CODES } from "../../types/errors.js" /** * The base AST node class all node types extend from. Can be used to check if an object is an ast node. @@ -16,15 +15,18 @@ import { ERROR_CODES } from "@/types/errors" * } * ``` */ - export class Node< TType extends AST_TYPE = AST_TYPE, TValid extends boolean = boolean, > { readonly type: TType + readonly start: number + readonly end: number + readonly valid!: TValid + get parent(): ConditionNode | GroupNode | @@ -33,6 +35,7 @@ export class Node< undefined { return undefined as any } + constructor(type: TType, start: number, end: number) { this.type = type if (start === undefined || end === undefined) { diff --git a/src/ast/classes/Token.ts b/src/ast/classes/Token.ts index 404df99..0215e70 100644 --- a/src/ast/classes/Token.ts +++ b/src/ast/classes/Token.ts @@ -1,13 +1,12 @@ -import type { ArrayNode } from "./ArrayNode" -import type { ConditionNode } from "./ConditionNode" -import type { ExpressionNode } from "./ExpressionNode" -import type { GroupNode } from "./GroupNode" -import type { VariableNode } from "./VariableNode" - -import { BooleanParserLibraryError } from "@/helpers/errors" -import type { TOKEN_TYPE } from "@/types" -import { ERROR_CODES } from "@/types/errors" +import type { ArrayNode } from "./ArrayNode.js" +import type { ConditionNode } from "./ConditionNode.js" +import type { ExpressionNode } from "./ExpressionNode.js" +import type { GroupNode } from "./GroupNode.js" +import type { VariableNode } from "./VariableNode.js" +import { BooleanParserLibraryError } from "../../helpers/errors.js" +import type { TOKEN_TYPE } from "../../types/ast.js" +import { ERROR_CODES } from "../../types/errors.js" /** * The base class from which @see ValidToken and @see ErrorToken extend. @@ -20,7 +19,6 @@ import { ERROR_CODES } from "@/types/errors" * ``` * Only really takes care of setting the start/end position. */ - export class Token< TValid extends boolean = boolean, TType extends @@ -34,10 +32,15 @@ export class Token< TValid extends false ? TOKEN_TYPE[] : never, > { readonly type!: TType + readonly value!: TValue + readonly expected!: TExpected + readonly start!: number + readonly end!: number + get parent(): VariableNode | GroupNode | ExpressionNode | @@ -45,6 +48,7 @@ export class Token< ConditionNode { return undefined as any } + constructor(start: number, end: number) { if (start === undefined || end === undefined) { throw new BooleanParserLibraryError(ERROR_CODES.PARSER_POSITION_ERROR, { start, end }) diff --git a/src/ast/classes/ValidToken.ts b/src/ast/classes/ValidToken.ts index 5df8690..a489015 100644 --- a/src/ast/classes/ValidToken.ts +++ b/src/ast/classes/ValidToken.ts @@ -1,11 +1,11 @@ -import type { ArrayNode } from "./ArrayNode" -import type { ConditionNode } from "./ConditionNode" -import type { ExpressionNode } from "./ExpressionNode" -import type { GroupNode } from "./GroupNode" -import { Token } from "./Token" -import type { VariableNode } from "./VariableNode" +import type { ArrayNode } from "./ArrayNode.js" +import type { ConditionNode } from "./ConditionNode.js" +import type { ExpressionNode } from "./ExpressionNode.js" +import type { GroupNode } from "./GroupNode.js" +import { Token } from "./Token.js" +import type { VariableNode } from "./VariableNode.js" -import type { TOKEN_TYPE } from "@/types" +import type { TOKEN_TYPE } from "../../types/ast.js" /** @@ -13,13 +13,15 @@ import type { TOKEN_TYPE } from "@/types" * * Valid tokens always have a value, even if it might be an empty string. */ - export class ValidToken< TType extends TOKEN_TYPE = TOKEN_TYPE, > extends Token { readonly type: TType + readonly value: string + #parent: any + get parent(): | VariableNode | GroupNode @@ -28,6 +30,7 @@ export class ValidToken< | ArrayNode { return this.#parent } + set parent(value: | VariableNode | GroupNode @@ -38,6 +41,7 @@ export class ValidToken< if (this.#parent) {throw new Error("parent property is readonly")} this.#parent = value } + constructor({ type, value, start, end }: { type: TType value: string diff --git a/src/ast/classes/VariableNode.ts b/src/ast/classes/VariableNode.ts index c4ca0b8..2aed7ac 100644 --- a/src/ast/classes/VariableNode.ts +++ b/src/ast/classes/VariableNode.ts @@ -1,11 +1,10 @@ -import type { ArrayNode } from "./ArrayNode" -import type { ConditionNode } from "./ConditionNode" -import type { ErrorToken } from "./ErrorToken" -import { Node } from "./Node" -import { ValidToken } from "./ValidToken" - -import { AnyToken, AST_TYPE, NodeDelimiters, TOKEN_TYPE, TokenQuoteTypes } from "@/types" +import type { ArrayNode } from "./ArrayNode.js" +import type { ConditionNode } from "./ConditionNode.js" +import type { ErrorToken } from "./ErrorToken.js" +import { Node } from "./Node.js" +import { ValidToken } from "./ValidToken.js" +import { type AnyToken, AST_TYPE, type NodeDelimiters, type TOKEN_TYPE, type TokenQuoteTypes } from "../../types/ast.js" /** * A variable represents **just** a string value (NOT it's boolean value). @@ -18,7 +17,6 @@ import { AnyToken, AST_TYPE, NodeDelimiters, TOKEN_TYPE, TokenQuoteTypes } from * * If `prefixableStrings` is true, the `prefix` property might contain a value token. */ - export class VariableNode< TValid extends boolean = boolean, > extends Node { @@ -27,18 +25,25 @@ export class VariableNode< : TValid extends true ? ValidToken : ErrorToken + readonly prefix?: ValidToken // todo + readonly quote?: NodeDelimiters + #parent: any + #setParent: boolean = false + get parent(): ConditionNode | ArrayNode | undefined { return this.#parent } + set parent(value: ConditionNode | ArrayNode | undefined) { if (this.#setParent) {throw new Error("parent property is readonly")} this.#parent = value this.#setParent = true } + constructor({ prefix, value, quote, start, end }: { prefix?: VariableNode["prefix"] value: VariableNode["value"] diff --git a/src/ast/classes/index.ts b/src/ast/classes/index.ts index f29aae9..d574247 100644 --- a/src/ast/classes/index.ts +++ b/src/ast/classes/index.ts @@ -1,13 +1,13 @@ /* Autogenerated Index */ -export { ArrayNode } from "./ArrayNode" -export { Condition } from "./Condition" -export { ConditionNode } from "./ConditionNode" -export { ErrorToken } from "./ErrorToken" -export { Expression } from "./Expression" -export { ExpressionNode } from "./ExpressionNode" -export { GroupNode } from "./GroupNode" -export { Node } from "./Node" -export { Token } from "./Token" -export { ValidToken } from "./ValidToken" -export { VariableNode } from "./VariableNode" +export { ArrayNode } from "./ArrayNode.js" +export { Condition } from "./Condition.js" +export { ConditionNode } from "./ConditionNode.js" +export { ErrorToken } from "./ErrorToken.js" +export { Expression } from "./Expression.js" +export { ExpressionNode } from "./ExpressionNode.js" +export { GroupNode } from "./GroupNode.js" +export { Node } from "./Node.js" +export { Token } from "./Token.js" +export { ValidToken } from "./ValidToken.js" +export { VariableNode } from "./VariableNode.js" diff --git a/src/ast/handlers.ts b/src/ast/handlers.ts index bc35537..8041743 100644 --- a/src/ast/handlers.ts +++ b/src/ast/handlers.ts @@ -1,8 +1,14 @@ /* eslint-disable @typescript-eslint/no-shadow */ -import { ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken, VariableNode } from "./classes" -import { ArrayNode } from "./classes/ArrayNode" -import { AnyToken, FirstConstructorParam, Position, TOKEN_TYPE, TokenBooleanTypes, TokenDelimiterTypes, TokenOperatorTypes, TokenQuoteTypes } from "@/types" +import { ArrayNode } from "./classes/ArrayNode.js" +import { ConditionNode } from "./classes/ConditionNode.js" +import { ErrorToken } from "./classes/ErrorToken.js" +import { ExpressionNode } from "./classes/ExpressionNode.js" +import { GroupNode } from "./classes/GroupNode.js" +import { ValidToken } from "./classes/ValidToken.js" +import { VariableNode } from "./classes/VariableNode.js" + +import { type AnyToken, type FirstConstructorParam, type Position, TOKEN_TYPE, type TokenBooleanTypes, type TokenDelimiterTypes, type TokenOperatorTypes, type TokenQuoteTypes } from "../types/ast.js" /* #region HELPERS */ @@ -111,15 +117,15 @@ export function condition( node.sep = {} if (sepL) { node.sep.left = sepL - if (!node.property) node.property = error(sepL.start, [TOKEN_TYPE.VALUE]) - if (!node.propertyOperator) node.propertyOperator = error(sepL?.end ?? sepR?.start, [TOKEN_TYPE.VALUE]) + node.property ||= error(sepL.start, [TOKEN_TYPE.VALUE]) + node.propertyOperator ||= error(sepL?.end ?? sepR?.start, [TOKEN_TYPE.VALUE]) } if (sepR) node.sep.right = sepR else if (!node.value || node.value instanceof VariableNode) { node.sep.right = error(node.value?.start ?? end, [TOKEN_TYPE.OP_EXPANDED_SEP]) } } else if (propertyOperator) { - if (!node.property) node.property = error(propertyOperator.start, [TOKEN_TYPE.VALUE]) + node.property ||= error(propertyOperator.start, [TOKEN_TYPE.VALUE]) } const instance = new ConditionNode(node as any) diff --git a/src/ast/index.ts b/src/ast/index.ts index 2bc9ead..1f530d6 100644 --- a/src/ast/index.ts +++ b/src/ast/index.ts @@ -1,5 +1,5 @@ /* Autogenerated Index */ -export * as builders from "./builders" -export * as classes from "./classes" -export { token } from "./handlers" +export * as builders from "./builders/index.js" +export * as classes from "./classes/index.js" +export { token } from "./handlers.js" diff --git a/src/examples/advancedValueComparer.ts b/src/examples/advancedValueComparer.ts index 9cfbb44..081db76 100644 --- a/src/examples/advancedValueComparer.ts +++ b/src/examples/advancedValueComparer.ts @@ -1,4 +1,4 @@ -import type { ValueQuery } from "@/types" +import type { ValueQuery } from "../types/parser.js" /* TODO TOUPDATE */ type Operators = ">" | "contains" diff --git a/src/examples/shortcutContextParser.ts b/src/examples/shortcutContextParser.ts index 498b769..be22682 100644 --- a/src/examples/shortcutContextParser.ts +++ b/src/examples/shortcutContextParser.ts @@ -1,6 +1,3 @@ -import { Parser } from "@/parser" -import type { Position, ValueQuery } from "@/types" - /* TODO TOUPDATE */ /** * A pre-configured parser for parsing shortcut contexts (similar to VSCode's [when clause contexts](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts)). @@ -12,12 +9,19 @@ import type { Position, ValueQuery } from "@/types" * The validate function will return a list of positions with a list of errors which includes handling invalid or duplicate regex flags. */ +import { Parser } from "../parser.js" +import type { Position } from "../types/ast.js" +import type { ValueQuery } from "../types/parser.js" + + export class ShortcutContextParser extends Parser { validKeys: string[] = [] + regexablekeys: string[] = [] + constructor( dummyContext: Record, validRegexFlags: string[] = ["i", "u", "m"] @@ -118,6 +122,7 @@ export class ShortcutContextParser, prev?: string): void { for (const key of Object.keys(context)) { if (typeof context[key] === "boolean") { diff --git a/src/global.d.ts b/src/global.d.ts index 911992d..151463d 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,4 +1,4 @@ -declare module "@/package" { +declare module "./package.js" { export const version: string export const repository: string } diff --git a/src/grammar/ParserBase.ts b/src/grammar/ParserBase.ts index 6d035d1..ecd7636 100644 --- a/src/grammar/ParserBase.ts +++ b/src/grammar/ParserBase.ts @@ -1,16 +1,23 @@ /* eslint-disable @typescript-eslint/naming-convention */ -/* eslint-disable import/no-namespace */ -import { isArray, unreachable } from "@utils/utils" -import { EmbeddedActionsParser, EOF, IToken, tokenMatcher } from "chevrotain" -import type { createTokens } from "./createTokens" +import { isArray, unreachable } from "@alanscodelog/utils" +import { EmbeddedActionsParser, EOF, type IToken, tokenMatcher } from "chevrotain" -import { pos } from "@/ast/builders" -import { ArrayNode, ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import * as handle from "@/ast/handlers" -import { extractPosition } from "@/helpers/parser" -import { Parser } from "@/parser" -import { AnyToken, FullParserOptions, ParserResults, Position, TOKEN_TYPE, TokenQuoteTypes } from "@/types" +import type { createTokens } from "./createTokens.js" + +import { pos } from "../ast/builders/pos.js" +import { ArrayNode } from "../ast/classes/ArrayNode.js" +import { ConditionNode } from "../ast/classes/ConditionNode.js" +import { ErrorToken } from "../ast/classes/ErrorToken.js" +import type { ExpressionNode } from "../ast/classes/ExpressionNode.js" +import type { GroupNode } from "../ast/classes/GroupNode.js" +import type { ValidToken } from "../ast/classes/ValidToken.js" +import { VariableNode } from "../ast/classes/VariableNode.js" +import * as handle from "../ast/handlers.js" +import { extractPosition } from "../helpers/parser/extractPosition.js" +import { Parser } from "../parser.js" +import { type AnyToken, type ParserResults, type Position, TOKEN_TYPE, type TokenQuoteTypes } from "../types/ast.js" +import type { FullParserOptions } from "../types/parser.js" function processToken(token: IToken, shift: number): [TDefined extends true ? string : string | undefined, Position] { @@ -20,8 +27,11 @@ function processToken(token: IToken, shift: } export class ParserBase extends EmbeddedActionsParser { rawInput!: string + private subParser?: Parser + private subParser2?: Parser + constructor(opts: FullParserOptions, t: ReturnType["tokens"], { customOpAlsoNegation, expandedSepAlsoCustom }: ReturnType["info"]) { super(t, { recoveryEnabled: true, @@ -187,30 +197,30 @@ export class ParserBase extends EmbeddedActionsParser { const property = $.OPTION2({ GATE: () => ( tokenMatcher($.LA(1), t.EXP_PROP_OP) || - tokenMatcher($.LA(1), t.CUSTOM_PROP_OP) || - tokenMatcher($.LA(2), t.EXP_PROP_OP) || - tokenMatcher($.LA(2), t.CUSTOM_PROP_OP) || + tokenMatcher($.LA(1), t.CUSTOM_PROP_OP) || + tokenMatcher($.LA(2), t.EXP_PROP_OP) || + tokenMatcher($.LA(2), t.CUSTOM_PROP_OP) || + ( + customOpAlsoNegation && ( - customOpAlsoNegation && - ( - tokenMatcher($.LA(2), t.SYM_NOT) || - (tokenMatcher($.LA(0), t.SYM_NOT) && tokenMatcher($.LA(1), t.SYM_NOT)) - ) + tokenMatcher($.LA(2), t.SYM_NOT) || + (tokenMatcher($.LA(0), t.SYM_NOT) && tokenMatcher($.LA(1), t.SYM_NOT)) ) + ) ), DEF: () => $.SUBRULE($.property), }) as ReturnType | undefined const propVal = $.ACTION(() => property?.prop?.value === undefined ? undefined : property.prop.value instanceof ErrorToken - ? "" - : property.prop.value.value) + ? "" + : property.prop.value.value) const propOpVal = $.ACTION(() => property?.rest.propertyOperator === undefined ? undefined : property.rest.propertyOperator instanceof ErrorToken - ? "" - : property.rest.propertyOperator.value) + ? "" + : property.rest.propertyOperator.value) const isExpanded = $.ACTION(() => (property?.rest.sepL ?? property?.rest.sepR) !== undefined) const convertRegexValues = $.ACTION(() => @@ -226,29 +236,29 @@ export class ParserBase extends EmbeddedActionsParser { undefined = $.OR2([ { GATE: () => opts.prefixableGroups && property === undefined && - $.LA(1).tokenType !== t.PAREN_L && // moves to parsing group below - ( + $.LA(1).tokenType !== t.PAREN_L && // moves to parsing group below ( - tokenMatcher($.LA(1), t.VALUE) && ( - tokenMatcher($.LA(2), t.PAREN_L) || // a( - (tokenMatcher($.LA(2), t.QUOTE_ANY) && tokenMatcher($.LA(3), t.PAREN_L)) // a"( - ) - ) || - ( - tokenMatcher($.LA(1), t.QUOTE_ANY) && + tokenMatcher($.LA(1), t.VALUE) && + ( + tokenMatcher($.LA(2), t.PAREN_L) || // a( + (tokenMatcher($.LA(2), t.QUOTE_ANY) && tokenMatcher($.LA(3), t.PAREN_L)) // a"( + ) + ) || ( - tokenMatcher($.LA(2), t.PAREN_L) || // "( - (tokenMatcher($.LA(2), t.VALUE) && - ( - tokenMatcher($.LA(3), t.PAREN_L) || // "a( - (tokenMatcher($.LA(3), t.QUOTE_ANY) && tokenMatcher($.LA(4), t.PAREN_L)) // "a"( + tokenMatcher($.LA(1), t.QUOTE_ANY) && + ( + tokenMatcher($.LA(2), t.PAREN_L) || // "( + (tokenMatcher($.LA(2), t.VALUE) && + ( + tokenMatcher($.LA(3), t.PAREN_L) || // "a( + (tokenMatcher($.LA(3), t.QUOTE_ANY) && tokenMatcher($.LA(4), t.PAREN_L)) // "a"( + ) ) ) ) - ) - ) + ) , ALT: () => $.SUBRULE($.variable, { ARGS: [{ unprefixed: true }]}), // un-prefixed }, @@ -312,13 +322,13 @@ export class ParserBase extends EmbeddedActionsParser { { ALT: () => { let sepL: any = $.CONSUME(t.EXP_PROP_OP) - if (sepL) sepL = handle.token.sep(...processToken(sepL, $.shift)) + sepL &&= handle.token.sep(...processToken(sepL, $.shift)) let op: any = $.OPTION4(() => $.CONSUME2(t.VALUE_UNQUOTED)) - if (op) op = handle.token.value(...processToken(op, $.shift)) + op &&= handle.token.value(...processToken(op, $.shift)) let sepR: any = $.OPTION5(() => $.CONSUME2(t.EXP_PROP_OP)) - if (sepR) sepR = handle.token.sep(...processToken(sepR, $.shift)) + sepR &&= handle.token.sep(...processToken(sepR, $.shift)) if (expandedSepAlsoCustom && op === undefined && sepR === undefined) { op = sepL op.type = TOKEN_TYPE.OP_CUSTOM @@ -367,7 +377,7 @@ export class ParserBase extends EmbeddedActionsParser { ) { const token = $.CONSUME(t.ANY) - start = start ?? extractPosition(token, this.shift).start + start ??= extractPosition(token, this.shift).start if (tokenMatcher(token, t.PAREN_L)) { parenLeftCount++ } @@ -378,7 +388,7 @@ export class ParserBase extends EmbeddedActionsParser { } if (start !== undefined) { - end = end ?? extractPosition($.LA(0), this.shift).end + end ??= extractPosition($.LA(0), this.shift).end } const parenR = $.OPTION2(() => $.SUBRULE1($.parenR)) @@ -479,7 +489,7 @@ export class ParserBase extends EmbeddedActionsParser { }) - if (prefix) prefix = handle.token.value(...processToken(prefix, $.shift)) + prefix &&= handle.token.value(...processToken(prefix, $.shift)) const ARGS = [{ bracketVal }] const val = $.OR([ @@ -556,14 +566,14 @@ export class ParserBase extends EmbeddedActionsParser { const value = $.CONSUME(t.QUOTE_ANY) return $.ACTION(() => { const type = value.image === `"` - ? "double" - : value.image === "'" - ? "single" - : value.image === "\\" - ? "regex" - : value.image === "`" - ? "tick" - : unreachable() + ? "double" + : value.image === "'" + ? "single" + : value.image === "\\" + ? "regex" + : value.image === "`" + ? "tick" + : unreachable() return handle.delimiter[type](...processToken(value, $.shift)) }) }) diff --git a/src/grammar/createTokens.ts b/src/grammar/createTokens.ts index 6f3a0a1..f6000ad 100644 --- a/src/grammar/createTokens.ts +++ b/src/grammar/createTokens.ts @@ -1,8 +1,8 @@ /* eslint-disable camelcase */ -import { escapeRegex, isBlank } from "@utils/utils" -import { createToken, Lexer, TokenType } from "chevrotain" +import { escapeRegex, isBlank } from "@alanscodelog/utils" +import { createToken, Lexer, type TokenType } from "chevrotain" -import type { FullParserOptions } from "@/types" +import type { FullParserOptions } from "../types/parser.js" /** Makes it easier to rename the tokens while still returning a properly typed record of them.*/ @@ -207,9 +207,7 @@ export function createTokens(opts: FullParserOptions): { prevEscaped = false } } else { - if (prevEscaped) { - prevEscaped = false - } + prevEscaped &&= false } end++ char = text[end] diff --git a/src/grammar/index.ts b/src/grammar/index.ts index 8cf1ccf..81e74f0 100644 --- a/src/grammar/index.ts +++ b/src/grammar/index.ts @@ -1,4 +1,4 @@ /* Autogenerated Index */ -export { createTokens } from "./createTokens" -export { ParserBase } from "./ParserBase" +export { createTokens } from "./createTokens.js" +export { ParserBase } from "./ParserBase.js" diff --git a/src/helpers/errors.ts b/src/helpers/errors.ts index a6a2903..093d011 100644 --- a/src/helpers/errors.ts +++ b/src/helpers/errors.ts @@ -1,15 +1,20 @@ -import type { Keys } from "@utils/types" -import { crop, indent, pretty } from "@utils/utils" +import type { Keys } from "@alanscodelog/utils" +import { crop, indent, pretty } from "@alanscodelog/utils" -import { repository, version } from "@/package" -import type { ERROR_CODES, ErrorInfo } from "@/types" +// @ts-expect-error todo +import { repository, version } from "../package.js" +import type { ERROR_CODES, ErrorInfo } from "../types/errors.js" export class BooleanParserLibraryError extends Error { version: string = version + repo: string = repository + type: T + info: ErrorInfo + constructor(type: T, info: ErrorInfo, message?: string) { super( message diff --git a/src/helpers/general/applyPrefix.ts b/src/helpers/general/applyPrefix.ts index 38efc5e..ba492d1 100644 --- a/src/helpers/general/applyPrefix.ts +++ b/src/helpers/general/applyPrefix.ts @@ -1,4 +1,4 @@ -import type { PrefixApplier } from "@/types" +import type { PrefixApplier } from "../../types/parser.js" /** @internal */ export function applyPrefix(left: string | undefined, right: string, prefixApplier: PrefixApplier): string { diff --git a/src/helpers/general/defaultConditionNormalizer.ts b/src/helpers/general/defaultConditionNormalizer.ts index 63f9cc3..9bc7ef1 100644 --- a/src/helpers/general/defaultConditionNormalizer.ts +++ b/src/helpers/general/defaultConditionNormalizer.ts @@ -1,7 +1,9 @@ -import type { ConditionNormalizer } from "@/types" +import type { ConditionNormalizer, ValueQuery } from "../../types/parser.js" export const defaultConditionNormalizer: ConditionNormalizer = -function defaultConditionNormalizer({ value, operator, isNegated }) { +function defaultConditionNormalizer( + { value, operator, isNegated }: Pick +) { return { value, operator, negate: isNegated } } diff --git a/src/helpers/general/defaultKeyParser.ts b/src/helpers/general/defaultKeyParser.ts index 197775e..04bcb27 100644 --- a/src/helpers/general/defaultKeyParser.ts +++ b/src/helpers/general/defaultKeyParser.ts @@ -1,8 +1,8 @@ -import type { KeyParser } from "@/types" +import type { KeyParser } from "../../types/parser.js" export const defaultKeyParser: KeyParser = - function defaultKeyParser(value) { + function defaultKeyParser(value?: string) { if (value === undefined) return [] return [value] } diff --git a/src/helpers/general/defaultPrefixApplier.ts b/src/helpers/general/defaultPrefixApplier.ts index cd5c18c..ae918da 100644 --- a/src/helpers/general/defaultPrefixApplier.ts +++ b/src/helpers/general/defaultPrefixApplier.ts @@ -1,7 +1,7 @@ -import type { PrefixApplier } from "@/types" +import type { PrefixApplier } from "../../types/parser.js" export const defaultPrefixApplier: PrefixApplier = -function defaultPrefixApplier(prefix, value) { +function defaultPrefixApplier(prefix: string, value: string) { return prefix + value } diff --git a/src/helpers/general/defaultValueComparer.ts b/src/helpers/general/defaultValueComparer.ts index 1c7f84e..2213ffa 100644 --- a/src/helpers/general/defaultValueComparer.ts +++ b/src/helpers/general/defaultValueComparer.ts @@ -1,7 +1,7 @@ -import type { ValueComparer } from "@/types" +import type { ValueComparer } from "../../types/parser.js" export const defaultValueComparer: ValueComparer = -function defaultValueComparer(condition, contextValue) { +function defaultValueComparer(condition: { value: any }, contextValue: any) { return contextValue === condition.value } diff --git a/src/helpers/general/index.ts b/src/helpers/general/index.ts index c0d36de..9be3a82 100644 --- a/src/helpers/general/index.ts +++ b/src/helpers/general/index.ts @@ -1,8 +1,8 @@ /* Autogenerated Index */ -export { applyBoolean } from "./applyBoolean" -export { applyPrefix } from "./applyPrefix" -export { defaultConditionNormalizer } from "./defaultConditionNormalizer" -export { defaultKeyParser } from "./defaultKeyParser" -export { defaultPrefixApplier } from "./defaultPrefixApplier" -export { defaultValueComparer } from "./defaultValueComparer" +export { applyBoolean } from "./applyBoolean.js" +export { applyPrefix } from "./applyPrefix.js" +export { defaultConditionNormalizer } from "./defaultConditionNormalizer.js" +export { defaultKeyParser } from "./defaultKeyParser.js" +export { defaultPrefixApplier } from "./defaultPrefixApplier.js" +export { defaultValueComparer } from "./defaultValueComparer.js" diff --git a/src/helpers/index.ts b/src/helpers/index.ts index d4bd7e2..d87a823 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,5 +1,5 @@ /* Autogenerated Index [Ignore] */ -export * as general from "./general" -export * as parser from "./parser" -export { BooleanParserLibraryError } from "./errors" +export * as general from "./general/index.js" +export * as parser from "./parser/index.js" +export { BooleanParserLibraryError } from "./errors.js" diff --git a/src/helpers/parser/assignParents.ts b/src/helpers/parser/assignParents.ts index 31351b5..f184011 100644 --- a/src/helpers/parser/assignParents.ts +++ b/src/helpers/parser/assignParents.ts @@ -1,6 +1,10 @@ -import { ArrayNode, ConditionNode, ExpressionNode, GroupNode, Node, VariableNode } from "@/ast/classes" -import type { Nodes } from "@/types" - +import { ArrayNode } from "../../ast/classes/ArrayNode.js" +import { ConditionNode } from "../../ast/classes/ConditionNode.js" +import { ExpressionNode } from "../../ast/classes/ExpressionNode.js" +import { GroupNode } from "../../ast/classes/GroupNode.js" +import { Node } from "../../ast/classes/Node.js" +import { VariableNode } from "../../ast/classes/VariableNode.js" +import type { Nodes } from "../../types/ast.js" /** @internal */ export function assignParents(ast: Nodes): void { diff --git a/src/helpers/parser/checkParserOpts.ts b/src/helpers/parser/checkParserOpts.ts index a1b80f4..16a92cb 100644 --- a/src/helpers/parser/checkParserOpts.ts +++ b/src/helpers/parser/checkParserOpts.ts @@ -1,8 +1,10 @@ -import { isBlank, pushIfNotIn } from "@utils/utils" +import { isBlank, pushIfNotIn } from "@alanscodelog/utils" -import { BooleanParserLibraryError } from "@/helpers/errors" -import { defaultConditionNormalizer, defaultValueComparer } from "@/helpers/general" -import { ERROR_CODES, FullParserOptions, ParserOptions } from "@/types" +import { ERROR_CODES } from "../../types/errors.js" +import type { FullParserOptions, ParserOptions } from "../../types/parser.js" +import { BooleanParserLibraryError } from "../errors.js" +import { defaultConditionNormalizer } from "../general/defaultConditionNormalizer.js" +import { defaultValueComparer } from "../general/defaultValueComparer.js" export function checkParserOpts(opts: FullParserOptions, evaluatorChecks: boolean = false, validatorChecks: boolean = false): void { diff --git a/src/helpers/parser/extractPosition.ts b/src/helpers/parser/extractPosition.ts index f5bacee..f1473c5 100644 --- a/src/helpers/parser/extractPosition.ts +++ b/src/helpers/parser/extractPosition.ts @@ -1,4 +1,4 @@ -import type { Position } from "@/types" +import type { Position } from "../../types/ast.js" type ChevrotainLocation = { diff --git a/src/helpers/parser/getUnclosedRightParenCount.ts b/src/helpers/parser/getUnclosedRightParenCount.ts index 091f29b..cdbbd14 100644 --- a/src/helpers/parser/getUnclosedRightParenCount.ts +++ b/src/helpers/parser/getUnclosedRightParenCount.ts @@ -1,6 +1,6 @@ -import { IToken, tokenMatcher } from "chevrotain" +import { type IToken, tokenMatcher } from "chevrotain" -import type { createTokens } from "@/grammar" +import type { createTokens } from "../../grammar/createTokens.js" /** @internal */ diff --git a/src/helpers/parser/index.ts b/src/helpers/parser/index.ts index 052b44d..a0643ed 100644 --- a/src/helpers/parser/index.ts +++ b/src/helpers/parser/index.ts @@ -1,10 +1,10 @@ /* Autogenerated Index */ -export { assignParents } from "./assignParents" -export { checkParserOpts } from "./checkParserOpts" -export { extractPosition } from "./extractPosition" -export { getUnclosedRightParenCount } from "./getUnclosedRightParenCount" -export { parseParserOptions } from "./parseParserOptions" -export { seal } from "./seal" -export { setParent } from "./setParent" -export { unescape } from "./unescape" +export { assignParents } from "./assignParents.js" +export { checkParserOpts } from "./checkParserOpts.js" +export { extractPosition } from "./extractPosition.js" +export { getUnclosedRightParenCount } from "./getUnclosedRightParenCount.js" +export { parseParserOptions } from "./parseParserOptions.js" +export { seal } from "./seal.js" +export { setParent } from "./setParent.js" +export { unescape } from "./unescape.js" diff --git a/src/helpers/parser/parseParserOptions.ts b/src/helpers/parser/parseParserOptions.ts index 564f49c..24a3ff5 100644 --- a/src/helpers/parser/parseParserOptions.ts +++ b/src/helpers/parser/parseParserOptions.ts @@ -1,6 +1,8 @@ -import { defaultConditionNormalizer, defaultKeyParser, defaultPrefixApplier, defaultValueComparer } from "@/helpers/general" -import type { FullParserOptions, ParserOptions } from "@/types/parser" - +import type { FullParserOptions, ParserOptions } from "../../types/parser.js" +import { defaultConditionNormalizer } from "../general/defaultConditionNormalizer.js" +import { defaultKeyParser } from "../general/defaultKeyParser.js" +import { defaultPrefixApplier } from "../general/defaultPrefixApplier.js" +import { defaultValueComparer } from "../general/defaultValueComparer.js" /** @internal */ export function parseParserOptions( diff --git a/src/helpers/parser/seal.ts b/src/helpers/parser/seal.ts index a682c4f..ec3efce 100644 --- a/src/helpers/parser/seal.ts +++ b/src/helpers/parser/seal.ts @@ -1,8 +1,7 @@ -import { assignParents } from "./assignParents" - -import { Node } from "@/ast/classes" -import type { AnyToken, Nodes } from "@/types" +import { assignParents } from "./assignParents.js" +import { Node } from "../../ast/classes/Node.js" +import type { AnyToken, Nodes } from "../../types/ast.js" /** * set and "seals" all parent properties diff --git a/src/index.ts b/src/index.ts index 169b32c..678b410 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ /* Manually Generated Index */ -export * as ast from "./ast/classes" -export * as grammar from "./grammar" -export { Parser } from "./parser" -export * from "./types" -export * as utils from "./utils" +export * as ast from "./ast/classes/index.js" +export * as grammar from "./grammar/index.js" +export { Parser } from "./parser.js" +export * from "./types/index.js" +export * as utils from "./utils/index.js" diff --git a/src/methods/autocomplete.ts b/src/methods/autocomplete.ts index 8a4661a..753f364 100644 --- a/src/methods/autocomplete.ts +++ b/src/methods/autocomplete.ts @@ -1,8 +1,10 @@ -import { unreachable } from "@utils/utils" +import { unreachable } from "@alanscodelog/utils" -import { ConditionNode, VariableNode } from "@/ast/classes" -import type { Parser } from "@/parser" -import { Completion, FullParserOptions, Suggestion, SUGGESTION_TYPE } from "@/types" +import { ConditionNode } from "../ast/classes/ConditionNode.js" +import { VariableNode } from "../ast/classes/VariableNode.js" +import type { Parser } from "../parser.js" +import { type Completion, type Suggestion, SUGGESTION_TYPE } from "../types/autocomplete.js" +import type { FullParserOptions } from "../types/parser.js" export class AutocompleteMixin { diff --git a/src/methods/autoreplace.ts b/src/methods/autoreplace.ts index 4c81fb4..ffe5483 100644 --- a/src/methods/autoreplace.ts +++ b/src/methods/autoreplace.ts @@ -1,6 +1,6 @@ -import { insert } from "@utils/utils" +import { insert } from "@alanscodelog/utils" -import type { Completion } from "@/types" +import type { Completion } from "../types/autocomplete.js" export class AutoreplaceMixin { diff --git a/src/methods/autosuggest.ts b/src/methods/autosuggest.ts index d345c71..dbcbbfd 100644 --- a/src/methods/autosuggest.ts +++ b/src/methods/autosuggest.ts @@ -1,11 +1,20 @@ -import type { DeepPartial } from "@utils/types" -import { unreachable } from "@utils/utils" - -import { pos } from "@/ast/builders" -import { ArrayNode, ConditionNode, ErrorToken, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import type { Parser } from "@/parser" -import { KeywordEntry, ParserResults, Suggestion, SUGGESTION_TYPE, TOKEN_TYPE } from "@/types" -import { extractTokens, getCursorInfo, getSurroundingErrors } from "@/utils" +import type { DeepPartial } from "@alanscodelog/utils" +import { unreachable } from "@alanscodelog/utils" + +import { pos } from "../ast/builders/pos.js" +import { ArrayNode } from "../ast/classes/ArrayNode.js" +import { ConditionNode } from "../ast/classes/ConditionNode.js" +import { ErrorToken } from "../ast/classes/ErrorToken.js" +import { GroupNode } from "../ast/classes/GroupNode.js" +import type { ValidToken } from "../ast/classes/ValidToken.js" +import { VariableNode } from "../ast/classes/VariableNode.js" +import type { Parser } from "../parser.js" +import { type ParserResults, TOKEN_TYPE } from "../types/ast.js" +import { type Suggestion, SUGGESTION_TYPE } from "../types/autocomplete.js" +import type { KeywordEntry } from "../types/parser.js" +import { extractTokens } from "../utils/extractTokens.js" +import { getCursorInfo } from "../utils/getCursorInfo.js" +import { getSurroundingErrors } from "../utils/getSurroundingErrors.js" const defaultNodeDirs = { diff --git a/src/methods/evaluate.ts b/src/methods/evaluate.ts index ae62326..951a274 100644 --- a/src/methods/evaluate.ts +++ b/src/methods/evaluate.ts @@ -1,9 +1,9 @@ -import { get, unreachable } from "@utils/utils" +import { type AddParameters, get, unreachable } from "@alanscodelog/utils" -import { Expression } from "@/ast/classes" -import { Condition } from "@/ast/classes/Condition" -import type { Parser } from "@/parser" -import { AddParameters, TOKEN_TYPE } from "@/types" +import { Condition } from "../ast/classes/Condition.js" +import { Expression } from "../ast/classes/Expression.js" +import type { Parser } from "../parser.js" +import { TOKEN_TYPE } from "../types/ast.js" export class EvaluateMixin { diff --git a/src/methods/getIndexes.ts b/src/methods/getIndexes.ts index cfc6b6d..e26d809 100644 --- a/src/methods/getIndexes.ts +++ b/src/methods/getIndexes.ts @@ -1,10 +1,10 @@ /* eslint-disable no-labels */ -import type { AddParameters } from "@utils/types" -import { unreachable } from "@utils/utils" +import { type AddParameters, unreachable } from "@alanscodelog/utils" -import { Condition, Expression } from "@/ast/classes" -import { TOKEN_TYPE } from "@/types" +import { Condition } from "../ast/classes/Condition.js" +import { Expression } from "../ast/classes/Expression.js" +import { TOKEN_TYPE } from "../types/ast.js" export class GetIndexMixin { diff --git a/src/methods/index.ts b/src/methods/index.ts index c851012..6c4f34e 100644 --- a/src/methods/index.ts +++ b/src/methods/index.ts @@ -1,10 +1,10 @@ /* Autogenerated Index */ -export { AutocompleteMixin } from "./autocomplete" -export { AutoreplaceMixin } from "./autoreplace" -export { Autosuggest } from "./autosuggest" -export { EvaluateMixin } from "./evaluate" -export { GetBestIndexesMixin } from "./getBestIndex" -export { GetIndexMixin } from "./getIndexes" -export { NormalizeMixin } from "./normalize" -export { ValidateMixin } from "./validate" +export { AutocompleteMixin } from "./autocomplete.js" +export { AutoreplaceMixin } from "./autoreplace.js" +export { Autosuggest } from "./autosuggest.js" +export { EvaluateMixin } from "./evaluate.js" +export { GetBestIndexesMixin } from "./getBestIndex.js" +export { GetIndexMixin } from "./getIndexes.js" +export { NormalizeMixin } from "./normalize.js" +export { ValidateMixin } from "./validate.js" diff --git a/src/methods/normalize.ts b/src/methods/normalize.ts index 6cc5b77..b2080a9 100644 --- a/src/methods/normalize.ts +++ b/src/methods/normalize.ts @@ -1,10 +1,19 @@ -import { unreachable } from "@utils/utils" +import { type AddParameters, unreachable } from "@alanscodelog/utils" -import { ArrayNode, Condition, ConditionNode, ErrorToken, Expression, ExpressionNode, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import { applyBoolean, applyPrefix } from "@/helpers/general" -import { unescape } from "@/helpers/parser" -import type { Parser } from "@/parser" -import { AddParameters, ParserResults, TOKEN_TYPE, TokenBooleanTypes, ValueQuery } from "@/types" +import { ArrayNode } from "../ast/classes/ArrayNode.js" +import { Condition } from "../ast/classes/Condition.js" +import { ConditionNode } from "../ast/classes/ConditionNode.js" +import { ErrorToken } from "../ast/classes/ErrorToken.js" +import { Expression } from "../ast/classes/Expression.js" +import { ExpressionNode } from "../ast/classes/ExpressionNode.js" +import { GroupNode } from "../ast/classes/GroupNode.js" +import { ValidToken } from "../ast/classes/ValidToken.js" +import { VariableNode } from "../ast/classes/VariableNode.js" +import { applyBoolean } from "../helpers/general/applyBoolean.js" +import { applyPrefix } from "../helpers/general/applyPrefix.js" +import type { Parser } from "../parser.js" +import { type ParserResults, TOKEN_TYPE, type TokenBooleanTypes } from "../types/ast.js" +import type { ValueQuery } from "../types/parser.js" const OPPOSITE = { @@ -70,7 +79,7 @@ export class NormalizeMixin { ? unescape(ast.value.prefix.value) : undefined // one or the other might be defined, but never both since nested properties (e.g. `prop:op(prop:op(...))`) are not allowed - operator = operator ?? ast.propertyOperator?.value + operator ??= ast.propertyOperator?.value const isRegex = (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX const isQuoted = (ast.value as VariableNode)?.quote !== undefined const isExpanded = ast.sep !== undefined diff --git a/src/methods/validate.ts b/src/methods/validate.ts index b7956fe..655fd66 100644 --- a/src/methods/validate.ts +++ b/src/methods/validate.ts @@ -1,10 +1,17 @@ -import { get, isArray } from "@utils/utils" +import { type AddParameters, get, isArray } from "@alanscodelog/utils" -import { ArrayNode, ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import { applyBoolean, applyPrefix } from "@/helpers/general" -import { unescape } from "@/helpers/parser" -import type { Parser } from "@/parser" -import { AddParameters, ParserResults, Position, TOKEN_TYPE, ValidationQuery } from "@/types" +import { ArrayNode } from "../ast/classes/ArrayNode.js" +import { ConditionNode } from "../ast/classes/ConditionNode.js" +import { ErrorToken } from "../ast/classes/ErrorToken.js" +import { ExpressionNode } from "../ast/classes/ExpressionNode.js" +import { GroupNode } from "../ast/classes/GroupNode.js" +import { ValidToken } from "../ast/classes/ValidToken.js" +import { VariableNode } from "../ast/classes/VariableNode.js" +import { applyBoolean } from "../helpers/general/applyBoolean.js" +import { applyPrefix } from "../helpers/general/applyPrefix.js" +import type { Parser } from "../parser.js" +import { type ParserResults, type Position, TOKEN_TYPE } from "../types/ast.js" +import type { ValidationQuery } from "../types/parser.js" export class ValidateMixin { @@ -74,7 +81,7 @@ export class ValidateMixin { const valuePrefix = ast.value instanceof VariableNode && ast.value.prefix ? ast.value.prefix : undefined - operator = operator ?? ast.propertyOperator as ValidToken + operator ??= ast.propertyOperator as ValidToken const isRegex = (ast.value as VariableNode)?.quote?.left.type === TOKEN_TYPE.REGEX const isQuoted = (ast.value as VariableNode)?.quote !== undefined const isExpanded = ast.sep !== undefined diff --git a/src/package.js b/src/package.js index f1f113a..7030a40 100644 --- a/src/package.js +++ b/src/package.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-restricted-imports import pkg from "../package.json" /** diff --git a/src/parser.ts b/src/parser.ts index 537fb4a..1c734cf 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -9,18 +9,27 @@ * Docs work like normal (on methods). From the outside, users of the library cannot even tell the class is composed of mixins. */ -import type { Mixin } from "@utils/types" -import { isWhitespace, mixin } from "@utils/utils" -import { createSyntaxDiagramsCode, ILexingResult, Lexer } from "chevrotain" +import type { Mixin } from "@alanscodelog/utils" +import { isWhitespace, mixin } from "@alanscodelog/utils" +import { createSyntaxDiagramsCode, type ILexingResult, type Lexer } from "chevrotain" -import { NormalizeMixin } from "./methods/normalize" - -import { token as tokenHandler } from "@/ast/handlers" -import { createTokens, ParserBase } from "@/grammar" -import { BooleanParserLibraryError } from "@/helpers" -import { checkParserOpts, getUnclosedRightParenCount, parseParserOptions, seal } from "@/helpers/parser" -import { AutocompleteMixin, AutoreplaceMixin, Autosuggest, EvaluateMixin, GetBestIndexesMixin, GetIndexMixin, ValidateMixin } from "@/methods" -import { ERROR_CODES, FullParserOptions, ParserOptions, ParserResults } from "@/types" +import { token as tokenHandler } from "./ast/handlers.js" +import { createTokens } from "./grammar/createTokens.js" +import { ParserBase } from "./grammar/ParserBase.js" +import { BooleanParserLibraryError } from "./helpers/errors.js" +import { checkParserOpts } from "./helpers/parser/checkParserOpts.js" +import { getUnclosedRightParenCount } from "./helpers/parser/getUnclosedRightParenCount.js" +import { parseParserOptions, seal } from "./helpers/parser/index.js" +import { AutocompleteMixin } from "./methods/autocomplete.js" +import { AutoreplaceMixin } from "./methods/autoreplace.js" +import { Autosuggest } from "./methods/autosuggest.js" +import { EvaluateMixin } from "./methods/evaluate.js" +import { GetBestIndexesMixin } from "./methods/getBestIndex.js" +import { GetIndexMixin } from "./methods/getIndexes.js" +import { NormalizeMixin, ValidateMixin } from "./methods/index.js" +import type { ParserResults } from "./types/ast.js" +import { ERROR_CODES } from "./types/errors.js" +import type { FullParserOptions, ParserOptions } from "./types/parser.js" /** @@ -28,11 +37,17 @@ import { ERROR_CODES, FullParserOptions, ParserOptions, ParserResults } from "@/ */ export class Parser { options: FullParserOptions + private readonly rawOptions: ParserOptions + parser: ParserBase + private readonly lexer: Lexer + private readonly tokens: ReturnType["tokens"] + info: ReturnType["info"] + constructor(options?: ParserOptions) { this.rawOptions = options ?? {} const opts = parseParserOptions(this.rawOptions) @@ -44,6 +59,7 @@ export class Parser { this.info = info this.parser = new ParserBase(opts, this.tokens, this.info) } + /** * Parses a string. */ @@ -91,8 +107,10 @@ export class Parser { throw err } } + // needed for evaluate and validate so they are only checked on demand private evaluationOptionsChecked: boolean = false + // eslint-disable-next-line @typescript-eslint/naming-convention _checkEvaluationOptions(): void { if (!this.evaluationOptionsChecked) { @@ -100,7 +118,9 @@ export class Parser { this.evaluationOptionsChecked = true } } + private validationOptionsChecked: boolean = false + // eslint-disable-next-line @typescript-eslint/naming-convention _checkValidationOptions(): void { if (!this.validationOptionsChecked) { @@ -108,6 +128,7 @@ export class Parser { this.validationOptionsChecked = true } } + /** * Generates a railroad diagram for debugging. Does not 100% represent how things are actually handled internally. * @@ -120,6 +141,7 @@ export class Parser { const html = createSyntaxDiagramsCode(serialized) return html } + /** * For debugging. * Not exposed because it returns the raw chevrotain tokens. diff --git a/src/types/ast.ts b/src/types/ast.ts index 06d5d6f..d4886db 100644 --- a/src/types/ast.ts +++ b/src/types/ast.ts @@ -1,7 +1,12 @@ -import type { AnyFunction } from "@utils/types" - -import type { ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import type { ArrayNode } from "@/ast/classes/ArrayNode" +import type { AnyFunction } from "@alanscodelog/utils" + +import type { ArrayNode } from "../ast/classes/ArrayNode.js" +import type { ConditionNode } from "../ast/classes/ConditionNode.js" +import type { ErrorToken } from "../ast/classes/ErrorToken.js" +import type { ExpressionNode } from "../ast/classes/ExpressionNode.js" +import type { GroupNode } from "../ast/classes/GroupNode.js" +import type { ValidToken } from "../ast/classes/ValidToken.js" +import type { VariableNode } from "../ast/classes/VariableNode.js" export type AddParameters = (...args: [...Parameters, ...TExtra]) => ReturnType diff --git a/src/types/autocomplete.ts b/src/types/autocomplete.ts index 0fa9841..3d58e27 100644 --- a/src/types/autocomplete.ts +++ b/src/types/autocomplete.ts @@ -1,6 +1,6 @@ -import type { AnyToken, Position } from "./ast" +import type { AnyToken, Position } from "./ast.js" -import type { ValidToken } from "@/ast/classes" +import type { ValidToken } from "../ast/classes/ValidToken.js" /** diff --git a/src/types/errors.ts b/src/types/errors.ts index 2cfa33e..eeb0449 100644 --- a/src/types/errors.ts +++ b/src/types/errors.ts @@ -1,7 +1,7 @@ -import type { DeepPartial } from "@utils/types" +import type { DeepPartial } from "@alanscodelog/utils" import type { ILexingError, IRecognitionException, IToken } from "chevrotain" -import type { ParserOptions } from "./parser" +import type { ParserOptions } from "./parser.js" export enum ERROR_CODES { diff --git a/src/types/index.ts b/src/types/index.ts index 7469505..9ea9793 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,7 +1,6 @@ -/** @packageDocumentation @module types @preferred */ /* Autogenerated Index [Types] */ -export * from "./ast" -export * from "./autocomplete" -export * from "./errors" -export * from "./parser" +export * from "./ast.js" +export * from "./autocomplete.js" +export * from "./errors.js" +export * from "./parser.js" diff --git a/src/types/parser.ts b/src/types/parser.ts index 50b2564..eac41cb 100644 --- a/src/types/parser.ts +++ b/src/types/parser.ts @@ -1,8 +1,8 @@ -import type { DeepRequired, MakeRequired } from "@utils/types" +import type { DeepRequired, MakeRequired } from "@alanscodelog/utils" -import type { Position, TOKEN_TYPE } from "./ast" +import type { Position, TOKEN_TYPE } from "./ast.js" -import type { ArrayNode, Condition, ConditionNode, ValidToken, VariableNode } from "@/ast/classes" +import type { ArrayNode, Condition, ConditionNode, ValidToken, VariableNode } from "../ast/classes/index.js" // #partially-synced diff --git a/src/utils/extractTokens.ts b/src/utils/extractTokens.ts index 60a3c47..be4f3d7 100644 --- a/src/utils/extractTokens.ts +++ b/src/utils/extractTokens.ts @@ -1,7 +1,13 @@ -import { unreachable } from "@utils/utils" +import { unreachable } from "@alanscodelog/utils" -import { ArrayNode, ConditionNode, ErrorToken, ExpressionNode, GroupNode, Node, VariableNode } from "@/ast/classes" -import type { AnyToken, AST_TYPE } from "@/types" +import { ArrayNode } from "../ast/classes/ArrayNode.js" +import { ConditionNode } from "../ast/classes/ConditionNode.js" +import { ErrorToken } from "../ast/classes/ErrorToken.js" +import { ExpressionNode } from "../ast/classes/ExpressionNode.js" +import { GroupNode } from "../ast/classes/GroupNode.js" +import { Node } from "../ast/classes/Node.js" +import { VariableNode } from "../ast/classes/VariableNode.js" +import type { AnyToken, AST_TYPE } from "../types/ast.js" /** diff --git a/src/utils/getCursorInfo.ts b/src/utils/getCursorInfo.ts index b2fd64c..4b67c1e 100644 --- a/src/utils/getCursorInfo.ts +++ b/src/utils/getCursorInfo.ts @@ -1,9 +1,10 @@ -import { isArray, unreachable } from "@utils/utils" +import { isArray, unreachable } from "@alanscodelog/utils" -import { ErrorToken, ValidToken } from "@/ast/classes" -import type { AnyToken, CursorInfo, ParserResults } from "@/types" +import { extractTokens } from "./extractTokens.js" -import { extractTokens } from "." +import { ErrorToken, ValidToken } from "../ast/classes/index.js" +import type { AnyToken, ParserResults } from "../types/ast.js" +import type { CursorInfo } from "../types/autocomplete.js" /** @@ -55,9 +56,7 @@ export function getCursorInfo( } } if (token.start >= index) { - if (!info.next) { - info.next = token - } + info.next ||= token if (token instanceof ValidToken && !info.valid.next) { info.valid.next = token break diff --git a/src/utils/getOppositeDelimiter.ts b/src/utils/getOppositeDelimiter.ts index 4af479b..ab5eccf 100644 --- a/src/utils/getOppositeDelimiter.ts +++ b/src/utils/getOppositeDelimiter.ts @@ -1,13 +1,12 @@ -import { unreachable } from "@utils/utils" +import { unreachable } from "@alanscodelog/utils" -import { isBracket } from "./isBracket" -import { isDelimiter } from "./isDelimiter" -import { isParen } from "./isParen" -import { isQuote } from "./isQuote" - -import type { ArrayNode, ConditionNode, GroupNode, VariableNode } from "@/ast/classes" -import { AnyToken, TOKEN_TYPE, TokenDelimiterTypes } from "@/types" +import { isBracket } from "./isBracket.js" +import { isDelimiter } from "./isDelimiter.js" +import { isParen } from "./isParen.js" +import { isQuote } from "./isQuote.js" +import type { ArrayNode, ConditionNode, GroupNode, VariableNode } from "../ast/classes/index.js" +import { type AnyToken, TOKEN_TYPE, type TokenDelimiterTypes } from "../types/ast.js" /** * Given a delimiter token, returns it's opposite pair, or undefined if the type passed was not a delimiter token (so you can pass any type without checking). diff --git a/src/utils/getSurroundingErrors.ts b/src/utils/getSurroundingErrors.ts index 046c573..2a8d5b5 100644 --- a/src/utils/getSurroundingErrors.ts +++ b/src/utils/getSurroundingErrors.ts @@ -1,6 +1,3 @@ -import { ErrorToken } from "@/ast/classes" -import { AnyToken, CursorInfo, TOKEN_TYPE } from "@/types" - /** * Mostly for internal use by @see autosuggest. * @@ -22,6 +19,11 @@ import { AnyToken, CursorInfo, TOKEN_TYPE } from "@/types" * ``` */ +import { ErrorToken } from "../ast/classes/ErrorToken.js" +import { type AnyToken, TOKEN_TYPE } from "../types/ast.js" +import type { CursorInfo } from "../types/autocomplete.js" + + export function getSurroundingErrors(tokens: AnyToken[], token: CursorInfo): ErrorToken[] { if (token.at) {return []} const i = tokens.indexOf(token.next ?? token.prev as any) diff --git a/src/utils/index.ts b/src/utils/index.ts index 6dee158..d572739 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,11 +1,11 @@ /* Autogenerated Index */ -export { extractTokens } from "./extractTokens" -export { getCursorInfo } from "./getCursorInfo" -export { getOppositeDelimiter } from "./getOppositeDelimiter" -export { getSurroundingErrors } from "./getSurroundingErrors" -export { isBracket } from "./isBracket" -export { isDelimiter } from "./isDelimiter" -export { isParen } from "./isParen" -export { isQuote } from "./isQuote" -export { prettyAst } from "./prettyAst" +export { extractTokens } from "./extractTokens.js" +export { getCursorInfo } from "./getCursorInfo.js" +export { getOppositeDelimiter } from "./getOppositeDelimiter.js" +export { getSurroundingErrors } from "./getSurroundingErrors.js" +export { isBracket } from "./isBracket.js" +export { isDelimiter } from "./isDelimiter.js" +export { isParen } from "./isParen.js" +export { isQuote } from "./isQuote.js" +export { prettyAst } from "./prettyAst.js" diff --git a/src/utils/isBracket.ts b/src/utils/isBracket.ts index 0acffdc..bbf4f67 100644 --- a/src/utils/isBracket.ts +++ b/src/utils/isBracket.ts @@ -1,4 +1,4 @@ -import { AnyToken, TOKEN_TYPE, TokenBracketTypes } from "@/types" +import { type AnyToken, TOKEN_TYPE, type TokenBracketTypes } from "../types/ast.js" export function isBracket(token?: AnyToken): token is AnyToken { diff --git a/src/utils/isDelimiter.ts b/src/utils/isDelimiter.ts index 39f7a39..fdecde4 100644 --- a/src/utils/isDelimiter.ts +++ b/src/utils/isDelimiter.ts @@ -1,4 +1,4 @@ -import { AnyToken, TOKEN_TYPE, TokenDelimiterTypes } from "@/types" +import { type AnyToken, TOKEN_TYPE, type TokenDelimiterTypes } from "../types/ast.js" /** * Returns whether token is a delimiter type (including if it's an expanded operator separator). diff --git a/src/utils/isParen.ts b/src/utils/isParen.ts index c6b6f44..05fd4d5 100644 --- a/src/utils/isParen.ts +++ b/src/utils/isParen.ts @@ -1,4 +1,4 @@ -import { AnyToken, TOKEN_TYPE, TokenParenTypes } from "@/types" +import { type AnyToken, TOKEN_TYPE, type TokenParenTypes } from "../types/ast.js" export function isParen(token?: AnyToken): token is AnyToken { diff --git a/src/utils/isQuote.ts b/src/utils/isQuote.ts index 83e9bed..047cc29 100644 --- a/src/utils/isQuote.ts +++ b/src/utils/isQuote.ts @@ -1,4 +1,4 @@ -import { AnyToken, TOKEN_TYPE, TokenQuoteTypes } from "@/types" +import { type AnyToken, TOKEN_TYPE, type TokenQuoteTypes } from "../types/ast.js" /** Returns if the token is a quote token. This includes regex delimiters. */ export function isQuote(token?: AnyToken): token is AnyToken { diff --git a/src/utils/prettyAst.ts b/src/utils/prettyAst.ts index 4d09953..83b6f05 100644 --- a/src/utils/prettyAst.ts +++ b/src/utils/prettyAst.ts @@ -1,9 +1,9 @@ /* eslint-disable prefer-rest-params */ -import { AddParameters, colors as color } from "@alanscodelog/utils" -import { isBlank, unreachable } from "@utils/utils" +import { type AddParameters, colors as color } from "@alanscodelog/utils" +import { isBlank, unreachable } from "@alanscodelog/utils" -import { ArrayNode, ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import { AnyToken, ParserResults, TOKEN_TYPE } from "@/types" +import { ArrayNode, ConditionNode, ErrorToken, ExpressionNode, GroupNode, ValidToken, VariableNode } from "../ast/classes/index.js" +import { type AnyToken, type ParserResults, TOKEN_TYPE } from "../types/ast.js" type Colors = { diff --git a/tests/.eslintrc.js b/tests/.eslintrc.cjs similarity index 52% rename from tests/.eslintrc.js rename to tests/.eslintrc.cjs index fe8dfbf..6d37e7b 100644 --- a/tests/.eslintrc.js +++ b/tests/.eslintrc.cjs @@ -1,12 +1,12 @@ +/** @type {import('@typescript-eslint/utils').TSESLint.Linter.Config} */ module.exports = { root: false, - env: { - jest: true, - }, extends: [ // ./node_modules/@alanscodelog/eslint-config/tests.js "@alanscodelog/eslint-config/tests", ], - rules: { + parserOptions: { + // wut + project: "./tsconfig.eslint.json", }, } diff --git a/tests/array values.spec.ts b/tests/array values.spec.ts index a00f147..3d25e59 100644 --- a/tests/array values.spec.ts +++ b/tests/array values.spec.ts @@ -1,11 +1,11 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { findPos, t, v } from "./utils" +import { findPos, t, v } from "./utils.js" -import { array, condition, delim, variable } from "@/ast/builders" -import { Parser } from "@/index" -import { TOKEN_TYPE } from "@/types" +import { array, condition, delim, variable } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" +import { TOKEN_TYPE } from "../src/types/ast.js" // more related tests are in ./property operators diff --git a/tests/chai.ts b/tests/chai.ts deleted file mode 100644 index 0c2b535..0000000 --- a/tests/chai.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { partialDeepEqual } from "@utils/testing" -import chai from "chai" - - -chai.use(partialDeepEqual) -// eslint-disable-next-line import/no-default-export -export default chai -export const expect = chai.expect diff --git a/tests/cursorInfo-autosuggest-autocomplete-autoreplace.spec.ts b/tests/cursorInfo-autosuggest-autocomplete-autoreplace.spec.ts index 791a816..9baff4f 100644 --- a/tests/cursorInfo-autosuggest-autocomplete-autoreplace.spec.ts +++ b/tests/cursorInfo-autosuggest-autocomplete-autoreplace.spec.ts @@ -1,14 +1,14 @@ /* eslint-disable max-lines */ -import { catchError, testName } from "@utils/testing" -import type { DeepPartial } from "@utils/types" +import type { DeepPartial } from "@alanscodelog/utils" +import { catchError, testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { findPos } from "./utils" +import { findPos } from "./utils.js" -import { Parser } from "@/index" -import type { AnyToken, Position } from "@/types" -import { CursorInfo, Suggestion, SUGGESTION_TYPE } from "@/types/autocomplete" -import { getCursorInfo } from "@/utils" +import { Parser } from "../src/parser.js" +import type { AnyToken, Position } from "../src/types/ast.js" +import { type CursorInfo, type Suggestion, SUGGESTION_TYPE } from "../src/types/autocomplete.js" +import { getCursorInfo } from "../src/utils/getCursorInfo.js" const emptyCursor: Omit = Object.freeze({ diff --git a/tests/escaping.spec.ts b/tests/escaping.spec.ts index 3d77378..7292f8f 100644 --- a/tests/escaping.spec.ts +++ b/tests/escaping.spec.ts @@ -1,16 +1,16 @@ -import { testName } from "@utils/testing" -import { multisplice } from "@utils/utils" +import { multisplice, testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { checkVariables, e, t, unquoted, v } from "./utils" +import { checkVariables, e, t, unquoted, v } from "./utils.js" -import { condition, delim, expression, pos } from "@/ast/builders" -import { Parser } from "@/index" +import { condition, delim, expression, pos } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" const allQuotes = ["`", "'", `"`] const delims = ["(", ")", "["] // "]" not technically delim unless preceded by [ so will leave out for these tests const requireEscape = ["/", " ", "\n", "\t", "\r"] + describe(testName({ __filename }), () => { it(`escaped symbols`, () => { checkVariables([ diff --git a/tests/evaluate-validate.spec.ts b/tests/evaluate-validate.spec.ts index 2f3006a..d7252a7 100644 --- a/tests/evaluate-validate.spec.ts +++ b/tests/evaluate-validate.spec.ts @@ -1,13 +1,16 @@ -import { testName } from "@utils/testing" -import { get, isArray, unreachable } from "@utils/utils" +import { get, isArray, testName, unreachable } from "@alanscodelog/utils" +import { describe, expect, it, vi } from "vitest" -import { nCondition, nExpression } from "./utils" +import { nCondition, nExpression } from "./utils.js" -import { GroupNode, ValidToken, VariableNode } from "@/ast/classes" -import { applyBoolean, defaultConditionNormalizer, defaultValueComparer } from "@/helpers/general" -import { Parser } from "@/index" -import type { FullParserOptions, ValidationQuery, ValueValidator } from "@/types" -import { expect } from "@tests/chai" +import type { GroupNode } from "../src/ast/classes/GroupNode.js" +import { ValidToken } from "../src/ast/classes/ValidToken.js" +import { VariableNode } from "../src/ast/classes/VariableNode.js" +import { applyBoolean } from "../src/helpers/general/applyBoolean.js" +import { defaultConditionNormalizer } from "../src/helpers/general/defaultConditionNormalizer.js" +import { defaultValueComparer } from "../src/helpers/general/defaultValueComparer.js" +import { Parser } from "../src/parser.js" +import type { FullParserOptions, ValidationQuery, ValueValidator } from "../src/types/parser.js" describe(testName(), () => { @@ -188,7 +191,7 @@ describe(testName(), () => { describe("custom validation", () => { it("a(b:val)", () => { const input = "a(b:val)" - const valueValidator = jest.fn((_contextValue: string, query: ValidationQuery) => { + const valueValidator = vi.fn((_contextValue: string, query: ValidationQuery) => { expect(query.value).to.be.instanceof(VariableNode) expect(query.property[0]).to.be.instanceof(VariableNode) expect(query.property[1]).to.be.instanceof(VariableNode) @@ -210,7 +213,7 @@ describe(testName(), () => { }) it("a(b)", () => { const input = "a(b)" - const valueValidator = jest.fn((_contextValue: string, query: ValidationQuery) => { + const valueValidator = vi.fn((_contextValue: string, query: ValidationQuery) => { expect(query.property[0]).to.be.instanceof(VariableNode) expect(query.property[1]).to.be.instanceof(VariableNode) expect(query.property[0].value.value).to.equal("a") @@ -231,7 +234,7 @@ describe(testName(), () => { }) it(`a(prefix"b")`, () => { const input = `a(prefix"b")` - const valueValidator = jest.fn((_contextValue: string | undefined, query: ValidationQuery) => { + const valueValidator = vi.fn((_contextValue: string | undefined, query: ValidationQuery) => { expect(query.property[0]).to.be.instanceof(VariableNode) expect(query.property[1]).to.be.instanceof(VariableNode) expect(query.property[0].value.value).to.equal("a") @@ -279,7 +282,7 @@ describe(testName(), () => { }) it(`a(c(d)) || e - partial prefix "highlighting"`, () => { const input = `a(c(d)) || e` - const valueValidator = jest.fn((_contextValue: string | undefined, query: ValidationQuery, context: any): any => { + const valueValidator = vi.fn((_contextValue: string | undefined, query: ValidationQuery, context: any): any => { const values = query.property.map(node => node.value.value) let i = 1 while (i < query.property.length && get(context, values.slice(0, i)) !== undefined) { diff --git a/tests/examples.spec.ts b/tests/examples.spec.ts index 6849d84..e9b2734 100644 --- a/tests/examples.spec.ts +++ b/tests/examples.spec.ts @@ -1,7 +1,7 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { ShortcutContextParser } from "@/examples/shortcutContextParser" -import { expect } from "@tests/chai" +import { ShortcutContextParser } from "../src/examples/shortcutContextParser.js" describe(testName(), () => { diff --git a/tests/groups.spec.ts b/tests/groups.spec.ts index 99713ec..62a751b 100644 --- a/tests/groups.spec.ts +++ b/tests/groups.spec.ts @@ -1,10 +1,10 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { e, t, v } from "./utils" +import { e, t, v } from "./utils.js" -import { condition, delim, expression, group } from "@/ast/builders" -import { Parser } from "@/index" +import { condition, delim, expression, group } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" const parser = new Parser() diff --git a/tests/helpers.spec.ts b/tests/helpers.spec.ts index c9eabed..332578a 100644 --- a/tests/helpers.spec.ts +++ b/tests/helpers.spec.ts @@ -1,9 +1,8 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" - -import { getUnclosedRightParenCount } from "@/helpers/parser" -import { Parser } from "@/index" +import { getUnclosedRightParenCount } from "../src/helpers/parser/getUnclosedRightParenCount.js" +import { Parser } from "../src/parser.js" describe(testName({ __filename }), () => { diff --git a/tests/indexes.spec.ts b/tests/indexes.spec.ts index 340e0f2..6b8efb5 100644 --- a/tests/indexes.spec.ts +++ b/tests/indexes.spec.ts @@ -1,9 +1,9 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" - -import { defaultConditionNormalizer, defaultValueComparer } from "@/helpers/general" -import { Parser } from "@/index" +import { defaultConditionNormalizer } from "../src/helpers/general/defaultConditionNormalizer.js" +import { defaultValueComparer } from "../src/helpers/general/defaultValueComparer.js" +import { Parser } from "../src/parser.js" const parser = new Parser({ diff --git a/tests/negations.spec.ts b/tests/negations.spec.ts index 77ff856..2c85353 100644 --- a/tests/negations.spec.ts +++ b/tests/negations.spec.ts @@ -1,30 +1,30 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { e, t, v } from "./utils" +import { e, t, v } from "./utils.js" -import { condition, expression, group } from "@/ast/builders" -import { Parser } from "@/index" +import { condition, expression, group } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" describe(testName({ __filename }), () => { it(`!`, () => { const input = `!` const expected = - condition( - e(input, "!", [""]), - t(input, "!"), - ) + condition( + e(input, "!", [""]), + t(input, "!"), + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`not a`, () => { const input = `not a` const expected = - condition( - v(input, "a"), - t(input, "not") - ) + condition( + v(input, "a"), + t(input, "not") + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) @@ -32,43 +32,43 @@ describe(testName({ __filename }), () => { it(`! a`, () => { const input = `! a` const expected = - condition( - v(input, "a"), - t(input, "!") - ) + condition( + v(input, "a"), + t(input, "!") + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`!a`, () => { const input = `!a` const expected = - condition( - v(input, "a"), - t(input, "!") - ) + condition( + v(input, "a"), + t(input, "!") + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`nota`, () => { const input = `nota` const expected = - condition( - v(input, "nota"), - true - ) + condition( + v(input, "nota"), + true + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`!(a)`, () => { const input = `!(a)` const expected = - group( - t(input, "!"), - condition( - v(input, "a"), - true - ) + group( + t(input, "!"), + condition( + v(input, "a"), + true ) + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) @@ -76,26 +76,26 @@ describe(testName({ __filename }), () => { it(`not(a)`, () => { const input = `not(a)` const expected = - group( - t(input, "not"), - condition( - v(input, "a"), - true - ) + group( + t(input, "not"), + condition( + v(input, "a"), + true ) + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`not (a)`, () => { const input = `not (a)` const expected = - group( - t(input, "not"), - condition( - v(input, "a"), - true - ) + group( + t(input, "not"), + condition( + v(input, "a"), + true ) + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) @@ -103,52 +103,52 @@ describe(testName({ __filename }), () => { const input = `not((a))` const ast = new Parser({ prefixableGroups: false }).parse(input) const expected = + group( + t(input, "not"), group( - t(input, "not"), - group( - undefined, - condition( - v(input, "a"), - true - ) + undefined, + condition( + v(input, "a"), + true ) ) + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`not(a || b)`, () => { const input = `not(a || b)` const expected = - group( - t(input, "not"), - expression( - condition( - v(input, "a") - ), - t(input, "||"), - condition( - v(input, "b") - ), - ) + group( + t(input, "not"), + expression( + condition( + v(input, "a") + ), + t(input, "||"), + condition( + v(input, "b") + ), ) + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) it(`! (a || b)`, () => { const input = `! (a || b)` const expected = - group( - t(input, "!"), - expression( - condition( - v(input, "a") - ), - t(input, "||"), - condition( - v(input, "b") - ), - ) + group( + t(input, "!"), + expression( + condition( + v(input, "a") + ), + t(input, "||"), + condition( + v(input, "b") + ), ) + ) expect(new Parser().parse(input)).to.deep.equal(expected) expect(new Parser({ prefixableGroups: false }).parse(input)).to.deep.equal(expected) }) diff --git a/tests/newFile.ts b/tests/newFile.ts new file mode 100644 index 0000000..94ca646 --- /dev/null +++ b/tests/newFile.ts @@ -0,0 +1,25 @@ +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" + +import { getUnclosedRightParenCount } from "../src/helpers/parser/getUnclosedRightParenCount.js" +import { Parser } from "../src/parser.js" + + +describe(testName({ __filename }), () => { + it("unclosedRightParenCount", () => { + const parser = new Parser() + // @ts-expect-error tokens is private + const tokens = parser.tokens + // @ts-expect-error lex is private + const lex = parser._lex.bind(parser) + + expect(getUnclosedRightParenCount(lex(")((())))))").tokens, tokens)).to.equal(4) + expect(getUnclosedRightParenCount(lex("()").tokens, tokens)).to.equal(0) + expect(getUnclosedRightParenCount(lex(")(").tokens, tokens)).to.equal(1) + expect(getUnclosedRightParenCount(lex("()))").tokens, tokens)).to.equal(2) + expect(getUnclosedRightParenCount(lex(")(((((((((((").tokens, tokens)).to.equal(1) + expect(getUnclosedRightParenCount(lex("\\)").tokens, tokens)).to.equal(0) + expect(getUnclosedRightParenCount(lex("\\(").tokens, tokens)).to.equal(0) + }) +}) + diff --git a/tests/optional whitespace.spec.ts b/tests/optional whitespace.spec.ts index 4b34aad..37ea263 100644 --- a/tests/optional whitespace.spec.ts +++ b/tests/optional whitespace.spec.ts @@ -1,10 +1,10 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { double, t, v } from "./utils" +import { double, t, v } from "./utils.js" -import { condition, delim, expression, group, pos } from "@/ast/builders" -import { Parser } from "@/index" +import { condition, delim, expression, group, pos } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" describe(testName({ __filename }), () => { @@ -12,66 +12,66 @@ describe(testName({ __filename }), () => { const input = " a " const ast = new Parser().parse(input) const expected = - condition( - v(input, "a") - ) + condition( + v(input, "a") + ) expect(ast).to.deep.equal(expected) }) it("a || b", () => { const input = "a || b" const ast = new Parser().parse(input) const expected = - expression( - condition( - v(input, "a") - ), - t(input, "||"), - condition( - v(input, "b") - ), - ) + expression( + condition( + v(input, "a") + ), + t(input, "||"), + condition( + v(input, "b") + ), + ) expect(ast).to.deep.equal(expected) }) it("( a )", () => { const input = "( a )" const ast = new Parser().parse(input) const expected = - group(undefined, - condition( - v(input, "a") - ), - undefined, - pos(0, 1), - pos(4, 5) - ) + group(undefined, + condition( + v(input, "a") + ), + undefined, + pos(0, 1), + pos(4, 5) + ) expect(ast).to.deep.equal(expected) }) it(`( "a" )`, () => { const input = `( "a" )` const ast = new Parser().parse(input) const expected = - group(undefined, - condition( - v(input, "a", delim(double, double)) - ), - undefined, - pos(0, 1), - pos(6, 7) - ) + group(undefined, + condition( + v(input, "a", delim(double, double)) + ), + undefined, + pos(0, 1), + pos(6, 7) + ) expect(ast).to.deep.equal(expected) }) it(`( " a " )`, () => { const input = `( " a " )` const ast = new Parser().parse(input) const expected = - group(undefined, - condition( - v(input, " a ", delim(double, double)) - ), - undefined, - pos(0, 1), - pos(8, 9) - ) + group(undefined, + condition( + v(input, " a ", delim(double, double)) + ), + undefined, + pos(0, 1), + pos(8, 9) + ) expect(ast).to.deep.equal(expected) }) @@ -79,12 +79,12 @@ describe(testName({ __filename }), () => { const input = `(" a ")` const ast = new Parser().parse(input) const expected = - group(undefined, - condition( - v(input, " a ", delim(double, double)) - ), - undefined, - ) + group(undefined, + condition( + v(input, " a ", delim(double, double)) + ), + undefined, + ) expect(ast).to.deep.equal(expected) }) }) diff --git a/tests/prefixable values.spec.ts b/tests/prefixable values.spec.ts index 02918ed..3ec2c43 100644 --- a/tests/prefixable values.spec.ts +++ b/tests/prefixable values.spec.ts @@ -1,10 +1,10 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { t, v } from "./utils" +import { t, v } from "./utils.js" -import { condition, delim } from "@/ast/builders" -import { Parser } from "@/index" +import { condition, delim } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" describe(testName({ __filename }), () => { diff --git a/tests/property operators.spec.ts b/tests/property operators.spec.ts index 4e1715d..e91cbb1 100644 --- a/tests/property operators.spec.ts +++ b/tests/property operators.spec.ts @@ -1,15 +1,13 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" import { performance } from "perf_hooks" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { e, findPos, t, v } from "./utils" - -import { array, condition, delim, group, token, variable } from "@/ast/builders" -import { Parser } from "@/index" -import { TOKEN_TYPE } from "@/types" -import { prettyAst } from "@/utils" - +import { e, findPos, t, v } from "./utils.js" +import { array, condition, delim, group, token, variable } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" +import { TOKEN_TYPE } from "../src/types/ast.js" +import { prettyAst } from "../src/utils/prettyAst.js" /** * Note: If prop and op are used in the test inputings, the helper functions will "incorrectly" find the op in prop instead of op, so that's why OP is used instead */ @@ -277,7 +275,7 @@ describe(testName({ __filename }), () => { e(input, ":", [TOKEN_TYPE.VALUE]), { left: t(input, ":", TOKEN_TYPE.OP_EXPANDED_SEP), - // right: undefined, // right is undefined because we don' know if we need another separator or not + // right: undefined, // right is undefined because we don' know if we need another separator or not } ) diff --git a/tests/regex values.spec.ts b/tests/regex values.spec.ts index 0e59c4b..34e3be3 100644 --- a/tests/regex values.spec.ts +++ b/tests/regex values.spec.ts @@ -1,11 +1,10 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { e, v } from "./utils" - -import { condition, delim, variable } from "@/ast/builders" -import { Parser } from "@/index" +import { e, v } from "./utils.js" +import { condition, delim, variable } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" // more related tests are in ./property operators describe(testName({ __filename }), () => { diff --git a/tests/simple expressions.spec.ts b/tests/simple expressions.spec.ts index f281c47..b8370d3 100644 --- a/tests/simple expressions.spec.ts +++ b/tests/simple expressions.spec.ts @@ -1,11 +1,11 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { checkVariables, e, t, unquoted, v } from "./utils" +import { checkVariables, e, t, unquoted, v } from "./utils.js" -import { condition, delim, expression, pos, token } from "@/ast/builders" -import { Parser } from "@/index" -import { TOKEN_TYPE } from "@/types" +import { condition, delim, expression, pos, token } from "../src/ast/builders/index.js" +import { Parser } from "../src/parser.js" +import { TOKEN_TYPE } from "../src/types/ast.js" describe(testName({ __filename }), () => { @@ -175,15 +175,15 @@ describe(testName({ __filename }), () => { const ast = new Parser({ onMissingBooleanOperator: "and" }).parse(input) const expected = - expression( - condition( - v(input, "a") - ), - token(TOKEN_TYPE.AND, "", { start: input.indexOf(" "), end: input.indexOf(" ") }), - condition( - v(input, "b") - ), - ) + expression( + condition( + v(input, "a") + ), + token(TOKEN_TYPE.AND, "", { start: input.indexOf(" "), end: input.indexOf(" ") }), + condition( + v(input, "b") + ), + ) expect(ast).deep.equal(expected) }) @@ -192,15 +192,15 @@ describe(testName({ __filename }), () => { const ast = new Parser({ onMissingBooleanOperator: "or" }).parse(input) const expected = - expression( - condition( - v(input, "a") - ), - token(TOKEN_TYPE.OR, "", { start: input.indexOf(" "), end: input.indexOf(" ") }), - condition( - v(input, "b") - ), - ) + expression( + condition( + v(input, "a") + ), + token(TOKEN_TYPE.OR, "", { start: input.indexOf(" "), end: input.indexOf(" ") }), + condition( + v(input, "b") + ), + ) expect(ast).deep.equal(expected) }) @@ -209,21 +209,21 @@ describe(testName({ __filename }), () => { const ast = new Parser(({ onMissingBooleanOperator: "and" })).parse(input) const expected = - expression( - condition( - v(input, "a") - ), - t(input, "&&"), expression( condition( - v(input, "b") + v(input, "a") ), - token(TOKEN_TYPE.AND, "", { start: input.indexOf(" c"), end: input.indexOf(" c") }), - condition( - v(input, "c") + t(input, "&&"), + expression( + condition( + v(input, "b") + ), + token(TOKEN_TYPE.AND, "", { start: input.indexOf(" c"), end: input.indexOf(" c") }), + condition( + v(input, "c") + ), ), - ), - ) + ) expect(ast).deep.equal(expected) }) it(`a && b c - onMissingBooleanOperator = or`, () => { @@ -231,21 +231,21 @@ describe(testName({ __filename }), () => { const ast = new Parser(({ onMissingBooleanOperator: "or" })).parse(input) const expected = - expression( expression( - condition( - v(input, "a") + expression( + condition( + v(input, "a") + ), + t(input, "&&"), + condition( + v(input, "b") + ), ), - t(input, "&&"), + token(TOKEN_TYPE.OR, "", { start: input.indexOf(" c"), end: input.indexOf(" c") }), condition( - v(input, "b") + v(input, "c") ), - ), - token(TOKEN_TYPE.OR, "", { start: input.indexOf(" c"), end: input.indexOf(" c") }), - condition( - v(input, "c") - ), - ) + ) expect(ast).deep.equal(expected) }) }) diff --git a/tests/template.ts b/tests/template.ts index dbfaad1..a1726d9 100644 --- a/tests/template.ts +++ b/tests/template.ts @@ -1,10 +1,10 @@ import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "@tests/chai" - -describe(testName(), () => { - it("missing tests", () => { +describe(testName({ __filename }), () => { + it("works", () => { expect(true).to.equal(false) }) }) + diff --git a/tests/utils.spec.ts b/tests/utils.spec.ts index e0f30ab..5be2535 100644 --- a/tests/utils.spec.ts +++ b/tests/utils.spec.ts @@ -1,10 +1,10 @@ -import { testName } from "@utils/testing" +import { testName } from "@alanscodelog/utils" +import { describe, expect, it } from "vitest" -import { expect } from "./chai" -import { e, t } from "./utils" +import { e, t } from "./utils.js" -import { Parser } from "@/index" -import { extractTokens } from "@/utils" +import { Parser } from "../src/parser.js" +import { extractTokens } from "../src/utils/extractTokens.js" describe(testName({ __filename }), () => { diff --git a/tests/utils.ts b/tests/utils.ts index 682f6c2..88378ac 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -1,12 +1,11 @@ -import type { DeepPartial } from "@utils/types" +import type { DeepPartial } from "@alanscodelog/utils" +import { expect } from "vitest" -import { expect } from "./chai" - -import { condition, pos, token, type, variable } from "@/ast/builders" -import { error } from "@/ast/builders/error" -import { Condition, ErrorToken, Expression, ValidToken, VariableNode } from "@/ast/classes" -import { Parser } from "@/index" -import { ExtractTokenType, ParserOptions, Position, TOKEN_TYPE } from "@/types" +import { condition, error, pos, token, type, variable } from "../src/ast/builders/index.js" +import { Condition, type ErrorToken, Expression, type ValidToken, type VariableNode } from "../src/ast/classes/index.js" +import { Parser } from "../src/parser.js" +import type { ExtractTokenType, ParserOptions, Position } from "../src/types/index.js" +import { TOKEN_TYPE } from "../src/types/index.js" // for delims @@ -44,7 +43,7 @@ export const checkVariables = ( */ export const t = ( input: string, value: T, tokenType?: TForceType -): TForceType extends TOKEN_TYPE ? ValidToken: ValidToken> => +): TForceType extends TOKEN_TYPE ? ValidToken : ValidToken> => token(tokenType ?? type(value) as any, value, findPos(input, value)) as any /** @@ -62,7 +61,7 @@ export const v = ( * Given the input, a string right before the error, and the expected token types, returns an error token. * */ -export const e = ( +export const e = ( input: string, beforeError: string, expected: T[] ): ErrorToken> => error>(findPos(input, beforeError).end, expected as any) diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 0000000..70ecb46 --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,13 @@ +{ + // Here partly because eslint tends to think vue files aren't included even when they explicitly are + // also here because I want to lint configs as well, but including them in the regular tsconfig can cause problems + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "baseUrl": "." + }, + "include": [ + "**/*", + "*" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 810686e..b0284e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,31 +1,23 @@ -// https://www.typescriptlang.org/v2/en/tsconfig +// https://www.typescriptlang.org/tsconfig/ { // ./node_modules/@alanscodelog/tsconfigs/tsconfig.json - // https://github.com/AlansCodeLog/my-tsconfigs + // https://github.com/AlansCodeLog/tsconfigs "extends": "@alanscodelog/tsconfigs", "compilerOptions": { - "esModuleInterop": true, - "baseUrl": ".", - "paths": { - "@/*": ["src/*"], - "@tests/*": ["tests/*"], - "@utils/*": [ "node_modules/@alanscodelog/utils/dist/*" ], - }, - "resolveJsonModule": true, - "downlevelIteration": true + "outDir": "dist", + // "types": [ + /* "node" */ + // ], + // the libs are explicitly specified because otherwise typescript includes the dom by default + "lib": [ + /* "dom", */ + "esnext" + ] }, - "types" : [ - "jest", - "node", - ], - "lib": [ - "esnext", - ], "include": [ "src/**/*.ts", "src/**/*.js", - "tests/**/*.ts", + "tests/**/*.ts" ], - "exclude": [ - ] + "exclude": [] } diff --git a/tsconfig.types.json b/tsconfig.types.json index 93840d4..fc3541c 100644 --- a/tsconfig.types.json +++ b/tsconfig.types.json @@ -1,17 +1,22 @@ -// https://www.typescriptlang.org/v2/en/tsconfig -// see https://github.com/babel/babel/issues/9668 for why a tsconfig specifically for types +// https://www.typescriptlang.org/tsconfig/ { "extends": "./tsconfig", "compilerOptions": { "outDir": "dist", + "rootDir": "src", "declaration": true, - "emitDeclarationOnly": true, - "noEmit": false, - "allowJs": false, "declarationMap": true, + // "emitDeclarationOnly": controlled by build/lint:types scripts which both need this config + "noEmit": false, // override value in ./tsconfig + "allowJs": false, + "skipLibCheck": true, // ignore node modules + // preserve documentation + "removeComments": false }, "exclude": [ - "tests/**/*.ts", - "**/*.js", - ] + "tests/**" + ], + "tsc-alias": { + "resolveFullPaths": true // for esm compatibility + } } diff --git a/typedoc.config.cjs b/typedoc.config.cjs new file mode 100644 index 0000000..eb94831 --- /dev/null +++ b/typedoc.config.cjs @@ -0,0 +1,49 @@ +// #awaiting https://github.com/TypeStrong/typedoc/pull/2268 +// import fs from "fs" +// import path from "path" +// +// import pkg from "./package.json" +const fs = require("fs") +const path = require("path") +const pkg = require("./package.json") + + +module.exports = { + githubPages: true, + navigationLinks: { + Github: pkg.repository, + Issues: `${pkg.repository}/issues`, + npm: `http://npmjs.com/${pkg.name}`, + }, + readme: "README.md", + logLevel: "Verbose", + entryPoints: ["src/index.ts", ...fs.readdirSync("src") + .filter(dir => fs.statSync(path.join("src", dir)).isDirectory()) + .map(dir => `src/${dir}/index.ts`)], + out: "docs", + excludePrivate: true, + excludeExternals: true, + // // temporarily turn off plugins (just setting plugin: [] will not work) + // plugin: "none", + validation: { + invalidLink: true, + }, + pluginPages: { + source: "docs-src", + pages: [ + { + name: "Additional Docs", + children: [ + // { + // name: "Internal Docs", + // source: "internal_docs.md", + // }, + { + name: "Development", + source: "DEVELOPMENT.md", + }, + ], + }, + ], + }, +} diff --git a/typedoc.config.js b/typedoc.config.js deleted file mode 100644 index 1fff7ef..0000000 --- a/typedoc.config.js +++ /dev/null @@ -1,26 +0,0 @@ -// const pkg = require("./package.json") -// const fs = require("fs") -// const path = require("path") - - -module.exports = { - readme: "README.md", - logLevel: "Verbose", - entryPoints: [ - "src/index.ts", - // ...fs.readdirSync("src") - // .filter(dir => fs.statSync(path.join("src", dir)).isDirectory()) - // .map(dir => `src/${dir}/index.ts`), - ], - out: "docs", - excludePrivate: true, - excludeExternals: true, - externalPattern: "**/{ast/builders,grammar}/**.ts", - githubPages: true, - // prevents typedoc auto-detecting installed plugins - // // temporarily turn off plugins (just setting plugin: [] will not work) - // plugin: "none", - validation: { - invalidLink: true, - }, -} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..46520c6 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,70 @@ +import { run } from "@alanscodelog/utils/node" +import glob from "fast-glob" +import path from "path" +import type { PluginOption } from "vite" +import { externalizeDeps } from "vite-plugin-externalize-deps" +import tsconfigPaths from "vite-tsconfig-paths" +import { defineConfig } from "vitest/config" + + +const typesPlugin = (): PluginOption => ({ + name: "typesPlugin", + // eslint-disable-next-line no-console + writeBundle: async () => run(`npm run build:types`).promise.catch(e => { console.log(e.stdout); process.exit(1) }).then(() => undefined), +}) + +// https://vitejs.dev/config/ +export default async ({ mode }: { mode: string }) => defineConfig({ + plugins: [ + // it isn't enough to just pass the deps list to rollup.external since it will not exclude subpath exports + externalizeDeps(), + // even if we don't use aliases, this is needed to get imports based on baseUrl working + tsconfigPaths(), + // runs build:types script which takes care of generating types and fixing type aliases and baseUrl imports + typesPlugin(), + ], + build: { + outDir: "dist", + lib: { + entry: glob.sync(path.resolve(__dirname, "src/**/*.ts")), + formats: ["es"], + + }, + rollupOptions: { + output: { + preserveModulesRoot: "src", + preserveModules: true, + }, + }, + // if this is a library + minify: false, + ...(mode === "production" ? { + // if this is an app + // minify: true + } : { + minify: false, + sourcemap: "inline", + }), + }, + test: { + cache: process.env.CI ? false : undefined, + }, + resolve: { + alias: [ + // for tests only, absolute path needed because of https://github.com/vitest-dev/vitest/issues/2425 + { find: /^@\/(.*)/, replacement: `${path.resolve("src")}/$1/index.ts` }, + ], + }, + server: { + // for locally linked repos when using vite server (i.e. not needed for libraries) + fs: { + allow: [...(process.env.CODE_PROJECTS ?? [])!], + }, + watch: { + // for pnpm + followSymlinks: true, + // watch changes in linked repos + ignored: ["!**/node_modules/@alanscodelog/**"], + }, + }, +})