diff --git a/.editorconfig b/.editorconfig
index 9966bd6..3fefca2 100755
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,19 +1,19 @@
# http://editorconfig.org
-root = true
+root=true
[*]
-charset = utf-8
-end_of_line = lf
-indent_style = space
-indent_size = 4
-trim_trailing_whitespace = true
-insert_final_newline = true
+charset=utf-8
+end_of_line=lf
+indent_style=space
+indent_size=4
+trim_trailing_whitespace=true
+insert_final_newline=true
[*.md]
-trim_trailing_whitespace = false
+trim_trailing_whitespace=false
# Use 2 spaces since npm does not respect custom indentation settings
[package.json]
-indent_style = space
-indent_size = 2
+indent_style=space
+indent_size=2
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100755
index 170b4a9..0000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,308 +0,0 @@
-module.exports = {
- parser: '@typescript-eslint/parser',
- parserOptions: {
- ecmaVersion: 2018,
- sourceType: 'module',
- impliedStrict: true,
- warnOnUnsupportedTypeScriptVersion: false
- },
- env: {
- node: true
- },
- plugins: ['@typescript-eslint', 'import', 'no-null', 'prefer-arrow', 'prettier', 'import'],
- extends: [
- 'eslint:recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:@typescript-eslint/eslint-recommended',
- 'plugin:prettier/recommended',
- 'prettier/prettier',
- 'plugin:import/recommended',
- 'plugin:import/typescript'
- ],
- noInlineConfig: false,
- reportUnusedDisableDirectives: true,
- rules: {
- '@typescript-eslint/array-type': ['error'],
- '@typescript-eslint/ban-types': ['error'],
- '@typescript-eslint/consistent-type-definitions': ['error'],
- '@typescript-eslint/explicit-function-return-type': [
- 'error',
- {
- allowExpressions: true,
- allowTypedFunctionExpressions: true,
- allowHigherOrderFunctions: true
- }
- ],
- '@typescript-eslint/explicit-member-accessibility': [
- 'error',
- {
- accessibility: 'explicit'
- }
- ],
- '@typescript-eslint/member-ordering': [
- 'error',
- {
- default: {
- memberTypes: [
- // Static
- // ======
- // fields
- 'public-static-field',
- 'protected-static-field',
- 'private-static-field',
- '#private-static-field',
- 'static-field',
- // accessors
- 'public-static-accessor',
- 'protected-static-accessor',
- 'private-static-accessor',
- '#private-static-accessor',
- 'static-accessor',
- // initialization
- 'static-initialization',
- // Getter and setter
- ['public-static-get', 'public-static-set'],
- ['protected-static-get', 'protected-static-set'],
- ['private-static-get', 'private-static-set'],
- ['#private-static-get', '#private-static-set'],
- ['static-get', 'static-set'],
- // Methods
- 'public-static-method',
- 'protected-static-method',
- 'private-static-method',
- '#private-static-method',
- 'static-method',
-
- // Instance
- // ========
- // Index signature
- 'signature',
- 'call-signature',
-
- // Fields
- 'public-abstract-field',
- 'protected-abstract-field',
-
- 'public-decorated-field',
- 'protected-decorated-field',
- 'private-decorated-field',
-
- 'public-instance-field',
- 'protected-instance-field',
- 'private-instance-field',
- '#private-instance-field',
-
- 'public-field',
- 'protected-field',
- 'private-field',
- '#private-field',
-
- 'abstract-field',
- 'instance-field',
-
- 'decorated-field',
-
- 'field',
-
- // Constructors
- 'public-constructor',
- 'protected-constructor',
- 'private-constructor',
- 'constructor',
-
- // Accessors
- 'public-abstract-accessor',
- 'protected-abstract-accessor',
-
- 'public-decorated-accessor',
- 'protected-decorated-accessor',
- 'private-decorated-accessor',
-
- 'public-instance-accessor',
- 'protected-instance-accessor',
- 'private-instance-accessor',
- '#private-instance-accessor',
-
- 'public-accessor',
- 'protected-accessor',
- 'private-accessor',
- '#private-accessor',
-
- 'abstract-accessor',
- 'instance-accessor',
-
- 'decorated-accessor',
-
- 'accessor',
-
- // Getters and Setter
- ['public-abstract-get', 'public-abstract-set'],
- ['protected-abstract-get', 'protected-abstract-set'],
-
- ['public-decorated-get', 'public-decorated-set'],
- ['protected-decorated-get', 'protected-decorated-set'],
- ['private-decorated-get', 'private-decorated-set'],
-
- ['public-instance-get', 'public-instance-set'],
- ['protected-instance-get', 'protected-instance-set'],
- ['private-instance-get', 'private-instance-set'],
- ['#private-instance-get', '#private-instance-set'],
-
- ['public-get', 'public-set'],
- ['protected-get', 'protected-set'],
- ['private-get', 'private-set'],
- ['#private-get', '#private-set'],
-
- ['abstract-get', 'abstract-set'],
- ['decorated-get', 'decorated-set'],
- ['instance-get', 'instance-set'],
-
- ['get', 'set'],
-
- // Methods
- 'public-abstract-method',
- 'protected-abstract-method',
-
- 'public-decorated-method',
- 'protected-decorated-method',
- 'private-decorated-method',
-
- 'public-instance-method',
- 'protected-instance-method',
- 'private-instance-method',
- '#private-instance-method',
-
- 'public-method',
- 'protected-method',
- 'private-method',
- '#private-method',
-
- 'abstract-method',
- 'instance-method',
-
- 'decorated-method',
-
- 'method'
- ]
- }
- }
- ],
- '@typescript-eslint/no-empty-function': ['error'],
- '@typescript-eslint/no-explicit-any': ['off'],
- '@typescript-eslint/no-inferrable-types': ['off'],
- '@typescript-eslint/no-namespace': ['off'],
- '@typescript-eslint/no-parameter-properties': ['off'],
- '@typescript-eslint/no-shadow': [
- 'error',
- {
- hoist: 'all'
- }
- ],
- '@typescript-eslint/no-unused-vars': [
- 'error',
- {
- vars: 'all',
- args: 'none',
- ignoreRestSiblings: false
- }
- ],
- '@typescript-eslint/prefer-for-of': ['error'],
- '@typescript-eslint/prefer-function-type': ['error'],
- '@typescript-eslint/prefer-namespace-keyword': ['error'],
- '@typescript-eslint/triple-slash-reference': ['error'],
- '@typescript-eslint/unified-signatures': ['error'],
-
- 'no-null/no-null': ['error'],
-
- 'prettier/prettier': ['error'],
-
- 'prefer-arrow/prefer-arrow-functions': [
- 'error',
- {
- disallowPrototype: true,
- singleReturnOnly: true,
- classPropertiesAllowed: false
- }
- ],
-
- 'import/no-unresolved': ['error', { ignore: ['^@?[\\w\\d-_]+/?[\\w\\d-_]+/[\\w\\d-_]+$'] }],
- 'import/order': [
- 'error',
- {
- groups: ['builtin', 'external', 'internal', 'sibling', 'parent', 'index', 'unknown'],
- 'newlines-between': 'always',
- alphabetize: {
- /* sort in ascending order. Options: ["ignore", "asc", "desc"] */
- order: 'asc',
- /* ignore case. Options: [true, false] */
- caseInsensitive: true
- }
- }
- ],
-
- 'arrow-body-style': ['error'],
- camelcase: ['error'],
- 'capitalized-comments': ['off'],
- 'comma-dangle': [
- 'error',
- {
- objects: 'never',
- arrays: 'never',
- functions: 'never'
- }
- ],
- complexity: ['off'],
- 'default-case': ['error'],
- 'dot-location': ['error', 'property'],
- eqeqeq: ['error', 'smart'],
- 'max-len': [
- 'error',
- {
- code: 120,
- ignoreUrls: true
- }
- ],
- 'no-alert': ['error'],
- 'no-bitwise': ['error'],
- 'no-caller': ['error'],
- 'no-console': ['error'],
- 'no-constructor-return': ['error'],
- 'no-div-regex': ['error'],
- 'no-empty': ['error'],
- 'no-empty-function': [
- 'error',
- {
- allow: ['constructors']
- }
- ],
- 'no-eval': ['error'],
- 'no-extra-bind': ['error'],
- 'no-import-assign': ['error'],
- 'no-invalid-this': ['error'],
- 'no-labels': ['error'],
- 'no-multiple-empty-lines': ['error'],
- 'no-new-wrappers': ['error'],
- 'no-regex-spaces': ['error'],
- 'no-return-assign': ['error'],
- 'no-return-await': ['error'],
- 'no-self-compare': ['error'],
- 'no-shadow': ['off'],
- 'no-throw-literal': ['error'],
- 'no-undef-init': ['error'],
- 'no-underscore-dangle': ['off'],
- 'no-unused-expressions': ['error'],
- 'no-useless-call': ['error'],
- 'no-useless-concat': ['error'],
- 'no-var': ['error'],
- 'object-shorthand': ['error'],
- 'one-var': ['error', 'never'],
- 'prefer-const': ['error'],
- 'prefer-regex-literals': ['error'],
- radix: ['error'],
- 'require-await': ['error'],
- 'spaced-comment': ['error'],
- 'use-isnan': ['error'],
- 'valid-typeof': ['error'],
- yoda: ['error']
- }
-};
diff --git a/.gitignore b/.gitignore
index 6a98bde..114ef15 100755
--- a/.gitignore
+++ b/.gitignore
@@ -28,4 +28,3 @@ dist/
# Docs generated folder
docs/
-
diff --git a/.husky/commit-msg b/.husky/commit-msg
index 2f1a4f5..a7dcb45 100755
--- a/.husky/commit-msg
+++ b/.husky/commit-msg
@@ -1,13 +1,8 @@
-#!/usr/bin/env sh
-
-# Load husky
-. "$(dirname -- "$0")/_/husky.sh";
-
# Read parameters
-COMMIT_MSG_FILE=$1;
+COMMIT_MSG_FILE=$1
# Set failing on command fail, and undefined variable use
-set -eu;
+set -eu
# This hook is invoked by git-commit and git-merge, and can be
# bypassed with the --no-verify option. It takes a single
@@ -28,10 +23,10 @@ set -eu;
# message sent has the correct format for the project, aborting otherwise.
# Show welcome message
-echo "**************************";
-echo "Linting the commit message";
-echo "**************************";
-echo "";
+echo "**************************"
+echo "Linting the commit message"
+echo "**************************"
+echo ""
# Run commitlint
-npx --no -- commitlint --edit ${1};
+npx --no -- commitlint --edit ${1}
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 0cfbe23..70e0926 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,13 +1,8 @@
-#!/usr/bin/env sh
-
-# Load husky
-. "$(dirname -- "$0")/_/husky.sh";
-
# Read parameters
# NOTHING TO READ HERE
# Set failing on command fail, and undefined variable use
-set -eu;
+set -eu
# This hook is invoked by git-commit, and can be bypassed with the
# --no-verify option. It takes no parameters, and is invoked before
@@ -31,26 +26,29 @@ set -eu;
# Generated files are added to the commit.
# Show welcome message
-echo "**************************";
-echo "Running pre commit hooks";
-echo "**************************";
-echo "";
+echo "**************************"
+echo "Running pre commit hooks"
+echo "**************************"
+echo ""
# Run license
-echo "\nAdd license text to code files\n";
-npx --no -- gobstones-scripts run license --silent ;
-
-# Run prettify
-echo "Run prettify\n";
-npx --no -- gobstones-scripts run prettify --silent ;
+echo "\nAdd license text to code files\n"
+npx --no -- gobstones-scripts run license --silent
# Run changelog
-echo "\nRun changelog\n";
-npx --no -- gobstones-scripts run changelog --silent ;
+echo "\nRun changelog\n"
+# Only run if not first commit
+if git-log &> /dev/null; then
+ npx --no -- gobstones-scripts run changelog --silent
+fi
+
+# Run prettify
+echo "Run prettify\n"
+npx --no -- gobstones-scripts run prettify --silent
# Add all generated files
-echo "\nAdd generated files to commit\n";
-git add --all;
+echo "\nAdd generated files to commit\n"
+git add --all
# Exit
-exit 0;
+exit 0
diff --git a/.husky/pre-push b/.husky/pre-push
index 6d1acf0..305a10c 100755
--- a/.husky/pre-push
+++ b/.husky/pre-push
@@ -1,24 +1,23 @@
-#!/usr/bin/env sh
-
-# Load husky
-. "$(dirname -- "$0")/_/husky.sh"
-
# Read parameters
-REMOTE_NAME=$1;
-REMOTE_URL=$2;
+REMOTE_NAME=$1
+REMOTE_URL=$2
# Read the input and split it approprietly
-INPUT=$(cat);
-COUNTER=0;
+INPUT=$(cat)
+COUNTER=0
for WORD in $INPUT; do
case $COUNTER in
0)
- LOCAL_REF=$WORD;;
+ LOCAL_REF=$WORD
+ ;;
1)
- LOCAL_OBJ_NAME=$WORD;;
+ LOCAL_OBJ_NAME=$WORD
+ ;;
2)
- REMOTE_REF=$WORD;;
+ REMOTE_REF=$WORD
+ ;;
3)
- REMOTE_OBJ_NAME=$WORD;;
+ REMOTE_OBJ_NAME=$WORD
+ ;;
esac
COUNTER=$((COUNTER + 1))
done
@@ -26,14 +25,16 @@ done
case "$LOCAL_REF" in
refs\/tags*)
# Apply specific code when publishing tags
- IS_TAG=1;;
+ IS_TAG=1
+ ;;
*)
# Apply specific code when publishing any branch
- IS_TAG=0;;
+ IS_TAG=0
+ ;;
esac
# Set failing on command fail, and undefined variable use
-set -eu;
+set -eu
# This hook is called by git-push and can be used to prevent a
# push from taking place. The hook is called with two parameters
@@ -70,13 +71,13 @@ set -eu;
# to match that of the tag.
# Show welcome message
-echo "**************************";
-echo "Running pre push hooks";
-echo "**************************";
-echo "";
+echo "**************************"
+echo "Running pre push hooks"
+echo "**************************"
+echo ""
# Run all the tests
-echo "Running tests";
-npx --no -- gobstones-scripts run test --silent;
+echo "Running tests"
+npx --no -- gobstones-scripts run test --silent
-exit 0;
+exit 0
diff --git a/.husky/prepare-commit-msg b/.husky/prepare-commit-msg
index d69cd7d..f68c5d7 100755
--- a/.husky/prepare-commit-msg
+++ b/.husky/prepare-commit-msg
@@ -1,15 +1,10 @@
-#!/usr/bin/env sh
-
-# Load husky
-. "$(dirname -- "$0")/_/husky.sh";
-
# Read parameters
-COMMIT_MSG_FILE=$1;
-COMMIT_SOURCE=$2;
-SHA1=$3;
+COMMIT_MSG_FILE=$1
+COMMIT_SOURCE=$2
+SHA1=$3
# Set failing on command fail, and undefined variable use
-set -eu;
+set -eu
# This hook is invoked by git-commit right after preparing
# the default log message, and before the editor is started.
@@ -39,44 +34,44 @@ set -eu;
# semantic commit message through a prompt.
# Show welcome message
-echo "**************************";
-echo "Generate commit message";
-echo "**************************";
-echo "";
+echo "**************************"
+echo "Generate commit message"
+echo "**************************"
+echo ""
# Check if we are doing an amend
if [ "$COMMIT_SOURCE" = 'commit' ] && [ -n $SHA1 ]; then
# Amends do not call the "cz" command.
- exit 0;
+ exit 0
fi
# Check if we are doing an squash
if [ "$COMMIT_SOURCE" = 'squash' ]; then
# Squashes should not trigger the cz command.
- exit 0;
+ exit 0
fi
# Check if we are doing an merge
if [ "$COMMIT_SOURCE" = 'merge' ]; then
# Merging should not trigger the cz command.
- exit 0;
+ exit 0
fi
# Check if we are using a template
if [ "$COMMIT_SOURCE" = 'template' ]; then
# Cannot use templates, warn the user and fail.
- echo "Setting a template through -t or commit.template in this project ";
- echo "has been disabled. Please run a simple commit.\n";
- exit 1;
+ echo "Setting a template through -t or commit.template in this project "
+ echo "has been disabled. Please run a simple commit.\n"
+ exit 1
fi
# Check if a message was given
if [ "$COMMIT_SOURCE" = 'message' ]; then
# Cannot use message, warn the user and fail.
- echo "Setting a message through -m or -F option in this project ";
- echo "has been disabled. Please run a simple commit.\n";
- exit 1;
+ echo "Setting a message through -m or -F option in this project "
+ echo "has been disabled. Please run a simple commit.\n"
+ exit 1
fi
# Regular commit has been performed, run the command.
-exec < /dev/tty && npx cz --hook || true;
+exec < /dev/tty && npx cz --hook || true
diff --git a/.prettierrc b/.prettierrc
index d58a139..6e9466b 100755
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,67 +1,73 @@
{
- "printWidth": 120,
- "tabWidth": 4,
- "useTabs": false,
- "semi": true,
- "singleQuote": true,
- "endOfLine": "lf",
- "trailingComma": "none",
- "overrides": [
- {
- "files": ["*.js", "**/*.js", "*.jsx", "**/*.jsx"],
- "options": {
- "parser": "babel"
- }
- },
- {
- "files": ["*.ts", "**/*.ts", "*.tsx", "**/*.tsx"],
- "options": {
- "parser": "typescript"
- }
- },
- {
- "files": ["*.yml", "**/*.yml", "*.yaml", "**/*.yaml"],
- "options": {
- "parser": "yaml"
- }
- },
- {
- "files": ["*.json", "**/*.json"],
- "options": {
- "parser": "json"
- }
- },
- {
- "files": ["*.md", "**/*.md"],
- "options": {
- "parser": "markdown"
- }
- },
- {
- "files": ["*.css", "**/*.css", "*.scss", "**/*.scss", "*.less", "**/*.less"],
- "options": {
- "parser": "css"
- }
- },
- {
- "files": ["*.html", "**/*.html"],
- "options": {
- "parser": "html"
- }
- },
- {
- "files": ["package.json"],
- "options": {
- "tabWidth": 2,
- "parser": "json"
- }
- },
- {
- "files": [".prettierrc"],
- "options": {
- "tabWidth": 2,
- "parser": "json"
- }
- }
- ]
+ "plugins": ["prettier-plugin-ini", "prettier-plugin-sh"],
+ "printWidth": 120,
+ "tabWidth": 4,
+ "useTabs": false,
+ "semi": true,
+ "singleQuote": true,
+ "endOfLine": "lf",
+ "trailingComma": "none",
+ "overrides": [
+ {
+ "files": ["*.js", "**/*.js", "*.jsx", "**/*.jsx"],
+ "options": {
+ "parser": "babel"
+ }
+ },
+ {
+ "files": ["*.ts", "**/*.ts", "*.tsx", "**/*.tsx"],
+ "options": {
+ "parser": "typescript"
+ }
+ },
+ {
+ "files": ["*.yml", "**/*.yml", "*.yaml", "**/*.yaml"],
+ "options": {
+ "parser": "yaml"
+ }
+ },
+ {
+ "files": ["*.json", "**/*.json", ".czrc", "**/.czrc"],
+ "options": {
+ "parser": "json"
+ }
+ },
+ {
+ "files": ["package.json"],
+ "options": {
+ "tabWidth": 2,
+ "parser": "json"
+ }
+ },
+ {
+ "files": ["*.md", "**/*.md"],
+ "options": {
+ "parser": "markdown"
+ }
+ },
+ {
+ "files": ["*.css", "**/*.css", "*.scss", "**/*.scss", "*.less", "**/*.less"],
+ "options": {
+ "parser": "css"
+ }
+ },
+ {
+ "files": ["*.html", "**/*.html"],
+ "options": {
+ "parser": "html"
+ }
+ },
+ {
+ "files": ["**/*.ini", ".editorconfig", ".npmrc"],
+ "options": {
+ "parser": "ini"
+ }
+ },
+ {
+ "files": [".gitignore", ".npmignore", ".husky/*"],
+ "options": {
+ "parser": "sh"
+ }
+ }
+ ]
}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index dfb1c04..5d1da3c 100755
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -3,8 +3,10 @@
"streetsidesoftware.code-spell-checker",
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
- "orta.vscode-jest",
"christian-kohler.path-intellisense",
- "SantaCodes.santacodes-region-viewer"
+ "SantaCodes.santacodes-region-viewer",
+ "foxundermoon.shell-format",
+ "github.vscode-github-actions",
+ "redhat.vscode-yaml"
]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index e09e0ac..f1e8015 100755
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,18 +1,16 @@
{
+ // CSpell
+ "cSpell.words": [],
// Node and npm configuration
"npm.autoDetect": "on",
- "debug.node.autoAttach": "smart",
+ "debug.node.autoAttach": "never",
"files.exclude": {
"tsconfig.build.json": true
},
// Code style, regular and ESLint related
"files.trimTrailingWhitespace": true,
- "editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.validate": ["typescript"],
"editor.codeActionsOnSave": {
- "source.fixAll": true
- },
- "editor.formatOnSave": false,
- // CSpell
- "cSpell.words": []
+ "source.fixAll.eslint": "always"
+ }
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4938ebc..f457923 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,10 @@
-## 0.5.3 (2024-05-05)
+## 0.5.5 (2024-09-05)
+- build: bump gobstones-scripts version to 0.9.3 ([f9e850a](https://github.com/gobstones/gobstones-core/commit/f9e850a))
+## 0.5.5 (2024-09-05)
+## 0.5.3 (2024-05-05)
## 0.5.2 (2024-05-05)
diff --git a/commitlint.config.js b/commitlint.config.mjs
similarity index 73%
rename from commitlint.config.js
rename to commitlint.config.mjs
index a989bfc..115abd6 100644
--- a/commitlint.config.js
+++ b/commitlint.config.mjs
@@ -1,3 +1,3 @@
-module.exports = {
+export default {
extends: ['@commitlint/config-conventional']
};
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..ace463d
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,251 @@
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+import { includeIgnoreFile } from '@eslint/compat';
+import { FlatCompat } from '@eslint/eslintrc';
+import eslintJs from '@eslint/js';
+import eslintPluginNoNull from 'eslint-plugin-no-null';
+import eslintPluginPreferArrow from 'eslint-plugin-prefer-arrow';
+import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
+import globals from 'globals';
+import eslintTs from 'typescript-eslint';
+
+const baseUrl = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
+
+const tsConfigPath = path.join(baseUrl, 'tsconfig.json');
+const gitignorePath = path.join(baseUrl, '.gitignore');
+
+const compat = new FlatCompat({
+ baseDirectory: baseUrl,
+ recommendedConfig: eslintJs.configs.recommended
+});
+
+const withFilesOnly = (config, files) =>
+ config.map((e) => {
+ e.files = files;
+ return e;
+ });
+const _jsFiles = ['src/**/*.js', 'src/**/*.jsx', 'src/**/*.mjs', 'src/**/*.cjs'];
+const _tsFiles = ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.mts', 'src/**/*.cts'];
+const _codeFiles = [..._jsFiles, ..._tsFiles];
+
+const config = eslintTs.config(
+ // Add all .gitignore files to the ignore path
+ includeIgnoreFile(gitignorePath),
+ // Asure oackage-scripts as CJS, to avoid no-undef issues
+ { files: ['**/package-scripts.js'], languageOptions: { globals: globals.node } },
+ // Recommended settings from ESLint for JS
+ eslintJs.configs.recommended,
+ // Prettier plugin usage
+ eslintPluginPrettierRecommended,
+ // Import default settings. Import is not yet ESLint 9 compatible
+ ...withFilesOnly(
+ compat.extends(
+ 'plugin:import/recommended',
+ 'plugin:import/errors',
+ 'plugin:import/warnings',
+ 'plugin:import/typescript'
+ ),
+ _codeFiles
+ ),
+ // Custom settings and rules for all JS and TS files
+ {
+ files: _codeFiles,
+ linterOptions: {
+ reportUnusedDisableDirectives: true
+ },
+ languageOptions: {
+ parser: eslintJs.parser,
+ parserOptions: eslintJs.parserOptions,
+ globals: {
+ ...globals.node
+ },
+ ecmaVersion: 2022,
+ sourceType: 'module'
+ },
+ plugins: {
+ 'no-null': eslintPluginNoNull,
+ 'prefer-arrow': eslintPluginPreferArrow
+ // import: legacyPlugin('eslint-plugin-import', 'import')
+ },
+ settings: {
+ // 'import/ignore': ['i18next', 'fs', 'path']
+ },
+ rules: {
+ // Non plugin rules
+ 'no-console': ['error'],
+ 'arrow-body-style': ['error'],
+ 'no-shadow': ['off'],
+ camelcase: ['error'],
+ 'capitalized-comments': ['off'],
+ 'default-case': ['error'],
+ 'dot-location': ['error', 'property'],
+ eqeqeq: ['error', 'smart'],
+ 'no-alert': ['error'],
+ 'no-bitwise': ['error'],
+ 'no-caller': ['error'],
+ 'no-constructor-return': ['error'],
+ 'no-div-regex': ['error'],
+ 'no-empty': ['error'],
+
+ 'no-empty-function': [
+ 'error',
+ {
+ allow: ['constructors']
+ }
+ ],
+
+ 'no-eval': ['error'],
+ 'no-extra-bind': ['error'],
+ 'no-import-assign': ['error'],
+ 'no-invalid-this': ['error'],
+ 'no-labels': ['error'],
+ 'no-multiple-empty-lines': ['error'],
+ 'no-new-wrappers': ['error'],
+ 'no-regex-spaces': ['error'],
+ 'no-return-assign': ['error'],
+ 'no-return-await': ['error'],
+ 'no-self-compare': ['error'],
+ 'no-throw-literal': ['error'],
+ 'no-undef-init': ['error'],
+ 'no-underscore-dangle': ['off'],
+ 'no-unused-expressions': ['error'],
+ 'no-useless-call': ['error'],
+ 'no-useless-concat': ['error'],
+ 'no-var': ['error'],
+ 'object-shorthand': ['error'],
+ 'one-var': ['error', 'never'],
+ 'prefer-const': ['error'],
+ 'prefer-regex-literals': ['error'],
+ radix: ['error'],
+ 'require-await': ['error'],
+
+ 'sort-imports': [
+ 'error',
+ {
+ ignoreCase: false,
+ ignoreDeclarationSort: true,
+ ignoreMemberSort: false,
+ memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
+ allowSeparatedGroups: true
+ }
+ ],
+
+ 'spaced-comment': ['error'],
+ 'use-isnan': ['error'],
+ 'valid-typeof': ['error'],
+ yoda: ['error'],
+
+ // No Null plugin
+ 'no-null/no-null': ['error'],
+
+ // Prefer arrow Plugin
+ 'prefer-arrow/prefer-arrow-functions': [
+ 'error',
+ {
+ disallowPrototype: true,
+ singleReturnOnly: false,
+ classPropertiesAllowed: false
+ }
+ ],
+
+ // Import is still not v9 compatible, some some rules fail.
+ // Instead of using the default provided configurations,
+ // we manually configure the rules, to avoid rules that have problems.
+
+ // Helpful warnings
+ 'import/no-empty-named-blocks': ['error'],
+ 'import/no-extraneous-dependencies': ['error'],
+ 'import/no-mutable-exports': ['off'],
+ 'import/no-named-as-default': ['off'],
+ 'import/no-named-as-default-member': ['off'],
+ // Module systems
+ 'import/no-import-module-exports': ['error'],
+ // Static Analysis
+ 'import/default': ['off'],
+ 'import/namespace': ['off'],
+ 'import/no-absolute-path': ['error'],
+ 'import/no-dynamic-require': ['error'],
+ 'import/no-self-import': ['error'],
+ 'import/no-unresolved': ['off'],
+ 'import/no-useless-path-segments': ['error'],
+ 'import/no-webpack-loader-syntax': ['error'],
+ // Style guide
+ 'import/no-duplicates': ['error'],
+ 'import/order': [
+ 'error',
+ {
+ groups: ['builtin', 'external', 'internal', 'sibling', 'parent', 'index', 'unknown'],
+ 'newlines-between': 'always',
+
+ alphabetize: {
+ order: 'asc',
+ caseInsensitive: true
+ }
+ }
+ ]
+ }
+ },
+ // This rules applies only for TS files, recommended typescript-eslint settings.
+ ...withFilesOnly(eslintTs.configs.strict, _tsFiles),
+ ...withFilesOnly(eslintTs.configs.stylistic, _tsFiles),
+ ...withFilesOnly(eslintTs.configs.strictTypeChecked, _tsFiles),
+ ...withFilesOnly(eslintTs.configs.stylisticTypeChecked, _tsFiles),
+ // Custom typescript-eslint configuration
+ {
+ files: _tsFiles,
+ languageOptions: {
+ parser: eslintTs.parser,
+ parserOptions: {
+ project: [tsConfigPath],
+ impliedStrict: true,
+ warnOnUnsupportedTypeScriptVersion: false
+ }
+ },
+ rules: {
+ '@typescript-eslint/prefer-nullish-coalescing': ['off'],
+ '@typescript-eslint/no-unnecessary-type-parameters': ['off'],
+ '@typescript-eslint/no-unnecessary-condition': ['off'],
+ '@typescript-eslint/no-inferrable-types': ['off'],
+ '@typescript-eslint/no-namespace': ['off'],
+ '@typescript-eslint/prefer-regexp-exec': ['off'],
+ '@typescript-eslint/no-shadow': ['error'],
+ '@typescript-eslint/restrict-template-expressions': [
+ 'error',
+ {
+ allowNumber: true
+ }
+ ],
+ '@typescript-eslint/explicit-member-accessibility': [
+ 'error',
+ {
+ accessibility: 'explicit'
+ }
+ ],
+ '@typescript-eslint/member-ordering': [
+ 'error',
+ {
+ default: ['signature', 'field', 'constructor', ['get', 'set'], 'method']
+ }
+ ],
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {
+ argsIgnorePattern: '^_',
+ caughtErrorsIgnorePattern: '^_',
+ destructuredArrayIgnorePattern: '^_'
+ }
+ ],
+ '@typescript-eslint/explicit-function-return-type': [
+ 'error',
+ {
+ allowExpressions: true,
+ allowTypedFunctionExpressions: true,
+ allowHigherOrderFunctions: true
+ }
+ ]
+ }
+ }
+);
+
+export default config;
diff --git a/package.json b/package.json
index df4eb60..3fba094 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@gobstones/gobstones-core",
- "version": "0.5.4",
+ "version": "0.5.5",
"description": "A set of utility types, interfaces and classes that are used through all the Gobstones Platform repositories.",
"repository": "https://github.com/gobstones/gobstones-core",
"homepage": "https://gobstones.github.io/gobstones-core",
@@ -38,9 +38,9 @@
".": ["./dist/esm/typings/index.d.ts"]
}
},
- "packageManager": "npm@9.2.0",
+ "packageManager": "npm@10.8.2",
"scripts": {
- "prepare": "is-ci || husky install",
+ "prepare": "is-ci || husky",
"prepack": "npm start build",
"start": "gobstones-scripts run",
"gbs": "gobstones-scripts"
@@ -52,10 +52,10 @@
}
},
"dependencies": {
- "commander": "^11.1.0"
+ "commander": "^12.1.0"
},
"devDependencies": {
- "@gobstones/gobstones-scripts": "^0.8.7",
- "husky": "^9.0.11"
+ "@gobstones/gobstones-scripts": "^0.9.3",
+ "husky": "^9.1.4"
}
}
diff --git a/rollup.config.js b/rollup.config.mjs
similarity index 77%
rename from rollup.config.js
rename to rollup.config.mjs
index e9c2685..cfcfd83 100644
--- a/rollup.config.js
+++ b/rollup.config.mjs
@@ -1,17 +1,16 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-const fs = require('fs');
+import { readFileSync } from 'fs';
-const { config } = require('@gobstones/gobstones-scripts');
-const commonjs = require('@rollup/plugin-commonjs');
-const nodeResolve = require('@rollup/plugin-node-resolve');
-const typescript = require('@rollup/plugin-typescript');
+import { config } from '@gobstones/gobstones-scripts';
+import commonjs from '@rollup/plugin-commonjs';
+import nodeResolve from '@rollup/plugin-node-resolve';
+import typescript from '@rollup/plugin-typescript';
-const packageJson = JSON.parse(fs.readFileSync('./package.json').toString());
+const packageJson = JSON.parse(readFileSync('./package.json').toString());
config.init();
const tsConfigPath = config.projectType.tsConfigJSON.toolingFile;
-module.exports = [
+export default [
{
input: 'src/index.ts',
output: [
diff --git a/src/Events/EventEmitter.ts b/src/Events/EventEmitter.ts
index 4725464..131428f 100644
--- a/src/Events/EventEmitter.ts
+++ b/src/Events/EventEmitter.ts
@@ -10,21 +10,22 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Events
+ * @module Events
* @author Alan Rodas Bonjour
*/
-/* eslint-disable @typescript-eslint/consistent-type-definitions */
+
+import { asDefined } from '../Functions';
/**
* This type describes the basic mapping of available events to the
* corresponding subscriber functions that may subscribe to such event.
* Multiple events could be added, with different signatures for each
* subscriber.
- *
- * @group Internal: Types
*/
export type EventSignature = {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
[E in keyof L]: (...args: any[]) => any;
};
@@ -33,12 +34,9 @@ export type EventSignature = {
* event is key is a string (the most common case), and the subscriber
* functions are any function. This is the default behavior of most
* JavaScript event emitter, and the DOM event's signature.
- *
- * @group Internal: Types
*/
-export type DefaultEventSignature = {
- [k: string]: (...args: any[]) => any;
-};
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type DefaultEventSignature = Record any>;
/**
* The EventEmitter class is a minimal observer pattern class definition.
@@ -49,15 +47,13 @@ export type DefaultEventSignature = {
* The EventEmitter accepts as a type as a {@link EventSignature}, that is,
* a set of event names together with the expected parameters that the observer
* will be called with when the event occurs.
- *
- * @group API: Main
*/
export class EventEmitter = DefaultEventSignature> {
/** A map of event to observers for the full time observers. */
- private eventObservers: Map> = new Map();
+ private eventObservers = new Map>();
/** A map of event to observers for the one time observers. */
- private eventOnceObservers: Map> = new Map();
+ private eventOnceObservers = new Map>();
/**
* Register a observer to a particular event of this event emitter, as a
@@ -68,8 +64,8 @@ export class EventEmitter = DefaultEventSignature> {
* as a one time observer. If it's a full time observer, it will be transformed
* to a one time observer.
*
- * @param event The event that the observer will be registered to.
- * @param observer The observer that will be called when the event occurs.
+ * @param event - The event that the observer will be registered to.
+ * @param observer - The observer that will be called when the event occurs.
*
* @returns The event emitter.
*/
@@ -88,8 +84,8 @@ export class EventEmitter = DefaultEventSignature> {
* as a full time observer. If it's a one time observer, it will be transformed
* to a full time observer.
*
- * @param event The event that the observer will be registered to.
- * @param observer The observer that will be called when the event occurs.
+ * @param event - The event that the observer will be registered to.
+ * @param observer - The observer that will be called when the event occurs.
*
* @returns The event emitter.
*/
@@ -109,8 +105,8 @@ export class EventEmitter = DefaultEventSignature> {
* Note that the observer is removed only to the specified event, and such
* it may still be registered for other events.
*
- * @param event The event that the observer will be removed from.
- * @param observer The observer that will be removed when the event occurs.
+ * @param event - The event that the observer will be removed from.
+ * @param observer - The observer that will be removed when the event occurs.
*
* @returns The event emitter.
*/
@@ -128,7 +124,7 @@ export class EventEmitter = DefaultEventSignature> {
* Event if all observers are removed, an observer may subscribe again to
* the event afterwards.
*
- * @param event The event that the observers will be removed from.
+ * @param event - The event that the observers will be removed from.
*
* @returns The event emitter.
*/
@@ -146,7 +142,7 @@ export class EventEmitter = DefaultEventSignature> {
* After the emission, one time subscribers are removed as subscribers to the
* event, as they should not be called again.
*
- * @param event The event to emit.
+ * @param event - The event to emit.
*/
public emit(event: U, ...args: Parameters): void {
for (const observer of this.getSetOrEmpty(event, this.eventObservers)) {
@@ -164,13 +160,13 @@ export class EventEmitter = DefaultEventSignature> {
* only the new observer. If the observer is already present for that
* event in the given map, do nothing.
*
- * @param event The event to add the observer to.
- * @param observer The observer to add.
- * @param map The map to register the event and observer.
+ * @param event - The event to add the observer to.
+ * @param observer - The observer to add.
+ * @param map - The map to register the event and observer.
*/
private appendToMap(event: U, observer: L[U], map: Map>): void {
if (map.has(event)) {
- const set = map.get(event) as Set;
+ const set = asDefined(map.get(event));
set.add(observer);
} else {
const set = new Set();
@@ -184,9 +180,9 @@ export class EventEmitter = DefaultEventSignature> {
* If the observer does not exists in the event for the map, or the event
* is not present in the map, do nothing.
*
- * @param event The event to remove the observer from.
- * @param observer The observer to be removed.
- * @param map The map to unregister the event and observer.
+ * @param event - The event to remove the observer from.
+ * @param observer - The observer to be removed.
+ * @param map - The map to unregister the event and observer.
*/
private removeOfMap(event: U, observer: L[U], map: Map>): void {
const set = this.getSetOrEmpty(event, map);
@@ -197,8 +193,8 @@ export class EventEmitter = DefaultEventSignature> {
* Remove all entries for an event in the given map. That is, remove the event
* itself.
*
- * @param event The event to remove.
- * @param map The map to remove the event from.
+ * @param event - The event to remove.
+ * @param map - The map to remove the event from.
*/
private deleteEntriesInMap(event: U, map: Map>): void {
if (map.has(event)) {
@@ -210,14 +206,14 @@ export class EventEmitter = DefaultEventSignature> {
* Return a set for the given event. If the event exists in the given map,
* return the set of that event. If not, return a new set.
*
- * @param event The event to obtain the set for.
- * @param map The map from where to grab the set from.
+ * @param event - The event to obtain the set for.
+ * @param map - The map from where to grab the set from.
*
* @returns A set for the given event, a present one, or a new one.
*/
private getSetOrEmpty(event: U, map: Map>): Set {
if (map.has(event)) {
- return map.get(event) as Set;
+ return asDefined(map.get(event));
}
return new Set();
}
diff --git a/src/Events/index.ts b/src/Events/index.ts
index fc95ab4..9758947 100644
--- a/src/Events/index.ts
+++ b/src/Events/index.ts
@@ -66,7 +66,8 @@ export function subscribeToEvent(): void {
emitter.on('onStringChanged', subscriberToStringChanged);
}
* ```
- * @module API.Events
+
+ * @module Events
* @author Alan Rodas Bonjour
*/
export * from './EventEmitter';
diff --git a/src/Expectations/Classes/AbstractFinishedExpectation.ts b/src/Expectations/Implementation/AbstractFinishedExpectation.ts
similarity index 86%
rename from src/Expectations/Classes/AbstractFinishedExpectation.ts
rename to src/Expectations/Implementation/AbstractFinishedExpectation.ts
index a04cb8d..86379a5 100644
--- a/src/Expectations/Classes/AbstractFinishedExpectation.ts
+++ b/src/Expectations/Implementation/AbstractFinishedExpectation.ts
@@ -10,10 +10,13 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Implementation
* @author Alan Rodas Bonjour
*/
+
+import { noop } from '../../Functions';
import { FinishedExpectation } from '../Interfaces';
/**
@@ -50,13 +53,11 @@ export abstract class AbstractFinishedExpectation implements FinishedExpectation
/** @inheritDoc {@link FinishedExpectation.andDo} */
public andDo(action: () => void): void {
- // eslint-disable-next-line @typescript-eslint/no-empty-function, no-empty-function
- this.andDoOr(action, () => {});
+ this.andDoOr(action, noop);
}
/** @inheritDoc {@link FinishedExpectation.orDo} */
public orDo(action: () => void): void {
- // eslint-disable-next-line @typescript-eslint/no-empty-function, no-empty-function
- this.andDoOr(() => {}, action);
+ this.andDoOr(noop, action);
}
}
diff --git a/src/Expectations/Classes/FullExpectation.ts b/src/Expectations/Implementation/FullExpectation.ts
similarity index 90%
rename from src/Expectations/Classes/FullExpectation.ts
rename to src/Expectations/Implementation/FullExpectation.ts
index 344bc35..69fe6b2 100644
--- a/src/Expectations/Classes/FullExpectation.ts
+++ b/src/Expectations/Implementation/FullExpectation.ts
@@ -10,22 +10,24 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Implementation
* @author Alan Rodas Bonjour
*/
+
import { AbstractFinishedExpectation } from './AbstractFinishedExpectation';
import {
ArrayExpectation,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ Expectation,
FinishedExpectation,
NumberExpectation,
ObjectExpectation,
- StringExpectation,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- Expectation
+ StringExpectation
} from '../Interfaces';
-import { MatcherCall, Matchers } from '../Matchers';
+import * as Matchers from '../Matchers';
/**
* The expectation class is the class that is actually instantiated for
@@ -34,14 +36,14 @@ import { MatcherCall, Matchers } from '../Matchers';
*
* @group Internal: Types
*/
-export class FullExpectation extends AbstractFinishedExpectation {
+export class FullExpectation extends AbstractFinishedExpectation {
// -----------------------------------------------
// #region Internal: Properties
// -----------------------------------------------
/**
* The querying element of this expectation.
*/
- protected element: any;
+ protected element: unknown;
/**
* The current result of this expectation. Undefined until
* the first matcher is run.
@@ -55,7 +57,7 @@ export class FullExpectation extends AbstractFinishedExpectation {
/**
* An array of the matchers run in this expectation.
*/
- protected states: MatcherCall[];
+ protected states: Matchers.MatcherCall[];
// -----------------------------------------------
// #endregion Internal: Properties
// -----------------------------------------------
@@ -66,9 +68,9 @@ export class FullExpectation extends AbstractFinishedExpectation {
/**
* Create a new expectation for the given element.
*
- * @param element The element to query to.
+ * @param element - The element to query to.
*/
- public constructor(element: any) {
+ public constructor(element: unknown) {
super();
this.states = [];
this.element = element;
@@ -83,18 +85,18 @@ export class FullExpectation extends AbstractFinishedExpectation {
// #region IGenericExpectation implementors
// -----------------------------------------------
/** @inheritDoc {@link Expectation.not} */
- public get not(): FullExpectation {
+ public get not(): this {
this.isNot = !this.isNot;
return this;
}
/** @inheritDoc {@link Expectation.toBe} */
- public toBe(value: any): this & FinishedExpectation {
+ public toBe(value: unknown): this & FinishedExpectation {
return this.runMatcher('toBe', [value]);
}
/** @inheritDoc {@link Expectation.toBeLike} */
- public toBeLike(value: any): this & FinishedExpectation {
+ public toBeLike(value: unknown): this & FinishedExpectation {
return this.runMatcher('toBeLike', [value]);
}
@@ -210,7 +212,7 @@ export class FullExpectation extends AbstractFinishedExpectation {
}
/** @inheritDoc {@link NumberExpectation.toBeCloseTo} */
- public toBeCloseTo(value: number, digits: number = 5): this & FinishedExpectation {
+ public toBeCloseTo(value: number, digits = 5): this & FinishedExpectation {
return this.runMatcher('toBeCloseTo', [value, digits]);
}
// -----------------------------------------------
@@ -250,28 +252,34 @@ export class FullExpectation extends AbstractFinishedExpectation {
public toBeEmptyArray(count: number): this & FinishedExpectation {
return this.runMatcher('toBeEmptyArray', [count]);
}
+
/** @inheritDoc {@link ArrayExpectation.toHaveLength} */
public toHaveLength(count: number): this & FinishedExpectation {
return this.runMatcher('toHaveLength', [count]);
}
+
/** @inheritDoc {@link ArrayExpectation.toContain} */
- public toContain(value: T): this & FinishedExpectation {
+ public toContain(value: unknown): this & FinishedExpectation {
return this.runMatcher('toContain', [value]);
}
+
/** @inheritDoc {@link ArrayExpectation.toHaveAtPosition} */
- public toHaveAtPosition(value: T, position: number): this & FinishedExpectation {
+ public toHaveAtPosition(value: unknown, position: number): this & FinishedExpectation {
return this.runMatcher('toHaveAtPosition', [value, position]);
}
+
/** @inheritDoc {@link ArrayExpectation.allToSatisfy} */
- public allToSatisfy(criteria: (item: T) => boolean): this & FinishedExpectation {
+ public allToSatisfy(criteria: (item: unknown) => boolean): this & FinishedExpectation {
return this.runMatcher('allToSatisfy', [criteria]);
}
+
/** @inheritDoc {@link ArrayExpectation.anyToSatisfy} */
- public anyToSatisfy(criteria: (item: T) => boolean): this & FinishedExpectation {
+ public anyToSatisfy(criteria: (item: unknown) => boolean): this & FinishedExpectation {
return this.runMatcher('anyToSatisfy', [criteria]);
}
+
/** @inheritDoc {@link ArrayExpectation.amountToSatisfy} */
- public amountToSatisfy(count: number, criteria: (item: T) => boolean): this & FinishedExpectation {
+ public amountToSatisfy(count: number, criteria: (item: unknown) => boolean): this & FinishedExpectation {
return this.runMatcher('amountToSatisfy', [count, criteria]);
}
// -----------------------------------------------
@@ -285,24 +293,29 @@ export class FullExpectation extends AbstractFinishedExpectation {
public toBeEmptyObject(count: number): this & FinishedExpectation {
return this.runMatcher('toBeEmptyObject', [count]);
}
+
/** @inheritDoc {@link ObjectExpectation.toHavePropertyCount} */
public toHavePropertyCount(count: number): this & FinishedExpectation {
return this.runMatcher('toHavePropertyCount', [count]);
}
+
/** @inheritDoc {@link ObjectExpectation.toHaveAtLeast} */
public toHaveAtLeast(keys: string[]): this & FinishedExpectation {
return this.runMatcher('toHaveAtLeast', keys, false);
}
+
/** @inheritDoc {@link ObjectExpectation.toHaveNoOtherThan} */
public toHaveNoOtherThan(keys: string[]): this & FinishedExpectation {
return this.runMatcher('toHaveNoOtherThan', keys, false);
}
+
/** @inheritDoc {@link ObjectExpectation.toHaveProperty} */
public toHaveProperty(propertyName: string): this & FinishedExpectation {
return this.runMatcher('toHaveProperty', [propertyName]);
}
+
/** @inheritDoc {@link ObjectExpectation.toBeInstanceOf} */
- // eslint-disable-next-line @typescript-eslint/ban-types
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
public toBeInstanceOf(classConstructor: Function): this & FinishedExpectation {
return this.runMatcher('toBeInstanceOf', [classConstructor]);
}
@@ -347,13 +360,13 @@ export class FullExpectation extends AbstractFinishedExpectation {
* given arguments. The result of running the matcher is stores,
* and a new state is pushed to this particular matcher.
*
- * @param matcherName The matcher name to run
- * @param args The arguments to pass to the matcher
+ * @param matcherName - The matcher name to run
+ * @param args - The arguments to pass to the matcher
*/
- protected runMatcher(matcherName: string, args: any[], sparse: boolean = true): this {
+ protected runMatcher(matcherName: string, args: unknown[], sparse = true): this {
const matcherArgs = sparse ? [this.element, ...args] : [this.element, args];
- const matcherToCall = (Matchers as any)[matcherName] as any;
- const matcherResult = matcherToCall.call(this, ...matcherArgs);
+ const matcherToCall = Matchers[matcherName] as (actual: unknown, ...args: unknown[]) => boolean;
+ const matcherResult = matcherToCall.call(this, ...matcherArgs) as boolean;
const result = this.isNot ? !matcherResult : matcherResult;
this.states.push({
matcher: matcherName,
diff --git a/src/Expectations/Classes/JoinedExpectation.ts b/src/Expectations/Implementation/JoinedExpectation.ts
similarity index 90%
rename from src/Expectations/Classes/JoinedExpectation.ts
rename to src/Expectations/Implementation/JoinedExpectation.ts
index 71cb40d..d544ea6 100644
--- a/src/Expectations/Classes/JoinedExpectation.ts
+++ b/src/Expectations/Implementation/JoinedExpectation.ts
@@ -10,10 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Implementation
* @author Alan Rodas Bonjour
*/
+
import { AbstractFinishedExpectation } from './AbstractFinishedExpectation';
import { FinishedExpectation } from '../Interfaces';
@@ -38,8 +40,8 @@ export class JoinedExpectation extends AbstractFinishedExpectation {
* Create a new instance of a JoinedExpectation for the given set
* of expectations, using the provided joiner.
*
- * @param expectations The expectations that ought to be joined.
- * @param joiner The joiner to use to calculate the result.
+ * @param expectations - The expectations that ought to be joined.
+ * @param joiner - The joiner to use to calculate the result.
*/
public constructor(expectations: FinishedExpectation[], joiner: (expectations: FinishedExpectation[]) => boolean) {
super();
diff --git a/src/SourceReader/SourcePositions/SourceRange.ts b/src/Expectations/Implementation/index.ts
similarity index 64%
rename from src/SourceReader/SourcePositions/SourceRange.ts
rename to src/Expectations/Implementation/index.ts
index 6afc5f6..d6bc077 100644
--- a/src/SourceReader/SourcePositions/SourceRange.ts
+++ b/src/Expectations/Implementation/index.ts
@@ -10,16 +10,15 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
-/**
- * @module API.Functions
- * @author Pablo E. --Fidel-- Martínez López
- */
/**
- * Gives the string for a symbol, without the 'Symbol(...)' in it.
- * @group Static operations
+ * This module contains classes that implements the expectations system
+ * interfaces and behavior.
+ *
+ * @module Expectations/Implementation
+ * @author Alan Rodas Bonjour
*/
-export const symbolAsString = (s: symbol): string => {
- const str = s.toString();
- return str.slice(7, str.length - 1);
-};
+
+export * from './AbstractFinishedExpectation';
+export * from './FullExpectation';
+export * from './JoinedExpectation';
diff --git a/src/Expectations/Interfaces/ArrayExpectation.ts b/src/Expectations/Interfaces/ArrayExpectation.ts
index b647ca4..aa951bc 100644
--- a/src/Expectations/Interfaces/ArrayExpectation.ts
+++ b/src/Expectations/Interfaces/ArrayExpectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
diff --git a/src/Expectations/Interfaces/BooleanExpectation.ts b/src/Expectations/Interfaces/BooleanExpectation.ts
index 42d32f0..c234c2d 100644
--- a/src/Expectations/Interfaces/BooleanExpectation.ts
+++ b/src/Expectations/Interfaces/BooleanExpectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
diff --git a/src/Expectations/Interfaces/Expectation.ts b/src/Expectations/Interfaces/Expectation.ts
index 49633b8..2846352 100644
--- a/src/Expectations/Interfaces/Expectation.ts
+++ b/src/Expectations/Interfaces/Expectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
@@ -40,13 +41,13 @@ export interface Expectation {
/**
* Answers if the actual value is the same as expected, using strict compare.
* Do not use toBe with floating point numbers, use
- * {@link Matchers.toBeCloseTo} instead.
+ * {@link Expectations/Matchers.toBeCloseTo} instead.
*/
toBe(value: T): this & FinishedExpectation;
/**
* Answers if the actual value is the same as expected, using a deep compare mechanism.
* Do not use toBeLike with floating point numbers, use
- * {@link Matchers.toBeCloseTo} instead.
+ * {@link Expectations/Matchers.toBeCloseTo} instead.
*/
toBeLike(value: T): this & FinishedExpectation;
/**
diff --git a/src/Expectations/Interfaces/FinishedExpectation.ts b/src/Expectations/Interfaces/FinishedExpectation.ts
index 107b4ea..0c603f9 100644
--- a/src/Expectations/Interfaces/FinishedExpectation.ts
+++ b/src/Expectations/Interfaces/FinishedExpectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
/**
diff --git a/src/Expectations/Interfaces/NumberExpectation.ts b/src/Expectations/Interfaces/NumberExpectation.ts
index 817da06..d8225ea 100644
--- a/src/Expectations/Interfaces/NumberExpectation.ts
+++ b/src/Expectations/Interfaces/NumberExpectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
diff --git a/src/Expectations/Interfaces/ObjectExpectation.ts b/src/Expectations/Interfaces/ObjectExpectation.ts
index 2e7d5c2..d915834 100644
--- a/src/Expectations/Interfaces/ObjectExpectation.ts
+++ b/src/Expectations/Interfaces/ObjectExpectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
@@ -49,6 +50,5 @@ export interface ObjectExpectation extends Expectation {
/**
* Answer if the actual element is an instance of a given class (using instanceof).
*/
- // eslint-disable-next-line @typescript-eslint/ban-types
- toBeInstanceOf(classConstructor: Function): this & FinishedExpectation;
+ toBeInstanceOf(classConstructor: (...arguments_: readonly unknown[]) => unknown): this & FinishedExpectation;
}
diff --git a/src/Expectations/Interfaces/StringExpectation.ts b/src/Expectations/Interfaces/StringExpectation.ts
index 503128b..3b4cb5e 100644
--- a/src/Expectations/Interfaces/StringExpectation.ts
+++ b/src/Expectations/Interfaces/StringExpectation.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
diff --git a/src/Expectations/Interfaces/index.ts b/src/Expectations/Interfaces/index.ts
index c81fbf1..6e13ca5 100644
--- a/src/Expectations/Interfaces/index.ts
+++ b/src/Expectations/Interfaces/index.ts
@@ -10,10 +10,15 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * This module contains interfaces that provide the basic messages that an
+ * expectation can understand, depending on it's type.
+ *
+ * @module Expectations/Interfaces
* @author Alan Rodas Bonjour
*/
+
export * from './Expectation';
export * from './FinishedExpectation';
export * from './BooleanExpectation';
diff --git a/src/Expectations/Matchers.ts b/src/Expectations/Matchers.ts
index c50f2db..e4f39ec 100644
--- a/src/Expectations/Matchers.ts
+++ b/src/Expectations/Matchers.ts
@@ -1,3 +1,4 @@
+/* eslint-disable no-null/no-null */
/*
* *****************************************************************************
* Copyright (C) National University of Quilmes 2018-2024
@@ -10,11 +11,22 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Expectations
+ * This module contains a series of matchers, that is, a series of functions
+ * that can be called with the actual value (and in cases a series of arguments)
+ * and returns a boolean, `true` if the value satisfies the matcher, and `false`
+ * otherwise.
+ *
+ * @remarks
+ * Having the matchers separated from the instances that use the matchers allow for
+ * greater extensibility.
+ *
+ * @module Expectations/Matchers
* @author Alan Rodas Bonjour
*/
-import { deepEquals } from '../Functions/deepEquals';
+import { deepEquals } from '../Functions/Querying/deepEquals';
+import { isBuffer } from '../Functions/Querying/isBuffer';
// ===============================================
// #region MatcherCall
@@ -23,11 +35,10 @@ import { deepEquals } from '../Functions/deepEquals';
* A matcher call represents a call to a matcher with it's corresponding
* arguments and the actual result.
*
- * @group Internal: Types
*/
export interface MatcherCall {
matcher: string;
- args: any[];
+ args: unknown[];
result: boolean;
}
// ===============================================
@@ -37,261 +48,192 @@ export interface MatcherCall {
// ===============================================
// #region Matchers
// ===============================================
+
+// -----------------------------------------------
+// #region IGenericExpectation implementors
+// -----------------------------------------------
+/** Answers if the actual value is the same as expected, using strict compare */
+export const toBe = (actual: unknown, expected: unknown): boolean => actual === expected;
+/** Answers if the actual value is the same as expected, using a deep compare mechanism */
+export const toBeLike = (actual: unknown, expected: unknown): boolean => deepEquals(actual, expected);
+/** Answers if the actual value is defined (as in not equal to undefined) */
+export const toBeDefined = (actual: unknown): boolean => actual !== undefined;
+/** Answers if the actual value is undefined */
+export const toBeUndefined = (actual: unknown): boolean => actual === undefined;
+/** Answers if the actual value is null (strict null, not undefined) */
+
+export const toBeNull = (actual: unknown): boolean => actual === null;
+/** Answers if the actual value is a truthy value */
+export const toBeTruthy = (actual: unknown): boolean => !!actual;
+/** Answers if the actual value is a falsy value */
+export const toBeFalsy = (actual: unknown): boolean => !actual;
/**
- * This object contains a series of matchers, that is, a series of functions
- * that can be called with the actual value (and in cases a series of arguments)
- * and returns a boolean, `true` if the value satisfies the matcher, and `false`
- * otherwise.
- *
- * Having the matchers separated from the instances that use the matchers allow for
- * greater extensibility.
- *
- * @group Internal: Types
+ * Answers if the actual value has a type matching the expected type.
+ * This comparison is performed using the `typeof` operation over the value,
+ * with additional logic added to support 'array' as a type.
+ * @example `toHaveType([1,2,3], 'array')` returns `true` as expected.
*/
-export class Matchers {
- // -----------------------------------------------
- // #region IGenericExpectation implementors
- // -----------------------------------------------
- /** Answers if the actual value is the same as expected, using strict compare */
- public static toBe(actual: any, expected: any): boolean {
- return actual === expected;
- }
- /** Answers if the actual value is the same as expected, using a deep compare mechanism */
- public static toBeLike(actual: any, expected: any): boolean {
- return deepEquals(actual, expected);
- }
- /** Answers if the actual value is defined (as in not equal to undefined) */
- public static toBeDefined(actual: any): boolean {
- return actual !== undefined;
- }
- /** Answers if the actual value is undefined */
- public static toBeUndefined(actual: any): boolean {
- return actual === undefined;
- }
- /** Answers if the actual value is null (strict null, not undefined) */
- public static toBeNull(actual: any): boolean {
- // eslint-disable-next-line no-null/no-null
- return actual === null;
- }
- /** Answers if the actual value is a truthy value */
- public static toBeTruthy(actual: any): boolean {
- return !!actual;
- }
- /** Answers if the actual value is a falsy value */
- public static toBeFalsy(actual: any): boolean {
- return !actual;
- }
- /**
- * Answers if the actual value has a type matching the expected type.
- * This comparison is performed using the `typeof` operation over the value,
- * with additional logic added to support 'array' as a type.
- * @example `toHaveType([1,2,3], 'array')` returns `true` as expected.
- */
- public static toHaveType(actual: any, expectedType: string): boolean {
- return (
- (expectedType !== 'object' && typeof actual === expectedType) ||
- (expectedType === 'array' && typeof actual === 'object' && Array.isArray(actual)) ||
- (expectedType === 'regexp' && typeof actual === 'object' && actual instanceof RegExp) ||
- (expectedType === 'buffer' &&
- actual &&
- actual.constructor &&
- typeof actual.constructor.isBuffer === 'function' &&
- actual.constructor.isBuffer(actual)) ||
- (expectedType === 'object' && !Array.isArray(actual) && typeof actual === expectedType)
- );
- }
+export const toHaveType = (actual: unknown, expectedType: string): boolean =>
+ (expectedType !== 'object' && typeof actual === expectedType) ||
+ (expectedType === 'array' && typeof actual === 'object' && Array.isArray(actual)) ||
+ (expectedType === 'regexp' && typeof actual === 'object' && actual instanceof RegExp) ||
+ (expectedType === 'buffer' && isBuffer(actual)) ||
+ (expectedType === 'object' && !Array.isArray(actual) && typeof actual === expectedType);
- // -----------------------------------------------
- // #endregion IGenericExpectation implementors
- // -----------------------------------------------
+// -----------------------------------------------
+// #endregion IGenericExpectation implementors
+// -----------------------------------------------
- // -----------------------------------------------
- // #region IBooleanExpectation implementors
- // -----------------------------------------------
- /** Answers if the actual value is true */
- public static toBeTrue(actual: any): boolean {
- return actual === true;
- }
- /** Answers if the actual value is false */
- public static toBeFalse(actual: any): boolean {
- return actual === false;
- }
- // -----------------------------------------------
- // #endregion IBooleanExpectation implementors
- // -----------------------------------------------
+// -----------------------------------------------
+// #region IBooleanExpectation implementors
+// -----------------------------------------------
+/** Answers if the actual value is true */
+export const toBeTrue = (actual: unknown): boolean => actual === true;
+/** Answers if the actual value is false */
+export const toBeFalse = (actual: unknown): boolean => actual === false;
+// -----------------------------------------------
+// #endregion IBooleanExpectation implementors
+// -----------------------------------------------
- // -----------------------------------------------
- // #region INumberExpectation implementors
- // -----------------------------------------------
- /** Answer if the actual value is greater than the expected value. */
- public static toBeGreaterThan(actual: number, expected: number): boolean {
- return typeof actual === 'number' && actual > expected;
- }
- /** Answer if the actual value is greater than or equal than the expected value. */
- public static toBeGreaterThanOrEqual(actual: number, expected: number): boolean {
- return typeof actual === 'number' && actual >= expected;
- }
- /** Answer if the actual value is lower than the expected value. */
- public static toBeLowerThan(actual: number, expected: any): boolean {
- return typeof actual === 'number' && actual < expected;
- }
- /** Answer if the actual value is lower than or equal than the expected value. */
- public static toBeLowerThanOrEqual(actual: number, expected: number): boolean {
- return typeof actual === 'number' && actual <= expected;
- }
- /** Answer if the actual value is between the from and to values (inclusive). */
- public static toBeBetween(actual: number, from: number, to: number): boolean {
- return typeof actual === 'number' && from <= actual && actual <= to;
- }
- /** Answer if the actual value is infinity (positive or negative). */
- public static toBeInfinity(actual: number): boolean {
- return typeof actual === 'number' && (actual === Infinity || actual === -Infinity);
- }
- /** Answer if the actual value is not a number. */
- public static toBeNaN(actual: number): boolean {
- return typeof actual === 'number' && Number.isNaN(actual);
- }
- /**
- * Answer if the actual value is close to the expected value, by at least the number
- * of digits given.
- * @example `toBeCloseTo(4.0005, 4.0009, 3)` returns `true`, as there are 3
- * digits that are equal between actual and expected.
- * If no amount of digits is given, 5 is taken by default.
- */
- public static toBeCloseTo(actual: number, expected: number, numDigits: number): boolean {
- return typeof actual === 'number' && Math.abs(expected - actual) < Math.pow(10, -numDigits) / 10;
- }
- // -----------------------------------------------
- // #endregion INumberExpectation implementors
- // -----------------------------------------------
+// -----------------------------------------------
+// #region INumberExpectation implementors
+// -----------------------------------------------
+/** Answer if the actual value is greater than the expected value. */
+export const toBeGreaterThan = (actual: number, expected: number): boolean =>
+ typeof actual === 'number' && actual > expected;
+/** Answer if the actual value is greater than or equal than the expected value. */
+export const toBeGreaterThanOrEqual = (actual: number, expected: number): boolean =>
+ typeof actual === 'number' && actual >= expected;
+/** Answer if the actual value is lower than the expected value. */
+export const toBeLowerThan = (actual: number, expected: number): boolean =>
+ typeof actual === 'number' && actual < expected;
+/** Answer if the actual value is lower than or equal than the expected value. */
+export const toBeLowerThanOrEqual = (actual: number, expected: number): boolean =>
+ typeof actual === 'number' && actual <= expected;
+/** Answer if the actual value is between the from and to values (inclusive). */
+export const toBeBetween = (actual: number, from: number, to: number): boolean =>
+ typeof actual === 'number' && from <= actual && actual <= to;
+/** Answer if the actual value is infinity (positive or negative). */
+export const toBeInfinity = (actual: number): boolean =>
+ typeof actual === 'number' && (actual === Infinity || actual === -Infinity);
+/** Answer if the actual value is not a number. */
+export const toBeNaN = (actual: number): boolean => typeof actual === 'number' && Number.isNaN(actual);
+/**
+ * Answer if the actual value is close to the expected value, by at least the number
+ * of digits given.
+ * @example `toBeCloseTo(4.0005, 4.0009, 3)` returns `true`, as there are 3
+ * digits that are equal between actual and expected.
+ * If no amount of digits is given, 5 is taken by default.
+ */
+export const toBeCloseTo = (actual: number, expected: number, numDigits: number): boolean =>
+ typeof actual === 'number' && Math.abs(expected - actual) < Math.pow(10, -numDigits) / 10;
+// -----------------------------------------------
+// #endregion INumberExpectation implementors
+// -----------------------------------------------
- // -----------------------------------------------
- // #region IStringExpectation implementors
- // -----------------------------------------------
- /** Answer if the actual value has expected as a substring. */
- public static toHaveSubstring(actual: string, expected: any): boolean {
- return typeof actual === 'string' && actual.indexOf(expected) >= 0;
- }
- /** Answer if the actual value starts with the expected string. */
- public static toStartWith(actual: string, expected: any): boolean {
- return typeof actual === 'string' && actual.startsWith(expected);
- }
- /** Answer if the actual value ends with the expected string. */
- public static toEndWith(actual: string, expected: any): boolean {
- return typeof actual === 'string' && actual.endsWith(expected);
- }
- /** Answer if the actual value matches the given regexp. */
- public static toMatch(actual: string, expected: RegExp): boolean {
- return typeof actual === 'string' && expected.test(actual);
- }
- // -----------------------------------------------
- // #endregion IStringExpectation implementors
- // -----------------------------------------------
+// -----------------------------------------------
+// #region IStringExpectation implementors
+// -----------------------------------------------
+/** Answer if the actual value has expected as a substring. */
+export const toHaveSubstring = (actual: string, expected: string): boolean =>
+ typeof actual === 'string' && actual.includes(expected);
+/** Answer if the actual value starts with the expected string. */
+export const toStartWith = (actual: string, expected: string): boolean =>
+ typeof actual === 'string' && actual.startsWith(expected);
+/** Answer if the actual value ends with the expected string. */
+export const toEndWith = (actual: string, expected: string): boolean =>
+ typeof actual === 'string' && actual.endsWith(expected);
+/** Answer if the actual value matches the given regexp. */
+export const toMatch = (actual: string, expected: RegExp): boolean =>
+ typeof actual === 'string' && expected.test(actual);
+// -----------------------------------------------
+// #endregion IStringExpectation implementors
+// -----------------------------------------------
- // -----------------------------------------------
- // #region IArrayExpectation implementors
- // -----------------------------------------------
- public static toBeEmptyArray(actual: any): boolean {
- return typeof actual === 'object' && actual instanceof Array && actual.length === 0;
- }
- /** Answer if the actual value has a length of expected number. */
- public static toHaveLength(actual: any[], expected: number): boolean {
- return typeof actual === 'object' && actual instanceof Array && actual.length === expected;
- }
- /** Answer if the actual value contains the expected element. */
- public static toContain(actual: any[], expected: any): boolean {
- return typeof actual === 'object' && Array.isArray(actual) && actual.indexOf(expected) >= 0;
- }
- /**
- * Answer if the actual value has a the expected element at a given position.
- * Returns false if the position does not exist.
- */
- public static toHaveAtPosition(actual: any[], expected: any, position: number): boolean {
- return (
- typeof actual === 'object' &&
- Array.isArray(actual) &&
- actual.length > position &&
- position >= 0 &&
- actual[position] === expected
- );
- }
- /** Answer if all the element of the actual value satisfy a given criteria. */
- public static allToSatisfy(actual: any[], criteria: (elem: any) => boolean): boolean {
- return (
- typeof actual === 'object' &&
- Array.isArray(actual) &&
- actual.reduce((r, a) => criteria(a) && r, true)
- );
- }
- /** Answer if any of the element of the actual value satisfy a given criteria. */
- public static anyToSatisfy(actual: any[], criteria: (elem: any) => boolean): boolean {
- return (
- typeof actual === 'object' &&
- Array.isArray(actual) &&
- actual.reduce((r, a) => criteria(a) || r, false)
- );
- }
- /** Answer if a given amount of elements of the actual value satisfy a given criteria. */
- public static amountToSatisfy(actual: any[], amount: number, criteria: (elem: any) => boolean): boolean {
- return (
- typeof actual === 'object' &&
- Array.isArray(actual) &&
- actual.reduce((r, a) => (criteria(a) ? r + 1 : r), 0) === amount
- );
- }
- // -----------------------------------------------
- // #endregion IArrayExpectation implementors
- // -----------------------------------------------
+// -----------------------------------------------
+// #region IArrayExpectation implementors
+// -----------------------------------------------
+export const toBeEmptyArray = (actual: unknown): boolean =>
+ typeof actual === 'object' && actual instanceof Array && actual.length === 0;
+/** Answer if the actual value has a length of expected number. */
+export const toHaveLength = (actual: unknown[], expected: number): boolean =>
+ typeof actual === 'object' && actual instanceof Array && actual.length === expected;
+/** Answer if the actual value contains the expected element. */
+export const toContain = (actual: unknown[], expected: unknown): boolean =>
+ typeof actual === 'object' && Array.isArray(actual) && actual.includes(expected);
+/**
+ * Answer if the actual value has a the expected element at a given position.
+ * Returns false if the position does not exist.
+ */
+export const toHaveAtPosition = (actual: unknown[], expected: unknown, position: number): boolean =>
+ typeof actual === 'object' &&
+ Array.isArray(actual) &&
+ actual.length > position &&
+ position >= 0 &&
+ actual[position] === expected;
+/** Answer if all the element of the actual value satisfy a given criteria. */
+export const allToSatisfy = (actual: unknown[], criteria: (elem: unknown) => boolean): boolean =>
+ typeof actual === 'object' && Array.isArray(actual) && actual.reduce((r, a) => criteria(a) && r, true);
+/** Answer if any of the element of the actual value satisfy a given criteria. */
+export const anyToSatisfy = (actual: unknown[], criteria: (elem: unknown) => boolean): boolean =>
+ typeof actual === 'object' && Array.isArray(actual) && actual.reduce((r, a) => criteria(a) || r, false);
+/** Answer if a given amount of elements of the actual value satisfy a given criteria. */
+export const amountToSatisfy = (actual: unknown[], amount: number, criteria: (elem: unknown) => boolean): boolean =>
+ typeof actual === 'object' &&
+ Array.isArray(actual) &&
+ actual.reduce((r, a) => (criteria(a) ? r + 1 : r), 0) === amount;
+// -----------------------------------------------
+// #endregion IArrayExpectation implementors
+// -----------------------------------------------
- // -----------------------------------------------
- // #region IObjectExpectation implementors
- // -----------------------------------------------
- /** Answer if the actual value is empty. */
- public static toBeEmptyObject(actual: any): boolean {
- return (
- typeof actual === 'object' &&
- // eslint-disable-next-line no-null/no-null
- actual !== null &&
- Object.keys(actual).filter((e) => Object.hasOwnProperty.call(actual, e)).length === 0
- );
- }
- /** Answer if the actual element has the given amount of properties. */
- public static toHavePropertyCount(actual: any, amount: number): boolean {
- return (
- typeof actual === 'object' &&
- Object.keys(actual).filter((e) => Object.hasOwnProperty.call(actual, e)).length === amount
- );
- }
- /** Answer if an object has at least all keys in the least. Combine with
- * toHaveNoOtherThan to ensure exact key existence */
- public static toHaveAtLeast(actual: any, keys: string[]): boolean {
- if (typeof actual !== 'object') return false;
- for (const key of keys) {
- if (!actual[key]) return false;
- }
- return true;
- }
- /** Answer if an object has no other than the given keys (although not all given
- * need to be present). Combine with toHaveAtLeast to ensure exact key existence */
- public static toHaveNoOtherThan(actual: any, keys: string[]): boolean {
- if (typeof actual !== 'object') return false;
- for (const key of Object.keys(actual)) {
- if (keys.indexOf(key) < 0) {
- return false;
- }
+// -----------------------------------------------
+// #region IObjectExpectation implementors
+// -----------------------------------------------
+/** Answer if the actual value is empty. */
+export const toBeEmptyObject = (actual: unknown): boolean =>
+ typeof actual === 'object' &&
+ actual !== null &&
+ Object.keys(actual).filter((e) => Object.hasOwnProperty.call(actual, e)).length === 0;
+/** Answer if the actual element has the given amount of properties. */
+export const toHavePropertyCount = (actual: unknown, amount: number): boolean =>
+ typeof actual === 'object' &&
+ actual !== null &&
+ Object.keys(actual).filter((e) => Object.hasOwnProperty.call(actual, e)).length === amount;
+/** Answer if an object has at least all keys in the least. Combine with
+ * toHaveNoOtherThan to ensure exact key existence */
+export const toHaveAtLeast = (actual: unknown, keys: string[]): boolean => {
+ if (typeof actual !== 'object') return false;
+
+ if (actual === null) return false;
+ for (const key of keys) {
+ if (!actual[key]) return false;
+ }
+ return true;
+};
+/** Answer if an object has no other than the given keys (although not all given
+ * need to be present). Combine with toHaveAtLeast to ensure exact key existence */
+export const toHaveNoOtherThan = (actual: unknown, keys: string[]): boolean => {
+ if (typeof actual !== 'object') return false;
+
+ if (actual === null) return false;
+ for (const key of Object.keys(actual)) {
+ if (!keys.includes(key)) {
+ return false;
}
- return true;
- }
- /** Answer if the actual element has a property with the given name. */
- public static toHaveProperty(actual: any, propertyName: string): boolean {
- return typeof actual === 'object' && Object.prototype.hasOwnProperty.call(actual, propertyName);
}
- /** Answer if the actual element is an instance of a given class (using instanceof). */
- // eslint-disable-next-line @typescript-eslint/ban-types
- public static toBeInstanceOf(actual: any, classConstructor: Function): boolean {
- return typeof actual === 'object' && actual instanceof classConstructor;
- }
-}
+ return true;
+};
+/** Answer if the actual element has a property with the given name. */
+export const toHaveProperty = (actual: unknown, propertyName: string): boolean =>
+ typeof actual === 'object' &&
+ actual !== null &&
+ (Object.prototype.hasOwnProperty.call(actual, propertyName) as boolean);
+
+/** Answer if the actual element is an instance of a given class (using instanceof). */
+export const toBeInstanceOf = (
+ actual: unknown,
+ classConstructor: (...arguments_: readonly unknown[]) => unknown
+): boolean => typeof actual === 'object' && actual instanceof classConstructor;
// ===============================================
// #endregion Matchers
// ===============================================
diff --git a/src/Expectations/expect.ts b/src/Expectations/expect.ts
index f7e9e86..63d9ce5 100644
--- a/src/Expectations/expect.ts
+++ b/src/Expectations/expect.ts
@@ -11,11 +11,10 @@
* *****************************************************************************
*/
/**
- * @module API.Expectations
+ * @module Expectations
* @author Alan Rodas Bonjour
*/
-import { FullExpectation } from './Classes/FullExpectation';
-import { JoinedExpectation } from './Classes/JoinedExpectation';
+import { FullExpectation, JoinedExpectation } from './Implementation';
import {
ArrayExpectation,
BooleanExpectation,
@@ -30,54 +29,53 @@ import {
* depends on the type of the element passed, and thus, different matchers may be
* executed over the expectation.
* The generic matchers can be called over any expectation for any element, this include:
- * * {@link Matchers.toBe | toBe}
- * * {@link Matchers.toBeLike | toBeLike}
- * * {@link Matchers.toBeDefined | toBeDefined}
- * * {@link Matchers.toBeUndefined | toBeUndefined}
- * * {@link Matchers.toBeNull | toBeNull}
- * * {@link Matchers.toBeTruthy | toBeTruthy}
- * * {@link Matchers.toBeFalsy | toBeFalsy}
- * * {@link Matchers.toHaveType | toHaveType}
+ * * {@link Expectations/Matchers.toBe | toBe}
+ * * {@link Expectations/Matchers.toBe | toBe}
+ * * {@link Expectations/Matchers.toBeLike | toBeLike}
+ * * {@link Expectations/Matchers.toBeDefined | toBeDefined}
+ * * {@link Expectations/Matchers.toBeUndefined | toBeUndefined}
+ * * {@link Expectations/Matchers.toBeNull | toBeNull}
+ * * {@link Expectations/Matchers.toBeTruthy | toBeTruthy}
+ * * {@link Expectations/Matchers.toBeFalsy | toBeFalsy}
+ * * {@link Expectations/Matchers.toHaveType | toHaveType}
*
* If the given element is a number, then an {@link NumberExpectation} is returned, and so
* the following additional matchers are added to the previous list:
- * * {@link Matchers.toBeGreaterThan | toBeGreaterThan}
- * * {@link Matchers.toBeGreaterThanOrEqual | toBeGreaterThanOrEqual}
- * * {@link Matchers.toBeLowerThan | toBeLowerThan}
- * * {@link Matchers.toBeLowerThanOrEqual | toBeLowerThanOrEqual}
- * * {@link Matchers.toBeBetween | toBeBetween}
- * * {@link Matchers.toBeInfinity | toBeInfinity}
- * * {@link Matchers.toBeNaN | toBeNaN}
- * * {@link Matchers.toBeCloseTo | toBeCloseTo}
+ * * {@link Expectations/Matchers.toBeGreaterThan | toBeGreaterThan}
+ * * {@link Expectations/Matchers.toBeGreaterThanOrEqual | toBeGreaterThanOrEqual}
+ * * {@link Expectations/Matchers.toBeLowerThan | toBeLowerThan}
+ * * {@link Expectations/Matchers.toBeLowerThanOrEqual | toBeLowerThanOrEqual}
+ * * {@link Expectations/Matchers.toBeBetween | toBeBetween}
+ * * {@link Expectations/Matchers.toBeInfinity | toBeInfinity}
+ * * {@link Expectations/Matchers.toBeNaN | toBeNaN}
+ * * {@link Expectations/Matchers.toBeCloseTo | toBeCloseTo}
*
* If a string is used instead, the list is expanded with the following matchers:
- * * {@link Matchers.toHaveSubstring | toHaveSubstring}
- * * {@link Matchers.toStartWith | toStartWith}
- * * {@link Matchers.toEndWith | toEndWith}
- * * {@link Matchers.toMatch | toMatch}
+ * * {@link Expectations/Matchers.toHaveSubstring | toHaveSubstring}
+ * * {@link Expectations/Matchers.toStartWith | toStartWith}
+ * * {@link Expectations/Matchers.toEndWith | toEndWith}
+ * * {@link Expectations/Matchers.toMatch | toMatch}
* Note that matchers for string to not check things such as size, if you want that,
* we recommend calling expect over the string length and not the whole string.
*
* For the case of arrays, additional to the general ones, the following matchers
* are provided, that allow to test things over the elements of the array.
- * * {@link Matchers.toHaveLength | toHaveLength}
- * * {@link Matchers.toContain | toContain}
- * * {@link Matchers.toHaveAtPosition | toHaveAtPosition}
- * * {@link Matchers.allToSatisfy | allToSatisfy}
- * * {@link Matchers.anyToSatisfy | anyToSatisfy}
- * * {@link Matchers.amountToSatisfy | amountToSatisfy}
+ * * {@link Expectations/Matchers.toHaveLength | toHaveLength}
+ * * {@link Expectations/Matchers.toContain | toContain}
+ * * {@link Expectations/Matchers.toHaveAtPosition | toHaveAtPosition}
+ * * {@link Expectations/Matchers.allToSatisfy | allToSatisfy}
+ * * {@link Expectations/Matchers.anyToSatisfy | anyToSatisfy}
+ * * {@link Expectations/Matchers.amountToSatisfy | amountToSatisfy}
*
* For object, the focus of the matcher is put on the instance type (class it belongs to)
* and the properties it contains (attribute keys), extending so with:
- * * {@link Matchers.toHavePropertyCount | toHavePropertyCount}
- * * {@link Matchers.toHaveAtLeast | toHaveAtLeast}
- * * {@link Matchers.toHaveNoOtherThan | toHaveNoOtherThan}
- * * {@link Matchers.toHaveProperty | toHaveProperty}
- * * {@link Matchers.toBeInstanceOf | toBeInstanceOf}
+ * * {@link Expectations/Matchers.toHavePropertyCount | toHavePropertyCount}
+ * * {@link Expectations/Matchers.toHaveAtLeast | toHaveAtLeast}
+ * * {@link Expectations/Matchers.toHaveNoOtherThan | toHaveNoOtherThan}
+ * * {@link Expectations/Matchers.toHaveProperty | toHaveProperty}
+ * * {@link Expectations/Matchers.toBeInstanceOf | toBeInstanceOf}
*
- * @param element The element that is going to be queried by the created expectation.
- *
- * @group API: Main
+ * @param element - The element that is going to be queried by the created expectation.
*/
export function expect(element?: boolean): BooleanExpectation;
export function expect(element?: number): NumberExpectation;
@@ -85,18 +83,16 @@ export function expect(element?: string): StringExpectation;
export function expect(element?: T[]): ArrayExpectation;
export function expect(element?: T): ObjectExpectation;
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
-export function expect(element?: any): any {
- return new FullExpectation(element);
+export function expect(element?: unknown): unknown {
+ return new FullExpectation(element);
}
/**
* Create a new {@link JoinedExpectation} where all the expectations need to
* have a `true` result in order for the result of the joined one to be also
* `true`. That is, an expectation that joins it's components with a logical and.
- * @param expectations A list of expectations that need to be fulfilled in order to
+ * @param expectations - A list of expectations that need to be fulfilled in order to
* return `true` as result.
- *
- * @group API: Main
*/
export const and = (...expectations: FinishedExpectation[]): FinishedExpectation =>
new JoinedExpectation(expectations, (exp) => exp.reduce((r, e) => r && e.getResult(), true));
@@ -105,10 +101,8 @@ export const and = (...expectations: FinishedExpectation[]): FinishedExpectation
* Create a new {@link JoinedExpectation} where any of the expectations need to
* have a `true` result in order for the result of the joined one to be also
* `true`. That is, an expectation that joins it's components with a logical or.
- * @param expectations A list of expectations where one need to be fulfilled in order to
+ * @param expectations - A list of expectations where one need to be fulfilled in order to
* return `true` as result.
- *
- * @group API: Main
*/
export const or = (...expectations: FinishedExpectation[]): FinishedExpectation =>
new JoinedExpectation(expectations, (exp) => exp.reduce((r, e) => r || e.getResult(), false));
diff --git a/src/Expectations/index.ts b/src/Expectations/index.ts
index 5d22244..4a449ff 100644
--- a/src/Expectations/index.ts
+++ b/src/Expectations/index.ts
@@ -10,29 +10,7 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2012-2024
- * Gobstones (TM) is a registered trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3. Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.org/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2012-2024
- * Gobstones is a registered trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- *
- * Additional terms added in compliance to section 7 of such license apply.
- * You may read the full license at https://gobstones.github.org/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
+
/**
* This module exports the {@link expect} function, that is the kickoff to
* create "expectations" over a specific element as shown in the following
@@ -54,15 +32,15 @@ expect(x+y).toBeGreaterThan(z)
* expect.
*
* When a matcher is called, the element given to expect is passed to the
- * {@link Matchers} as the actual value, where the additional arguments over the
+ * {@link Expectations/Matchers} as the actual value, where the additional arguments over the
* matcher are the arguments given to the matcher method called, so for example,
- * `expect(x).toBe(y)` calls the {@link Matchers.toBe} with `x` as `actual` argument
+ * `expect(x).toBe(y)` calls the {@link Expectations/Matchers.toBe} with `x` as `actual` argument
* and `y` as `expected` argument.
*
- * Once the first matcher is called over an expectation, a {@link FinishedExpectation}
+ * Once the first matcher is called over an expectation, a {@link Expectations/Interfaces.FinishedExpectation}
* is obtained. A finished matcher has a result, that may be one of `true`
* (if the matcher was satisfied) or `false` if not. A finished matcher may be
- * queried for the result, by calling {@link FinishedExpectation.getResult | getResult},
+ * queried for the result, by calling {@link Expectations/Interfaces.FinishedExpectation.getResult | getResult},
* but additional helper methods are provided by the interface in order to fulfill
* different needs, such as throwing an error if the expectation was not satisfied,
* or calling a function if it was.
@@ -71,14 +49,14 @@ expect(x+y).toBeGreaterThan(z)
* matcher would be calculated as an "and" over all the results. e.g.
* `expect(x).toBeGreaterThan(y).toBeLowerThan(z)`. This creates a new expectations
* that is satisfied only when both parts (x being greater than y, and x being
- * lower than z) are true. This itself returns a new {@link FinishedExpectation},
+ * lower than z) are true. This itself returns a new {@link Expectations/Interfaces.FinishedExpectation},
* that can be extended with new matchers, or queried about the results as
* previously mentioned.
*
* To see a list of all matchers, read the {@link expect} documentation, and the
- * {@link Matchers} documentation.
+ * {@link Expectations/Matchers} documentation.
*
- * @module API.Expectations
+ * @module Expectations
* @author Alan Rodas Bonjour
*/
export * from './expect';
diff --git a/src/Functions/Conversion/asDefined.ts b/src/Functions/Conversion/asDefined.ts
new file mode 100644
index 0000000..277ecbf
--- /dev/null
+++ b/src/Functions/Conversion/asDefined.ts
@@ -0,0 +1,41 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Functions/Conversion
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * Returns a typed defined version of the given value.
+ *
+ * Given a value that may be undefined to the typechecker, but,
+ * you are sure that in runtime it would never be so, as per
+ * your preconditions, this function returns a typed defined version
+ * of the value.
+ *
+ * @remarks
+ * This is just an identity function, where the value
+ * is return as-is. This function only exist as to pass
+ * the static typechecking system in some particular
+ * scenarios, to avoid casting in multiple places.
+ *
+ * @param x - The value to return.
+ *
+ * @returns The given value.
+ */
+export const asDefined = (x: T | undefined): T => {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+ const ret = x as T;
+ return ret;
+};
diff --git a/src/Translations/index.ts b/src/Functions/Conversion/index.ts
similarity index 52%
rename from src/Translations/index.ts
rename to src/Functions/Conversion/index.ts
index da57019..642610a 100644
--- a/src/Translations/index.ts
+++ b/src/Functions/Conversion/index.ts
@@ -10,18 +10,14 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * This module provides mechanisms to support basic localization of strings.
- * This allows for error messages and CLI to support different languages
- * without much effort.
+ * This module provides different functions that provide conversion between
+ * objects, types or shapes, as well as creation of some basic shapes.
*
- * Note that this module does not provide localization for the Gobstones Language
- * but for a tool internally, and should not be confused with other classes
- * exposed by this package. If you want to learn about how to translate the
- * Gobstones Language see
- * [The Gobstones Language Translation Module](https://gobstones.github.io/gobstones-lang-intl).
- *
- * @module API.Translator
+ * @module Functions/Conversion
* @author Alan Rodas Bonjour
*/
-export * from './Translator';
+export * from './asDefined';
+export * from './matrix';
+export * from './symbolAsString';
diff --git a/src/Functions/matrix.ts b/src/Functions/Conversion/matrix.ts
similarity index 83%
rename from src/Functions/matrix.ts
rename to src/Functions/Conversion/matrix.ts
index 06a8a78..f03ab49 100644
--- a/src/Functions/matrix.ts
+++ b/src/Functions/Conversion/matrix.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Functions
+ * @module Functions/Conversion
* @author Alan Rodas Bonjour
*/
@@ -21,14 +22,12 @@
*
* @throws Error if the width or the height given are zero or negative.
*
- * @param width - The number of rows of the matrix
- * @param height - The number of columns of the matrix
- * @param initialValueGenerator - A function that given the i,j position of the element returns
+ * @param width - - The number of rows of the matrix
+ * @param height - - The number of columns of the matrix
+ * @param initialValueGenerator - - A function that given the i,j position of the element returns
* the element to store the matrix at that position
*
* @returns A `T[][]` where T is the type of the elements in the matrix.
- *
- * @group API: Functions
*/
export const matrix = (
width: number,
@@ -45,5 +44,5 @@ export const matrix = (
generatedMatrix[i][j] = initialValueGenerator ? initialValueGenerator(i, j) : undefined;
}
}
- return generatedMatrix as T[][];
+ return generatedMatrix;
};
diff --git a/src/Functions/symbolAsString.ts b/src/Functions/Conversion/symbolAsString.ts
similarity index 94%
rename from src/Functions/symbolAsString.ts
rename to src/Functions/Conversion/symbolAsString.ts
index 6afc5f6..a677b36 100644
--- a/src/Functions/symbolAsString.ts
+++ b/src/Functions/Conversion/symbolAsString.ts
@@ -10,14 +10,14 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Functions
+ * @module Functions/Conversion
* @author Pablo E. --Fidel-- Martínez López
*/
/**
* Gives the string for a symbol, without the 'Symbol(...)' in it.
- * @group Static operations
*/
export const symbolAsString = (s: symbol): string => {
const str = s.toString();
diff --git a/src/Functions/ExecutionManagement/debounce.ts b/src/Functions/ExecutionManagement/debounce.ts
new file mode 100644
index 0000000..6a2f905
--- /dev/null
+++ b/src/Functions/ExecutionManagement/debounce.ts
@@ -0,0 +1,160 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Functions/ExecutionManagement
+ * @author Alan Rodas Bonjour
+ */
+
+import { AnyFunction } from '../../Types/AnyFunction';
+
+/**
+ * @module Functions
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * Most of the code is copied from the `debounce` library by
+ * Sindre Sorhus (MIT licensed),
+ * but it's copied here to avoid extra dependencies.
+ */
+
+/**
+ * The type of a function that was debounced.
+ *
+ * @internal
+ */
+export interface DebouncedFunction {
+ (...arguments_: Parameters): ReturnType | undefined;
+ /** cancels any scheduled executions. */
+ clear(): void;
+ /** if an execution is scheduled then it will be immediately executed and the timer will be cleared. */
+ flush(): void;
+ /** executes the function immediately and clears the timer if it was previously set. */
+ trigger(): void;
+}
+
+/**
+ * Returns a debounced function that delays execution until wait milliseconds have
+ * passed since its last invocation.
+ *
+ * @remarks
+ * Debouncing postpones the execution until after a period of inactivity.
+ * It's ideal for tasks that don't need to execute repeatedly in quick succession,
+ * such as API calls based on user input.
+ *
+ * @privateRemarks
+ * Note that this cannot be converted to an arrow function, because the context
+ * of `this` is important during the call. Arrow functions significantly change the
+ * way the context is managed.
+ *
+ * @param func - The function to debounce.
+ * @param wait - The number of milliseconds to wait before calling the function.
+ * @param options - Additional options for the function.
+ *
+ * @returns A debounced function.
+ */
+// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
+export function debounce(
+ func: F,
+ wait = 100,
+ options: { immediate: boolean } = { immediate: false }
+): DebouncedFunction {
+ if (typeof func !== 'function') {
+ throw new TypeError(`Expected the first parameter to be a function, got \`${typeof func}\`.`);
+ }
+
+ if (wait < 0) {
+ throw new RangeError('`wait` must not be negative.');
+ }
+
+ let storedContext: unknown;
+ let storedArguments: unknown[] | undefined;
+ let timeoutId: unknown; // The timeout handle, platform dependent
+ let timestamp = 0;
+ let result: ReturnType | undefined;
+
+ const run = (): ReturnType | undefined => {
+ const callContext = storedContext;
+ const callArguments = storedArguments;
+ storedContext = undefined;
+ storedArguments = undefined;
+ result = func.apply(callContext, callArguments) as ReturnType;
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ return result;
+ };
+
+ const later = (): void => {
+ const last = Date.now() - timestamp;
+
+ if (last < wait && last >= 0) {
+ timeoutId = setTimeout(later, wait - last);
+ } else {
+ timeoutId = undefined;
+
+ if (!options.immediate) {
+ result = run();
+ }
+ }
+ };
+
+ const debounced = function (...args): ReturnType | undefined {
+ // eslint-disable-next-line no-invalid-this
+ if (storedContext && this !== storedContext) {
+ throw new Error('Debounced method called with different contexts.');
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-this-alias, no-invalid-this
+ storedContext = this;
+ storedArguments = args;
+ timestamp = Date.now();
+
+ const callNow = options.immediate && !timeoutId;
+
+ if (!timeoutId) {
+ timeoutId = setTimeout(later, wait);
+ }
+
+ if (callNow) {
+ result = run();
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ return result;
+ };
+
+ debounced.clear = () => {
+ if (!timeoutId) {
+ return;
+ }
+
+ clearTimeout(timeoutId as string | number);
+ timeoutId = undefined;
+ };
+
+ debounced.flush = () => {
+ if (!timeoutId) {
+ return;
+ }
+
+ debounced.trigger();
+ };
+
+ debounced.trigger = () => {
+ result = run();
+
+ debounced.clear();
+ };
+
+ return debounced;
+}
diff --git a/src/Functions/ExecutionManagement/index.ts b/src/Functions/ExecutionManagement/index.ts
new file mode 100644
index 0000000..3952759
--- /dev/null
+++ b/src/Functions/ExecutionManagement/index.ts
@@ -0,0 +1,22 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * This module provides different functions that provide different ways to
+ * manage how functions are executed.
+ *
+ * @module Functions/ExecutionManagement
+ * @author Alan Rodas Bonjour
+ */
+export * from './debounce';
+export * from './throttle';
diff --git a/src/Functions/ExecutionManagement/throttle.ts b/src/Functions/ExecutionManagement/throttle.ts
new file mode 100644
index 0000000..b06e827
--- /dev/null
+++ b/src/Functions/ExecutionManagement/throttle.ts
@@ -0,0 +1,110 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Functions/ExecutionManagement
+ * @author Alan Rodas Bonjour
+ */
+
+import { AnyFunction } from '../../Types/AnyFunction';
+
+/**
+ * Most of the code is copied from the `throttleit` library by
+ * Sindre Sorhus (MIT licensed),
+ * but it's copied here to avoid extra dependencies.
+ */
+
+/**
+ * The type of a function that was throttled.
+ *
+ * @internal
+ */
+export interface ThrotteledFunction {
+ // eslint-disable-next-line @typescript-eslint/prefer-function-type
+ (...arguments_: Parameters): ReturnType | undefined;
+}
+
+/**
+ * Returns a throttled function that limits calls to the original function to
+ * at most once every wait milliseconds. It guarantees execution after the final
+ * invocation and maintains the last context (this) and arguments.
+ *
+ * @remarks
+ * Throttling limits the execution to a fixed number of times over an interval.
+ * Throttling is suited for controlling the execution rate of functions called
+ * in response to events like scrolling or resizing.
+ *
+ * @privateRemarks
+ * Note that this cannot be converted to an arrow function, because the context
+ * of `this` is important during the call. Arrow functions significantly change the
+ * way the context is managed.
+ *
+ * @param func - The function to throttle
+ * @param wait - How many milliseconds to wait before running the function again.
+ *
+ * @returns A throttled function.
+ */
+// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
+export function throttle(func: F, wait: number): ThrotteledFunction {
+ if (typeof func !== 'function') {
+ throw new TypeError(`Expected the first argument to be a \`function\`, got \`${typeof func}\`.`);
+ }
+
+ if (wait < 0) {
+ throw new RangeError('`wait` must not be zero or negative.');
+ }
+
+ let storedContext: unknown;
+ let storedArguments: unknown[] | undefined;
+ let timeoutId: unknown; // The timeout handle, platform dependent
+ let lastCallTime = 0;
+ let result: ReturnType | undefined;
+
+ const run = (): ReturnType | undefined => {
+ const callContext = storedContext;
+ const callArguments = storedArguments;
+ storedContext = undefined;
+ storedArguments = undefined;
+ result = func.apply(callContext, callArguments) as ReturnType;
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ return result;
+ };
+
+ const throttled = function (...args): ReturnType | undefined {
+ clearTimeout(timeoutId as string | number);
+
+ const now = Date.now();
+ const timeSinceLastCall = now - lastCallTime;
+ const delayForNextCall = wait - timeSinceLastCall;
+
+ // eslint-disable-next-line @typescript-eslint/no-this-alias, no-invalid-this
+ storedContext = this;
+ storedArguments = args;
+
+ if (delayForNextCall <= 0) {
+ lastCallTime = now;
+
+ run();
+ } else {
+ timeoutId = setTimeout(() => {
+ lastCallTime = Date.now();
+ run();
+ }, delayForNextCall);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+ return result;
+ };
+
+ return throttled;
+}
diff --git a/src/Functions/deepStringAssign.ts b/src/Functions/ObjectManipulation/deepStringAssign.ts
similarity index 87%
rename from src/Functions/deepStringAssign.ts
rename to src/Functions/ObjectManipulation/deepStringAssign.ts
index 3e7b8bb..4e9a0db 100644
--- a/src/Functions/deepStringAssign.ts
+++ b/src/Functions/ObjectManipulation/deepStringAssign.ts
@@ -10,11 +10,13 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Functions
+ * @module Functions/ObjectManipulation
* @author Pablo E. --Fidel-- Martínez López
*/
-import { Subset } from '../Types/Subset';
+
+import { Subset } from '../../Types/Subset';
/**
* It returns a copy of the target object, where its string keys has been overwritten with
@@ -57,12 +59,11 @@ import { Subset } from '../Types/Subset';
* ```
*
* PRECONDITION: the keys of the objects have compatible types (that is, `T` is not just `object`).
- * @param target An object that provides the default values for the fields of the result.
- * @param sources A span parameter with objects possibly containing values to replace the defaults
+ * @param target - An object that provides the default values for the fields of the result.
+ * @param sources - A span parameter with objects possibly containing values to replace the defaults
* in string keys with strings as values.
- * @group API: Main
*/
-export function deepStringAssign(target: T, ...sources: Subset[]): T {
+export const deepStringAssign = (target: T, ...sources: Subset[]): T => {
// Needed for deepStringAssign not to overwrite the target
const cloneTarget = JSON.parse(JSON.stringify(target)) as T;
for (const source of sources) {
@@ -70,12 +71,12 @@ export function deepStringAssign(target: T, ...sources: Subset
const key = k as keyof T;
if (typeof source[key] === 'object') {
const tmp = cloneTarget[key] as object;
- cloneTarget[key] = deepStringAssign(tmp, source[key] as object) as any;
+ cloneTarget[key] = deepStringAssign(tmp, source[key] as object) as unknown as T[keyof T];
}
if (typeof source[key] === 'string') {
- cloneTarget[key] = source[key] as any;
+ cloneTarget[key] = source[key] as unknown as T[keyof T];
}
}
}
return cloneTarget;
-}
+};
diff --git a/src/Functions/flatten.ts b/src/Functions/ObjectManipulation/flatten.ts
similarity index 70%
rename from src/Functions/flatten.ts
rename to src/Functions/ObjectManipulation/flatten.ts
index 175c76b..5c66595 100644
--- a/src/Functions/flatten.ts
+++ b/src/Functions/ObjectManipulation/flatten.ts
@@ -10,17 +10,20 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Functions
+ * @module Functions/ObjectManipulation
* @author Alan Rodas Bonjour
- *
+ */
+
+/**
* Most of the code is copied from the `flat` library by
* Hugh Kennedy (BSD-3 licensed),
- * but it's copied here to avoid a dependency that may break
- * when using ESM instead of CJS.
+ * but it's copied here to avoid extra dependencies.
*/
-import { isBuffer } from './isBuffer';
+import { asDefined } from '../Conversion/asDefined';
+import { isBuffer } from '../Querying/isBuffer';
/**
* This type represent the options that are available for
@@ -29,7 +32,6 @@ import { isBuffer } from './isBuffer';
* and we do not recommend to relay on them, as they might change
* in the future.
*
- * @group Internal: Types
* @internal
*/
export interface FlattenOptions {
@@ -46,7 +48,6 @@ export interface FlattenOptions {
* and we do not recommend to relay on them, as they might change
* in the future.
*
- * @group Internal: Types
* @internal
*/
export interface UnflattenOptions {
@@ -89,22 +90,22 @@ flatten({
*
* For an inverse operation see {@link unflatten}.
*
- * @param target The element to flatten.
- * @param options The option to flatten.
+ * @param target - The element to flatten.
+ * @param options - The option to flatten.
*
- * @group API: Functions
+ * @returns The flattened object
*/
-export function flatten, TResult extends Record>(
+export const flatten = , TResult extends Record>(
target: TTarget,
options: Partial = {}
-): TResult {
+): TResult => {
const opts: FlattenOptions = Object.assign({}, flattenOptionsDefaults, options);
- const output: Record = {};
+ const output: Record = {};
- function step(object: any, prev?: any, currentDepth: number = 1): void {
- Object.keys(object).forEach(function (key) {
- const value: any = object[key];
- const type: string = Object.prototype.toString.call(value);
+ const step = (object: Record, prev?: string, currentDepth = 1): void => {
+ Object.keys(object).forEach((key) => {
+ const value: unknown = object[key];
+ const type: string = Object.prototype.toString.call(value) as string;
const isarray: boolean = opts.safe && Array.isArray(value);
const isbuffer: boolean = isBuffer(value);
const isobject: boolean = type === '[object Object]' || type === '[object Array]';
@@ -115,20 +116,21 @@ export function flatten, TResult extends Rec
!isarray &&
!isbuffer &&
isobject &&
- Object.keys(value).length &&
+ Object.keys(value as Record).length &&
(!opts.maxDepth || currentDepth < opts.maxDepth)
) {
- return step(value, newKey, currentDepth + 1);
+ step(value as Record, newKey, currentDepth + 1);
+ return;
}
output[newKey] = value;
});
- }
+ };
step(target);
return output as TResult;
-}
+};
/**
* Un-Flatten the given object.
@@ -161,17 +163,18 @@ unflatten({
* Additional options may be passed, such as which character is used as a delimiter,
* or the maximum depth level.
*
- * @param target The element to unflatten.
- * @param options The option to unflatten.
+ * @param target - The element to unflatten.
+ * @param options - The option to unflatten.
*
- * @group API: Functions
+ * @returns The unflattened object
*/
-export function unflatten, TResult extends Record>(
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const unflatten = , TResult extends Record>(
target: TTarget,
options?: Partial
-): TResult {
+): TResult => {
const opts: UnflattenOptions = Object.assign({}, unflattenOptionsDefaults, options);
- const output = {};
+ const output: Record = {};
const isbuffer = isBuffer(target);
if (isbuffer || Object.prototype.toString.call(target) !== '[object Object]') {
@@ -179,19 +182,23 @@ export function unflatten, TResult extends R
}
// return the key as a string or as an integer
- function getKey(key: string): string | number {
+ const getKey = (key: string): string | number => {
const parsedKey = Number(key);
- return isNaN(parsedKey) || key.indexOf('.') !== -1 || opts.object ? key : parsedKey;
- }
+ return isNaN(parsedKey) || key.includes('.') || opts.object ? key : parsedKey;
+ };
- const addKeys = (keyPrefix: string, recipient: any, targeted: any): any =>
- Object.keys(targeted).reduce(function (acc, key) {
+ const addKeys = (
+ keyPrefix: string,
+ recipient: Record,
+ targeted: Record
+ ): Record =>
+ Object.keys(targeted).reduce((acc, key) => {
acc[keyPrefix + opts.delimiter + key] = targeted[key];
return acc;
}, recipient);
- function isEmpty(val: any): boolean {
- const type = Object.prototype.toString.call(val);
+ const isEmpty = (val: unknown): boolean => {
+ const type = Object.prototype.toString.call(val) as string;
const isArray = type === '[object Array]';
const isObject = type === '[object Object]';
@@ -199,28 +206,28 @@ export function unflatten, TResult extends R
if (!val) {
return true;
} else if (isArray) {
- return !val.length;
+ return !(val as unknown[]).length;
} else if (isObject) {
return !Object.keys(val).length;
}
/* istanbul ignore next */
return false;
- }
+ };
- target = Object.keys(target).reduce(function (acc: Record, key: string) {
- const type = Object.prototype.toString.call(target[key]);
+ target = Object.keys(target).reduce>((acc: Record, key: string) => {
+ const type = Object.prototype.toString.call(target[key]) as string;
const isObject = type === '[object Object]' || type === '[object Array]';
if (!isObject || isEmpty(target[key])) {
acc[key] = target[key];
return acc;
} else {
- return addKeys(key, acc, flatten(target[key], opts));
+ return addKeys(key, acc, flatten(target[key] as Record, opts));
}
}, {}) as TTarget;
- Object.keys(target).forEach(function (key) {
+ Object.keys(target).forEach((key) => {
const split = key.split(opts.delimiter).map(opts.transformKey);
- let key1 = getKey(split.shift() as string);
+ let key1 = getKey(asDefined(split.shift()));
let key2 = getKey(split[0]);
let recipient = output;
@@ -229,58 +236,56 @@ export function unflatten, TResult extends R
return;
}
- const type = Object.prototype.toString.call((recipient as any)[key1]);
+ const type = Object.prototype.toString.call(recipient[key1]) as string;
const isobject = type === '[object Object]' || type === '[object Array]';
// do not write over falsey, non-undefined values if overwrite is false
- if (!opts.overwrite && !isobject && typeof (recipient as any)[key1] !== 'undefined') {
+ if (!opts.overwrite && !isobject && typeof recipient[key1] !== 'undefined') {
return;
}
if (
(opts.overwrite && !isobject) ||
// eslint-disable-next-line no-null/no-null
- (!opts.overwrite && (recipient as any)[key1] == null)
+ (!opts.overwrite && recipient[key1] == null)
) {
- (recipient as any)[key1] = typeof key2 === 'number' && !opts.object ? [] : {};
+ recipient[key1] = typeof key2 === 'number' && !opts.object ? [] : {};
}
- recipient = (recipient as any)[key1];
+ recipient = recipient[key1] as Record;
if (split.length > 0) {
- key1 = getKey(split.shift() as string);
+ key1 = getKey(asDefined(split.shift()));
key2 = getKey(split[0]);
}
}
// unflatten again for 'messy objects'
- (recipient as any)[key1] = unflatten((target as any)[key], opts);
+ recipient[key1] = unflatten(target[key] as Record, opts);
});
return output as TResult;
-}
+};
/**
* The default options for the flatten function.
*
- * @group Internal: Objects
* @internal
*/
const flattenOptionsDefaults: FlattenOptions = {
delimiter: '.',
maxDepth: undefined,
safe: false,
- transformKey: (key: any): any => key
+ transformKey: (key: string): string => key
};
/**
* The default options for the unflatten function.
*
- * @group Internal: Objects
* @internal
*/
const unflattenOptionsDefaults: UnflattenOptions = {
delimiter: '.',
object: false,
overwrite: false,
- transformKey: (key: any): any => key
+ transformKey: (key: string): string => key
};
diff --git a/src/Functions/ObjectManipulation/index.ts b/src/Functions/ObjectManipulation/index.ts
new file mode 100644
index 0000000..66f7ad9
--- /dev/null
+++ b/src/Functions/ObjectManipulation/index.ts
@@ -0,0 +1,22 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * This module provides different functions that provide different ways to
+ * change an object's shape and values.
+ *
+ * @module Functions/ObjectManipulation
+ * @author Alan Rodas Bonjour
+ */
+export * from './deepStringAssign';
+export * from './flatten';
diff --git a/src/Functions/deepEquals.ts b/src/Functions/Querying/deepEquals.ts
similarity index 86%
rename from src/Functions/deepEquals.ts
rename to src/Functions/Querying/deepEquals.ts
index f756fde..b4997ea 100644
--- a/src/Functions/deepEquals.ts
+++ b/src/Functions/Querying/deepEquals.ts
@@ -10,13 +10,16 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Functions
+ * @module Functions/Querying
* @author Alan Rodas Bonjour
*/
import { isBuffer } from './isBuffer';
+import { asDefined } from '../Conversion/asDefined';
+
/**
* Answer wether or not two elements are semantically equal, considering them
* equal when they have the same type and all their internal elements are
@@ -58,15 +61,13 @@ import { isBuffer } from './isBuffer';
* If you want to see all supported and unsupported cases, we recommend you to check
* out the test cases.
*
- * @param first The element to compare to.
- * @param second The element to compare against.
+ * @param first - The element to compare to.
+ * @param second - The element to compare against.
*
* @return `true` if both elements are equal, `false` otherwise.
- *
- * @group API: Functions
*/
export const deepEquals = (first: T, second: T): boolean => {
- const compare = (a: any, b: any): boolean => {
+ const compare = (a: unknown, b: unknown): boolean => {
// Return true if they are the same object
if (a === b) return true;
// and false if they don't have the same type
@@ -80,7 +81,7 @@ export const deepEquals = (first: T, second: T): boolean => {
if (typeof a === 'object' && typeof b === 'object') {
// If they belong to different classes, then they are not equal,
// one of them might not have a class, so consider that case too.
- if (a.constructor && b.constructor && a.constructor !== b.constructor) return false;
+ if (a?.constructor && b?.constructor && a.constructor !== b.constructor) return false;
// Use array comparison if both are arrays
if (Array.isArray(a) && Array.isArray(b)) return arrayEquals(a, b, compare);
// If both are Sets
@@ -108,8 +109,8 @@ export const deepEquals = (first: T, second: T): boolean => {
* Answer if two numbers are equal. Two numbers are equal
* if they happen to be the same number, or, if both are NaN.
*
- * @param a The first number
- * @param b The second number
+ * @param a - The first number
+ * @param b - The second number
*
* @returns true when both numbers are the same, or both are NaN.
*
@@ -128,13 +129,12 @@ const numberEquals = (a: number, b: number): boolean => {
* the {@link innerComparer} is used. The expected value for {@link innerComparer}
* is the recursive comparer function in deepEquals.
*
- * @param a The first array
- * @param b The second array
- * @param innerComparer The function for testing if two inner elements are equal
+ * @param aArr - The first array
+ * @param bArr - The second array
+ * @param innerComparer - The function for testing if two inner elements are equal
*
* @returns `true` if both arrays are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const arrayEquals = (aArr: T[], bArr: T[], innerComparer: (a: T, b: T) => boolean): boolean => {
@@ -158,13 +158,12 @@ const arrayEquals = (aArr: T[], bArr: T[], innerComparer: (a: T, b: T) => boo
* are equal the {@link innerComparer} is used. The expected value for {@link innerComparer}
* is the recursive comparer function in deepEquals.
*
- * @param a The first object
- * @param b The second object
- * @param innerComparer The function for testing if two inner elements are equal
+ * @param objA - The first object
+ * @param objB - The second object
+ * @param innerComparer - The function for testing if two inner elements are equal
*
* @returns `true` if both object are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const objectEquals = (objA: T, objB: T, innerComparer: (a: T, b: T) => boolean): boolean => {
@@ -178,11 +177,12 @@ const objectEquals = (objA: T, objB: T, innerComparer: (a: T, b: T) => boolea
if (aKeys[i] !== bKeys[i]) return false;
}
// If they do, perform a more expensive deep equal test in all values
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (let i = 0; i < aKeys.length; i++) {
- const aValue: any = (objA as any)[aKeys[i]];
- const bValue: any = (objB as any)[aKeys[i]];
- if (!innerComparer(aValue, bValue)) return false;
+ const aValue: unknown = objA[aKeys[i]];
+ const bValue: unknown = objB[aKeys[i]];
+ if (!innerComparer(aValue as T, bValue as T)) return false;
}
// They must be equal when this is reached
return true;
@@ -193,12 +193,11 @@ const objectEquals = (objA: T, objB: T, innerComparer: (a: T, b: T) => boolea
* have the exact same number of elements, and they have the same
* elements.
*
- * @param a The first object
- * @param b The second object
+ * @param a - The first object
+ * @param b - The second object
*
* @returns `true` if both object are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const setEquals = (a: Set, b: Set): boolean => {
@@ -206,7 +205,7 @@ const setEquals = (a: Set, b: Set): boolean => {
const aIterator = a.entries();
let aNext = aIterator.next();
while (aNext && !aNext.done) {
- if (!b.has(aNext.value[1])) return false;
+ if (!b.has((aNext.value as [T, T])[1])) return false;
aNext = aIterator.next();
}
return true;
@@ -219,13 +218,12 @@ const setEquals = (a: Set, b: Set): boolean => {
* are equal the {@link innerComparer} is used. The expected value for {@link innerComparer}
* is the recursive comparer function in deepEquals.
*
- * @param a The first map
- * @param b The second map
- * @param innerComparer The function for testing if two inner elements are equal
+ * @param a - The first map
+ * @param b - The second map
+ * @param innerComparer - The function for testing if two inner elements are equal
*
* @returns `true` if both Maps are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const mapEquals = (a: Map, b: Map, innerComparer: (a: V, b: V) => boolean): boolean => {
@@ -234,8 +232,8 @@ const mapEquals = (a: Map, b: Map, innerComparer: (a: V, b: V)
let aNext = aEntries.next();
while (!aNext.done) {
// Should have a key with same name or value
- if (!b.has(aNext.value[0])) return false;
- if (!innerComparer(aNext.value[1], b.get(aNext.value[0]) as V)) return false;
+ if (!b.has((aNext.value as [K, V])[0])) return false;
+ if (!innerComparer((aNext.value as [K, V])[1], asDefined(b.get((aNext.value as [K, V])[0])))) return false;
aNext = aEntries.next();
}
return true;
@@ -245,8 +243,8 @@ const mapEquals = (a: Map, b: Map, innerComparer: (a: V, b: V)
* Answer if two Errors are equal. Two Errors are equal when they both
* have the exact name and message.
*
- * @param a The first Error
- * @param b The second Error
+ * @param a - The first Error
+ * @param b - The second Error
*
* @returns `true` if both Errors are equal, `false` otherwise.
*
@@ -259,12 +257,11 @@ const errorEquals = (a: Error, b: Error): boolean => a.name === b.name && a.mess
* Answer if two RegExps are equal. Two RegExps are equal when they both
* have the exact source and flags.
*
- * @param a The first RegExp
- * @param b The second RegExp
+ * @param a - The first RegExp
+ * @param b - The second RegExp
*
* @returns `true` if both RegExp are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const regexpEquals = (a: RegExp, b: RegExp): boolean => a.source === b.source && a.flags === b.flags;
@@ -273,12 +270,11 @@ const regexpEquals = (a: RegExp, b: RegExp): boolean => a.source === b.source &&
* Answer if two Dates are equal. Two Date are equal when they both
* have the exact time.
*
- * @param a The first Date
- * @param b The second Date
+ * @param a - The first Date
+ * @param b - The second Date
*
* @returns `true` if both Date are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const dateEquals = (a: Date, b: Date): boolean => a.getTime() === b.getTime();
@@ -287,12 +283,11 @@ const dateEquals = (a: Date, b: Date): boolean => a.getTime() === b.getTime();
* Answer if two Buffers are equal. Two Buffers are equal when they both
* have the exact element at each position.
*
- * @param a The first Buffer
- * @param b The second Buffer
+ * @param a - The first Buffer
+ * @param b - The second Buffer
*
* @returns `true` if both Buffers are equal, `false` otherwise.
*
- * @group Internal: Function
* @internal
*/
const bufferEquals = (a: Buffer, b: Buffer): boolean => {
diff --git a/src/Functions/Querying/index.ts b/src/Functions/Querying/index.ts
new file mode 100644
index 0000000..0c5e771
--- /dev/null
+++ b/src/Functions/Querying/index.ts
@@ -0,0 +1,22 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * This module provides different functions that allows you to query about the shape
+ * or type of an object.
+ *
+ * @module Functions/Querying
+ * @author Alan Rodas Bonjour
+ */
+export * from './deepEquals';
+export * from './isBuffer';
diff --git a/src/Functions/Querying/isBuffer.ts b/src/Functions/Querying/isBuffer.ts
new file mode 100644
index 0000000..bcfda5a
--- /dev/null
+++ b/src/Functions/Querying/isBuffer.ts
@@ -0,0 +1,33 @@
+/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint-disable @typescript-eslint/no-unsafe-member-access */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unsafe-return */
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Functions/Querying
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * Answer if an element is a Buffer.
+ *
+ * @param obj - The element to test if it's a buffer
+ *
+ * @returns `true` if the element is a Buffer, `false` otherwise.
+ */
+export const isBuffer = (obj: unknown): obj is Buffer =>
+ obj?.constructor &&
+ typeof (obj.constructor as any).isBuffer === 'function' &&
+ (obj.constructor as any).isBuffer(obj);
diff --git a/src/Functions/index.ts b/src/Functions/index.ts
index 0f3dbfd..fe72b8f 100644
--- a/src/Functions/index.ts
+++ b/src/Functions/index.ts
@@ -10,6 +10,7 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
* This module provides different functions that provide common functionality
* that may be reused in different packages.
@@ -17,11 +18,11 @@
* for better accessibility in all packages.
*
*
- * @module API.Functions
+ * @module Functions
* @author Alan Rodas Bonjour
*/
-export * from './deepEquals';
-export * from './flatten';
-export * from './matrix';
-export * from './symbolAsString';
-export * from './deepStringAssign';
+export * from './Conversion';
+export * from './ExecutionManagement';
+export * from './Querying';
+export * from './ObjectManipulation';
+export * from './noop';
diff --git a/src/Functions/isBuffer.ts b/src/Functions/noop.ts
similarity index 64%
rename from src/Functions/isBuffer.ts
rename to src/Functions/noop.ts
index e9cf250..dcda95f 100644
--- a/src/Functions/isBuffer.ts
+++ b/src/Functions/noop.ts
@@ -11,17 +11,19 @@
* *****************************************************************************
*/
/**
- * @module API.Functions
+ * @module Functions
* @author Alan Rodas Bonjour
*/
+
/**
- * Answer if an element is a Buffer.
+ * A function that does nothing.
*
- * @param obj The element to test if it's a buffer
- *
- * @returns `true` if the element is a Buffer, `false` otherwise.
- *
- * @group API: Function
+ * @remarks
+ * This is useful as a placeholder in many scenarios, specially
+ * in react applications, where a function must be given to callbacks
+ * and events, even though the real function may not still be ready in
+ * the app yet.
*/
-export const isBuffer = (obj: any): boolean =>
- obj && obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj);
+export const noop = (): void => {
+ /* Intentionally empty */
+};
diff --git a/src/GobstonesLang/Board.ts b/src/GobstonesLang/Board.ts
deleted file mode 100644
index 3f0cc32..0000000
--- a/src/GobstonesLang/Board.ts
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-import { BoardDefinition, CellDataDefinition, CellLocation } from './BoardDefinition';
-import {
- InvalidBoardDescription,
- InvalidCellReading,
- InvalidSizeChange,
- InvalidSizeChangeAttempt,
- LocationChangeActionAttempt,
- LocationFallsOutsideBoard
-} from './BoardErrors';
-import { Cell } from './Cell';
-import { Color } from './Color';
-import { Direction } from './Direction';
-
-import { EventEmitter } from '../Events/EventEmitter';
-import { and, expect, or } from '../Expectations';
-import { matrix } from '../Functions/matrix';
-
-/**
- * This object contains the default values for a {@link Board}.
- * When a specific value is not given, the defaults are used.
- *
- * @group Internal: Default Values
- * @internal
- */
-const Defaults = {
- width: 4,
- height: 4,
- head: [0, 0] as CellLocation
-};
-
-/**
- * This type represents the function that acts as a callback of
- * the {@link Board.onSizeChanged} event. Such an event is thrown by
- * an instance of a board whenever an operation is performed such
- * that the original size of the board is altered.
- *
- * This function receives 5 arguments:
- * * the size of the board (encapsulated in an object containing both
- * width and height attributes), that being, the new size that the
- * board has been set to.
- * * the new head location. This might be the same location that the head was
- * previously in, but it might change if the size was reduced and the cell
- * where the head was no longer exists.
- * * A boolean, that is `true`if the board change was performed origin first.
- * That is, the size was reduced from the West or the South, or expanded
- * into those directions.
- * * The previous size the board had, in an encapsulated object with `width` and `height`.
- * * The previous cell that the head was at. Might be the same as the current one.
- *
- * @see {@link Board.onSizeChanged} for more information.
- *
- * @group API: Events
- * @event
- */
-export type OnBoardSizeChangedCallback = (
- newSize: { width: number; height: number },
- newHeadLocation: CellLocation,
- fromOriginCell: boolean,
- previousSize: { width: number; height: number },
- previousHeadLocation: CellLocation
-) => void;
-
-/**
- * This type represents the function that acts as a callback of
- * the {@link Board.onHeadMoved} event. Such an event is thrown by
- * an instance of a board whenever an operation is performed such
- * that the current head location is altered.
- *
- * This function receives two arguments.
- * * The current head location.
- * * The previous head location.
- *
- * @see {@link Board.onHeadMoved} for more information.
- *
- * @event
- * @group API: Events
- */
-export type OnBoardHeadMovedCallback = (currentLocation: CellLocation, previousLocation: CellLocation) => void;
-
-/**
- * This interface contains the signature of the
- * events that a Board can throw.
- *
- * @group Internal: Events
- * @internal
- */
-export interface BoardEvents {
- [Board.onSizeChanged]: OnBoardSizeChangedCallback;
- [Board.onHeadMoved]: OnBoardHeadMovedCallback;
-}
-
-/**
- * This class models a Gobstones Board with all it's associated behavior.
- * Note that an instance of this class implements {@link BoardDefinition},
- * so it can be used as a valid description of a board in the [Gobstones
- * Interpreter](http://github.com/gobstones/gobstones-interpreter) and is
- * returned by [The Gobstones GBB Parser](http://github.com/gobstones/gobstones-gbb-parser).
- * All newer developments are expected to use this class instead of a particular ad-hoc
- * representation for a board.
- *
- * Note that this class provides a {@link board} attribute, that used to be the standard
- * way to access the cells of the boards, but this new class is intended to be used
- * as an ADT. So it's expected that you use the provided functions for accessing
- * cells, columns ands rows, instead of using the board attribute. Be aware of
- * deprecation warnings.
- *
- * The class provides a set of method for accessing and querying the properties
- * of the board and cell contents, modify the head location, the size and the
- * cell contents. This class works in conjunction with the {@link Cell} class. Note
- * that internal representation of a board might change, so do not rely on
- * representation, and abstract away of it as much as possible.
- *
- * @group API: Main
- */
-export class Board extends EventEmitter implements BoardDefinition {
- /**
- * This event is thrown whenever an action that alters the position of the head
- * is performed. Listeners of this action are expected to conform to
- * {@link OnBoardHeadMovedCallback}.
- *
- * The actions that trigger this callback include:
- * * Setting the {@link head} attribute of an instance.
- * * Calling {@link moveHeadTo} on an instance with any direction.
- * * Calling {@link moveHeadToEdgeAt} on an instance with any direction.
- *
- * Note however that there is a particular case where the head moves, but this
- * event is not triggered. Such particular case happens when the board is resized
- * is such a way that, the location where the head was at, no longer exists as
- * a valid cell of the board, thus, the head is assigned to a new location.
- * If you wish to consider such a case, consider also listening to {@link onSizeChanged}.
- * @event
- */
- public static readonly onHeadMoved: unique symbol = Symbol('onHeadMoved');
-
- /**
- * This event is thrown whenever an action that alters the size of the board
- * is performed. Listeners of this action are expected to conform to
- * {@link OnBoardSizeChangedCallback}
- *
- * The actions that trigger this callback include:
- * * Setting the {@link width} attribute of an instance.
- * * Setting the {@link height} attribute of an instance.
- * * Calling {@link changeSizeTo} on an instance with any values
- * (even with the same width and height as the actual size)
- * * Calling {@link addColumn} on an instance.
- * * Calling {@link addColumns} on an instance.
- * * Calling {@link removeColumn} on an instance.
- * * Calling {@link removeColumns} on an instance.
- * * Calling {@link addRow} on an instance.
- * * Calling {@link addRows} on an instance.
- * * Calling {@link removeRow} on an instance.
- * * Calling {@link removeRows} on an instance.
- * @event
- */
- public static readonly onSizeChanged: unique symbol = Symbol('onSizeChanged');
-
- /**
- * The internal representation of the width of the board.
- *
- * @see {@link width}
- */
- private boardWidth: number;
-
- /**
- * The internal representation of the height of the board
- *
- * @see {@link height}
- */
- private boardHeight: number;
-
- /**
- * The internal representation of head's X location, where the
- * position should always comply to:
- * ```typescript
- * 0 <= x < width
- * ```
- *
- * @see {@link head}
- */
- private headXLocation: number;
-
- /**
- * The internal representation of head's Y location, where the
- * position should comply to:
- * ```typescript
- * 0 <= y < height
- * ```
- *
- * @see {@link head}
- */
- private headYLocation: number;
-
- /**
- * The internal representation of the cells of the board.
- * Currently this is represented as an array of {@link boardWidth}
- * elements, where each element is itself an array of {@link boardHeight}
- * elements, where each of them is a {@link Cell}.
- *
- * @see {@link board}
- */
- private boardData: Cell[][];
-
- /**
- * Create a new instance of a board. You may choose between a default empty board
- * with width=4, height=4 and the head at [0,0]. Alternatively pass a custom `width`
- * and `height`, and an optional specific location for the `head`.
- *
- * Optionally and additionally, when creating a custom sized board, you can
- * initialize some of the cells with some specific stones amount, by providing
- * an array of {@link CellDataDefinition}, specifying the stones of each color for a
- * given position of the board (There's no specific behavior if two elements
- * for the same location is given, any of them might be used,
- * so be sure to specify the stones of a specific location only once).
- *
- * @example The following example initializes a Board of 5 columns
- * by 4 rows, with the head starting in the x=2, y=3 coordinate, and
- * in which there are 10 red stones in each cell of the firs column.
- * ```
- * new Board(5, 4, [2, 3], [
- * {x: 0, y: 0, [Color.Red]: 10},
- * {x: 0, y: 1, [Color.Red]: 10},
- * {x: 0, y: 2, [Color.Red]: 10},
- * {x: 0, y: 3, [Color.Red]: 10}
- * ]);
- * ```
- *
- * Note that when passing {@link CellDataDefinition}, the usage of the
- * {@link Color} enum values as keys for specifying the stones amount is
- * preferred over the 'a', 'n', 'r', 'v' string keys. Although equivalent,
- * the actual strings of the enum may change is the future.
- *
- * @throws {@link InvalidBoardDescription} if the given width or height
- * are lower or equal than zero.
- * @throws {@link InvalidBoardDescription} if the given head location
- * has an `x` coordinate lower than zero or greater or equal
- * than the `width` or an `y` coordinate lower than zero or
- * greater or equal than the `height`.
- * @throws {@link InvalidBoardDescription} if any of the given cell
- * locations in `initialState` has a location as an `[x, y]`
- * coordinate such that `x < 0 || x >= width` or
- * `y < 0 || y >= height`.
- *
- * @param width The width of the board.
- * @param height The height of the board.
- * @param head The head location.
- * @param initialState An array of {@link CellDataDefinition} for the cells
- * that you want to specify initial stones to.
- */
- public constructor(width?: number, height?: number, head?: CellLocation, initialState?: CellDataDefinition[]) {
- super();
- this.boardWidth = width ?? Defaults.width;
- this.boardHeight = height ?? Defaults.height;
- this.headXLocation = (head ?? Defaults.head)[0];
- this.headYLocation = (head ?? Defaults.head)[1];
-
- and(
- expect(this.boardWidth).toBeGreaterThan(0),
- expect(this.boardHeight).toBeGreaterThan(0),
- expect(this.headX).toBeGreaterThanOrEqual(0).toBeLowerThan(this.boardWidth),
- expect(this.headY).toBeGreaterThanOrEqual(0).toBeLowerThan(this.boardHeight)
- ).orThrow(new InvalidBoardDescription(this.boardHeight, this.boardWidth, [this.headX, this.headY]));
-
- const cells: Map = new Map(
- (initialState ?? []).map((cellDef) => {
- and(
- expect(cellDef.x).toBeGreaterThanOrEqual(0).toBeLowerThan(this.boardWidth),
- expect(cellDef.y).toBeGreaterThanOrEqual(0).toBeLowerThan(this.boardHeight)
- );
- return [`${cellDef.x}-${cellDef.y}`, cellDef];
- })
- );
- this.boardData = matrix(
- this.boardWidth,
- this.boardHeight,
- (i, j) => new Cell(this, cells.get(`${i}-${j}`) ?? { x: i, y: j })
- );
- }
-
- /* ************* Accessors ************** */
-
- /**
- * Returns true for any board.
- * Useful to test if an untyped object is a board.
- */
- public get isBoard(): boolean {
- return true;
- }
-
- /**
- * The board format. Always: GBB/1.0 as it's derived from the GBB format.
- *
- * @deprecated
- * In the future, the version information would not be available on a board,
- * as it's derived from the GBB format, but the way in which this instance
- * is produces might come from any other location or format other than GBB,
- * and is not at all relevant to the user.
- *
- * @see {@link BoardDefinition.format | BoardDefinition.format}
- */
- public get format(): string {
- return 'GBB/1.0';
- }
-
- /**
- * Get the width of this board.
- *
- * @see {@link BoardDefinition.width | BoardDefinition.width}
- *
- * @returns The width of the board, always greater than 0.
- */
- public get width(): number {
- return this.boardWidth;
- }
-
- /**
- * Sets the width of this board.
- *
- * @see {@link BoardDefinition.width | BoardDefinition.width}
- *
- * @throws {@link InvalidSizeChange} with the attempt as `Resize`
- * if attempting to set the attribute and the given value is
- * lower or equal to zero.
- */
- public set width(value: number) {
- this.innerChangeSize(value, this.boardHeight, false, 'Resize');
- }
-
- /**
- * Get the height of this board.
- *
- * @see {@link BoardDefinition.height | BoardDefinition.height}
- *
- * @returns The height of the board, always greater than 0.
- */
- public get height(): number {
- return this.boardHeight;
- }
-
- /**
- * Get or sets the height of this board.
- *
- * @see {@link BoardDefinition.height | BoardDefinition.height}
- *
- * @throws {@link InvalidSizeChange} with the attempt as `Resize`
- * if attempting to set the attribute and the given value is
- * lower or equal to zero.
- */
- public set height(value: number) {
- this.innerChangeSize(this.boardWidth, value, false, 'Resize');
- }
-
- /**
- * Get the head location of this board as an `[x, y]` coordinate.
- *
- * @see {@link BoardDefinition.head | BoardDefinition.head}
- *
- * @returns The head location as a two element array `[x, y]`, that satisfies
- * `0 <= x < width && 0 <= y < height`
- */
- public get head(): CellLocation {
- return [this.headX, this.headY] as CellLocation;
- }
-
- /**
- * Sets the head location of this board as an `[x, y]` coordinate.
- *
- * @see {@link BoardDefinition.head | BoardDefinition.head}
- *
- * @throws {@link LocationFallsOutsideBoard} with the attempt as `SetLocation`
- * if attempting to set the attribute and the given cell location as
- * `[x, y]` has `x < 0 || x > width` or `y < 0 || y > width`.
- */
- public set head(value: CellLocation) {
- this.innerSetHeadLocation(value, 'SetLocation');
- }
-
- /**
- * The head's X coordinate of this board.
- *
- * @returns The board X's coordinate, which satisfies `0 <= x < width`
- *
- * @see {@link BoardDefinition.head | BoardDefinition.head}
- */
- public get headX(): number {
- return this.headXLocation;
- }
-
- /**
- * The head's Y coordinate of this board
- *
- * @returns The board X's coordinate, which satisfies `0 <= y < height`
- *
- * @see {@link BoardDefinition.head | BoardDefinition.head}
- */
- public get headY(): number {
- return this.headYLocation;
- }
-
- /**
- * Obtain the cells of the board as an array of `width` elements, each
- * of which is an array of `height` elements, each of which is a {@link Cell},
- * or in another sense, a {@link API.Functions!matrix} of {@link Cell | Cells}.
- *
- * This is retain only for compatibility reasons.
- *
- * @see {@link BoardDefinition.board | BoardDefinition.board}
- *
- * @deprecated
- * Note that this method of accessing the board is deprecated and should not
- * be used. If you need a cell matrix, in such a way that the first
- * array represents the columns, and each array inside the cells of such a column,
- * the method {@link getColumns} should be used. Instead if you are attempting to
- * access a specific cell as `board[x][y]`, use the {@link getCell} method instead as
- * `getCell(x, y)`.
- *
- * @returns A matrix of cells.
- */
- /* istanbul ignore next */
- public get board(): Cell[][] {
- return this.boardData;
- }
-
- /* ************* Cloning ************** */
-
- /**
- * Clone this board, returning a new one with the same characteristics.
- *
- * @returns A new Board.
- */
- public clone(): Board {
- const cellStates = this.foldCells((cells, cell) => {
- cells.push({
- x: cell.x,
- y: cell.y,
- [Color.BLUE]: cell.getStonesOf(Color.Blue),
- [Color.BLACK]: cell.getStonesOf(Color.Black),
- [Color.RED]: cell.getStonesOf(Color.Red),
- [Color.GREEN]: cell.getStonesOf(Color.Green)
- });
- return cells;
- }, []);
- return new Board(this.width, this.height, this.head, cellStates);
- }
-
- /* ************* Querying ************** */
-
- /**
- * Get a {@link Cell} for the given location, or the cell for the
- * head location if none is given.
- *
- * @throws {@link LocationFallsOutsideBoard} with the attempt as `ReadCell`
- * if the given cell location as `[x, y]` has `x < 0 || x > width`
- * or `y < 0 || y > width`.
- *
- * @param location The location from which to obtain the cell
- * data from, or undefined if the data is ought to be taken
- * from the cell at the head location.
- *
- * @returns A {@link Cell} for the given location.
- */
- public getCell(x?: number, y?: number): Cell {
- return this.innerGetCell(x ?? this.headX, y ?? this.headY);
- }
-
- /**
- * Get an array of {@link Cell | Cells} for the specific column.
- *
- * @throws {@link LocationFallsOutsideBoard} with the attempt as `ReadColumn`
- * if the given column number is lower than cero or greater than of equal
- * than the {@link width}.
- *
- * @param columnNumber The column number to obtain the cell from.
- *
- * @returns A {@link Cell} array for the given column.
- */
- public getColumn(columnNumber: number): Cell[] {
- return this.innerGetColumn(columnNumber);
- }
-
- /**
- * Get an array of {@link Cell | Cells} for the specific row.
- *
- * Note that with the current implementation this takes more
- * time than accessing by column, but this might change in future
- * implementations.
- *
- * @throws {@link LocationFallsOutsideBoard} with the attempt as `ReadRow`
- * if the given column number is lower than cero or greater of equal
- * than the {@link height}.
- *
- * @param rowNumber The row number to obtain the cell from.
- *
- * @returns A {@link Cell} array for the given row.
- */
- public getRow(rowNumber: number): Cell[] {
- return this.innerGetRow(rowNumber);
- }
-
- /**
- * Get an array of arrays of {@link Cell | Cells} for the board, that can be
- * iterated by column, that is, an array of columns.
- *
- * @returns A {@link Cell} array of arrays where each element is a column,
- * and each column is a list of cells.
- */
- public getColumns(): Cell[][] {
- return this.innerGetColumns();
- }
-
- /**
- * Get an array of arrays of {@link Cell | Cells} for the board, that can be
- * iterated by rows, that is, an array of rows.
- *
- * Note that with the current implementation this takes more
- * time than accessing by column, but this might change in future
- * implementations.
- *
- * @returns A {@link Cell} array of arrays where each element is a row,
- * and each row is a list of cells.
- */
- public getRows(): Cell[][] {
- const rows: Cell[][] = [];
- for (let row = 0; row < this.height; row++) {
- rows.push(this.getRow(row));
- }
- return rows;
- }
-
- /**
- * Fold a value over all the cells of a board.
- * The order of the cells should not be assumed, as any order might be used.
- *
- * Note that with the current implementation, the cells are iterated by column
- * starting from 0,0 to the one in the North-East corner.
- *
- * @param f A function to apply to each cells. The function expect to receive
- * the current accumulated value at the moment, the currently iterated cell,
- * and the row and column position for such a cell and returning a value of
- * the same type as the accumulated value.
- * @param initialValue The initial value to fold against.
- */
- public foldCells(f: (previousValue: A, cell: Cell, row: number, column: number) => A, initialValue: A): A {
- let currentValue = initialValue;
- for (let c = 0; c < this.boardData.length; c++) {
- const column = this.boardData[c];
- for (let r = 0; r < column.length; r++) {
- const cell = column[r];
- currentValue = f(currentValue, cell, r, c);
- }
- }
- return currentValue;
- }
-
- /**
- * Map all the cells of the board, generating a matrix of values.
- * The order of the cells should not be assumed, as any order might be used.
- *
- * Note that with the current implementation, the cells are iterated by column
- * starting from 0,0 to the one in the North-East corner.
- *
- * @param f A function to apply to each cells. The function expect to receive
- * the currently iterated cell, and the row and column position for such a cell,
- * and returning any value.
- */
- public mapCells(f: (cell: Cell, row: number, column: number) => A): A[][] {
- return this.foldCells(
- (previousMatrix, cell, row, column) => {
- previousMatrix[column][row] = f(cell, row, column);
- return previousMatrix;
- },
- matrix(this.width, this.height)
- );
- }
-
- /**
- * Filter all the cells of the board, generating an array of Cells.
- * The order of the cells should not be assumed, as any order might be used.
- *
- * Note that with the current implementation, the cells are iterated by column
- * starting from 0,0 to the one in the North-East corner.
- *
- * @param f A function to apply to each cells. The function expect to receive
- * the currently iterated cell, and the row and column position for such a cell,
- * that returns a boolean, returning `true` if the cell is ought to be in the result,
- * and `false`otherwise.
- */
- public filterCells(f: (cell: Cell, row: number, column: number) => boolean): Cell[] {
- return this.foldCells((previousList: Cell[], cell: Cell, row: number, column: number) => {
- if (f(cell, row, column)) {
- previousList.push(cell);
- }
- return previousList;
- }, []);
- }
-
- /**
- * Execute a function over each of the cells of the board.
- * The order of the cells should not be assumed, as any order might be used.
- *
- * Note that with the current implementation, the cells are iterated by column
- * starting from 0,0 to the one in the North-East corner.
- *
- * @param f A function to apply to each cells. The function expect to receive
- * the currently iterated cell, and the row and column position for such a cell.
- */
- public foreachCells(f: (cell: Cell, row: number, column: number) => void): void {
- this.foldCells((_, cell, row, column) => {
- f(cell, row, column);
- return undefined;
- }, undefined);
- }
-
- /* ************* Clean Board ************** */
-
- /**
- * Clean the board contents, leaving all cells empty.
- */
- public clean(): void {
- this.foreachCells((cell) => cell.empty());
- }
-
- /* ************* Modifying Head ************** */
-
- /**
- * Change the head coordinate, by moving the head to the adjacent cell
- * in the given direction. Thus given a direction `dir`, and considering
- * that the head is at `[x, y]` coordinate, the new head location is calculated as:
- * * for `dir === Direction.North` the new head is at `[x, y+1]`.
- * * for `dir === Direction.South` the new head is at `[x, y-1]`.
- * * for `dir === Direction.East` the new head is at `[x+1, y]`.
- * * for `dir === Direction.West` the new head is at `[x-1, y]`.
- *
- * @throws {@link LocationFallsOutsideBoard} with the attempt as `Move`
- * if moving the head to the given direction makes it fall
- * outside the board.
- *
- * @param dir The direction in which to move the head to.
- */
- public moveHeadTo(dir: Direction): void {
- const [deltaX, deltaY] = this.innerGetDeltaByDirection(dir, 1);
- this.innerSetHeadLocation([this.headX + deltaX, this.headY + deltaY], 'Move');
- }
-
- /**
- * Change the head coordinate location to the coordinate at the edge at
- * given direction. Thus given a direction `dir`, and considering that
- * the head is at `[x, y]` coordinate, the new head coordinate is
- * calculated as:
- * * for `dir === Direction.North` the new head is at `[x, height-1]`.
- * * for `dir === Direction.South` the new head is at `[x, 0]`.
- * * for `dir === Direction.East` the new head is at `[width-1, y]`.
- * * for `dir === Direction.West` the new head is at `[0, y]`.
- *
- * @param dir The direction in which to move the head to.
- */
- public moveHeadToEdgeAt(dir: Direction): void {
- const [deltaX, deltaY] = this.innerGetDeltaByDirection(dir);
- this.innerSetHeadLocation([this.headX + deltaX, this.headY + deltaY], 'MoveToEdge');
- }
-
- /* ************* Modifying Size ************** */
-
- /**
- * Change the size of the board to the given width and height.
- * If `fromOriginCorner` is `true`, and cells are being added, they are
- * added to the West and/or South (depending on the new size value), if
- * `false` they are added to the East and/or North. The same happens when removing,
- * that is, when the new size is lower that the current one, for any of width or
- * height.
- * Note that changing the size of the board by setting the {@link width} or {@link height}
- * attributes act as using this same method with `fromOriginCorner` set to `false`.
- * Thus, this methods provides a more generic way of modifying the size, allowing to
- * add columns or rows at the beginning of the board instead of the end.
- *
- * Note that if the given size is smaller than the current size, the location
- * of the head is adjusted in any case that the location falls outside the board
- * given the new size.
- *
- * @throws {@link InvalidBoardDescription} if any of the given
- * `width` or `height` are lower than or equal to zero.
- *
- * @param width The new width of the board.
- * @param height The new height of the board.
- * @param fromOriginCorner Wether to change the size considering the
- * change being performed from the origin cell instead of the North-East corner.
- */
- public changeSizeTo(width: number, height: number, fromOriginCorner: boolean = false): void {
- this.innerChangeSize(width, height, fromOriginCorner, 'Resize');
- }
-
- /**
- * Add a new column to the board at the given direction.
- * Note that this is equivalent of adding one column
- * by calling {@link addColumns} with argument 1 for the same direction
- * as given.
- *
- * If no direction is given, the column is added to the East.
- *
- * @param dir The direction where to add the new column.
- */
- public addColumn(dir: Direction = Direction.East): void {
- or(expect(dir).toBe(Direction.East), expect(dir).toBe(Direction.West)).orThrow(
- new TypeError('The direction to addColumn should be East or West')
- );
- this.addColumns(1, dir);
- }
-
- /**
- * Add a given amount of new columns to the board at the given direction.
- * Note that, this is equivalent as increasing the size of the board with
- * {@link changeSizeTo} where the new width corresponds to the current width
- * plus the number of new columns. If the given direction is `Direction.East`,
- * then the new columns are added at the beginning of the board (that is,
- * using `changeSizeTo` with `fromOriginCell` as `true`).
- *
- * If no direction is given, the columns are added to the East.
- *
- * @param amount The number of columns to add.
- * @param dir The direction where to add the new column.
- */
- public addColumns(amount: number, dir: Direction = Direction.East): void {
- or(expect(dir).toBe(Direction.East), expect(dir).toBe(Direction.West)).orThrow(
- new TypeError('The direction to addColumns should be East or West')
- );
- this.innerChangeSize(this.width + amount, this.height, dir === Direction.West, 'AddColumns');
- }
-
- /**
- * Remove a column to the board at the given direction.
- * Note that this is equivalent to removing one column
- * by calling {@link removeColumns} with argument 1 for the same direction
- * as given.
- *
- * If no direction is given, the column is removed from the East.
- *
- * @param dir The direction where to remove the new column.
- */
- public removeColumn(dir: Direction = Direction.East): void {
- or(expect(dir).toBe(Direction.East), expect(dir).toBe(Direction.West)).orThrow(
- new TypeError('The direction to removeColumn should be East or West')
- );
- this.removeColumns(1, dir);
- }
-
- /**
- * Remove given number of columns from the board at the given direction.
- * Note that, this is equivalent as decreasing the size of the board with
- * {@link changeSizeTo} where the new width corresponds to the current width
- * minus the number of columns to remove. If the given direction is
- * `Direction.East`, then the new columns are removed from the beginning of
- * the board (that is, using `changeSizeTo` with `fromOriginCell` as `true`).
- *
- * If no direction is given, the columns are removed from the East.
- *
- * @param amount The amount of columns to remove.
- * @param dir The direction where to remove the new column.
- */
- public removeColumns(amount: number, dir: Direction = Direction.East): void {
- or(expect(dir).toBe(Direction.East), expect(dir).toBe(Direction.West)).orThrow(
- new TypeError('The direction to removeColumns should be East or West')
- );
- this.innerChangeSize(this.width - amount, this.height, dir === Direction.West, 'RemoveColumn');
- }
-
- /**
- * Add a new row to the board at the given direction.
- * Note that this is equivalent of adding one row
- * by calling {@link addRows} with argument 1 for the same direction
- * as given.
- *
- * If no direction is given, the row is added to the North.
- *
- * @param dir The direction where to add the new column.
- */
- public addRow(dir: Direction = Direction.North): void {
- or(expect(dir).toBe(Direction.North), expect(dir).toBe(Direction.South)).orThrow(
- new TypeError('The direction to addRow should be North or South')
- );
- this.addRows(1, dir);
- }
-
- /**
- * Add a given amount of new rows to the board at the given direction.
- * Note that, this is equivalent as increasing the size of the board with
- * {@link changeSizeTo} where the new height corresponds to the current height
- * plus the number of new rows. If the given direction is `Direction.South`,
- * then the new columns are added at the beginning of the board (that is,
- * using `changeSizeTo` with `fromOriginCell` as `true`).
- *
- * If no direction is given, the rows are added to the North.
- *
- * @param amount The number of rows to add.
- * @param dir The direction where to add the new row.
- */
- public addRows(amount: number, dir: Direction = Direction.North): void {
- or(expect(dir).toBe(Direction.North), expect(dir).toBe(Direction.South)).orThrow(
- new TypeError('The direction to addRows should be North or South')
- );
- this.innerChangeSize(this.width, this.height + amount, dir === Direction.South, 'AddRows');
- }
-
- /**
- * Remove a row to the board at the given direction.
- * Note that this is equivalent to removing one row
- * by calling {@link removeRows} with argument 1 for the same direction
- * as given.
- *
- * If no direction is given, the row is removed from the North.
- *
- * @param dir The direction where to remove the new row.
- */
- public removeRow(dir: Direction = Direction.North): void {
- or(expect(dir).toBe(Direction.North), expect(dir).toBe(Direction.South)).orThrow(
- new TypeError('The direction to removeRow should be North or South')
- );
- this.removeRows(1, dir);
- }
-
- /**
- * Remove given number of rows from the board at the given direction.
- * Note that, this is equivalent as decreasing the size of the board with
- * {@link changeSizeTo} where the new height corresponds to the current height
- * minus the number of rows to remove. If the given direction is
- * `Direction.South`, then the new columns are removed from the beginning of
- * the board (that is, using `changeSizeTo` with `fromOriginCell` as `true`).
- *
- * If no direction is given, the rows are removed from the North.
- *
- * @param amount The amount of rows to remove.
- * @param dir The direction where to remove the new row.
- */
- public removeRows(amount: number, dir: Direction = Direction.North): void {
- or(expect(dir).toBe(Direction.North), expect(dir).toBe(Direction.South)).orThrow(
- new TypeError('The direction to removeRows should be North or South')
- );
- this.innerChangeSize(this.width, this.height - amount, dir === Direction.South, 'RemoveRow');
- }
-
- /**
- * Retrieve a string representation of the board as a pretty print.
- * Useful for debugging purposes mostly.
- *
- * Note that this only pretty prints boards where
- * there are less than ten stones in each cell. Other board
- * may print incorrectly.
- */
- /* istanbul ignore next */
- public toString(): string {
- let board = '';
- const cellString = (cell: Cell, line: number): string => {
- const sep = cell.isHeadLocation() ? '|' : '¦';
- return line === 0
- ? `${sep} ${cell.getStonesOf(Color.Blue)} B ${cell.getStonesOf(Color.Black)} K ${sep}`
- : `${sep} ${cell.getStonesOf(Color.Red)} R ${cell.getStonesOf(Color.Green)} G ${sep}`;
- };
-
- for (let r = this.height - 1; r >= 0; r--) {
- board += ' ';
- for (let c = 0; c < this.width; c++) {
- board +=
- this.boardData[c][r].isHeadLocation() || this.boardData[c][r + 1]?.isHeadLocation()
- ? '-----------'
- : '- - - - - -';
- }
- board += '\n ';
- for (let c = 0; c < this.width; c++) {
- board += cellString(this.boardData[c][r], 0);
- }
- board += `\n${r} `;
- for (let c = 0; c < this.width; c++) {
- board += cellString(this.boardData[c][r], 1);
- }
- board += '\n';
- }
- board += ' ';
- for (let c = 0; c < this.width; c++) {
- board += this.boardData[c][0].isHeadLocation() ? '-----------' : '- - - - - -';
- }
- board += '\n ';
- for (let c = 0; c < this.width; c++) {
- board += ` ${c} `;
- }
- return board;
- }
-
- /* ************* Private ************** */
-
- /**
- * Retrieve all the columns from the board. This is another way of
- * saying, retrieve all the cells as a 2 dimensional matrix, where
- * the outer element corresponds to a column, and the inner one to
- * the cells in that column.
- *
- * @returns An array of arrays of cells with the board information
- */
- private innerGetColumns(): Cell[][] {
- return this.boardData;
- }
-
- /**
- * Retrieve all the cells in a given column.
- *
- * @throws {@link InvalidCellReading} with the attempt as `ReadColumn`
- * if the given column number is lower than zero or greater
- * or equal to the board width.
- *
- * @returns An array of cells with the cells in the given column.
- */
- private innerGetColumn(column: number): Cell[] {
- expect(column)
- .toBeGreaterThanOrEqual(0)
- .toBeLowerThan(this.width)
- .orThrow(new InvalidCellReading('ReadColumn', [column, 0]));
- return this.boardData[column];
- }
-
- /**
- * Retrieve all the cells in a given row.
- *
- * @throws {@link InvalidCellReading} with the attempt as `ReadRow`
- * if the given row number is lower than zero or greater
- * or equal to the board height.
- *
- * @returns An array of cells with the cells in the given row.
- */
- private innerGetRow(row: number): Cell[] {
- expect(row)
- .toBeGreaterThanOrEqual(0)
- .toBeLowerThan(this.height)
- .orThrow(new InvalidCellReading('ReadRow', [0, row]));
- const rowData: Cell[] = [];
- for (let c = 0; c < this.width; c++) {
- rowData.push(this.boardData[c][row]);
- }
- return rowData;
- }
-
- /**
- * Retrieve the cells in a given location.
- *
- * @throws {@link InvalidCellReading} with the attempt as `ReadCell`
- * if the location given as `[x, y]` has `x` that is lower
- * than zero or greater or equal to the board width, or `y`
- * that is lower than zero or greater or equal to the board height.
- *
- * @returns A cell for the given location
- */
- private innerGetCell(x: number, y: number): Cell {
- expect(x)
- .toBeGreaterThanOrEqual(0)
- .toBeLowerThan(this.width)
- .orThrow(new InvalidCellReading('ReadCell', [x, y]));
- expect(y)
- .toBeGreaterThanOrEqual(0)
- .toBeLowerThan(this.height)
- .orThrow(new InvalidCellReading('ReadCell', [x, y]));
- return this.boardData[x][y];
- }
-
- /**
- * Change the head location to the specific cell location.
- *
- * @throws {@link LocationFallsOutsideBoard} with the attempt as `performedAction`
- * if the given cell location as `[x, y]` has `x < 0 || x > width`
- * or `y < 0 || y > width`.
- *
- * @param location The location to move the head to.
- */
- private innerSetHeadLocation(location: CellLocation, performedAction: LocationChangeActionAttempt): void {
- and(
- expect(location[0]).toBeGreaterThanOrEqual(0).toBeLowerThan(this.width),
- expect(location[1]).toBeGreaterThanOrEqual(0).toBeLowerThan(this.height)
- ).orThrow(new LocationFallsOutsideBoard(performedAction, location, this.head));
- const oldHeadX = this.headXLocation;
- const oldHeadY = this.headYLocation;
- this.headXLocation = location[0];
- this.headYLocation = location[1];
- this.emit(Board.onHeadMoved, [this.headXLocation, this.headYLocation], [oldHeadX, oldHeadY]);
- }
-
- /**
- * Change the size of the board to the given width and height.
- *
- * @warning Changing size is an expensive operation with the current implementation,
- * and probably with any other representation for the current API. All things
- * considered, changing the size of the Board is not an operation that is
- * performed multiple time, nor expected immediacy, so the penalties
- * in performance are acceptable.
- *
- * @throws {@link InvalidBoardDescription} if any of the given
- * `width` or `height` are lower tor equal than zero.
- *
- * @param width The new width of the board.
- * @param height The new height of the board.
- * @param fromOriginCorner Wether to change the size considering the
- * change being performed from the origin cell instead of the North-East corner.
- */
- private innerChangeSize(
- width: number,
- height: number,
- fromOriginCorner: boolean = false,
- attempt: InvalidSizeChangeAttempt
- ): void {
- and(expect(height).toBeGreaterThan(0), expect(width).toBeGreaterThan(0)).orThrow(
- new InvalidSizeChange(attempt, this.boardWidth, this.boardHeight, width, height)
- );
-
- // Gather state of change
- const oldHeight = this.boardHeight;
- const oldWidth = this.boardWidth;
- const oldHeadX = this.headXLocation;
- const oldHeadY = this.headYLocation;
-
- this.boardHeight = height;
- this.boardWidth = width;
-
- // Firstly fix columns
- if (this.boardWidth >= oldWidth) {
- // Add columns or leave as it
- for (let k = 0; k < this.boardWidth - oldWidth; k++) {
- if (fromOriginCorner) {
- this.boardData.unshift([]);
- } else {
- this.boardData.push([]);
- }
- }
- } else {
- // Remove columns
- for (let k = 0; k < oldWidth - this.boardWidth; k++) {
- if (fromOriginCorner) {
- this.boardData.shift();
- } else {
- this.boardData.pop();
- }
- }
- }
- // Then fix cells in columns
- for (let c = 0; c < this.boardWidth; c++) {
- const columnInitialLength = this.boardData[c].length;
- if (this.boardHeight >= oldHeight) {
- // Add cell or leave as it
- for (let k = 0; k < this.boardHeight - columnInitialLength; k++) {
- if (fromOriginCorner) {
- // Note that Cell location does not matter at this point, so 0,0 is OK.
- this.boardData[c].unshift(new Cell(this, { x: 0, y: 0 }));
- } else {
- this.boardData[c].push(new Cell(this, { x: 0, y: 0 }));
- }
- }
- } else {
- // Remove cells
- for (let k = 0; k < columnInitialLength - this.boardHeight; k++) {
- if (fromOriginCorner) {
- this.boardData[c].shift();
- } else {
- this.boardData[c].pop();
- }
- }
- }
- }
- // Then fix all cell locations
- // Note that our previously added 0,0 cells get fixed at this point.
- this.foreachCells((cell: Cell, row: number, column: number) => {
- cell.x = column;
- cell.y = row;
- });
-
- if (fromOriginCorner) {
- /* istanbul ignore next */
- if (this.boardWidth >= oldWidth) {
- // cells added first
- const newHeadX = oldHeadX + (this.boardWidth - oldWidth);
- this.headXLocation = newHeadX < this.boardWidth ? newHeadX : this.boardWidth - 1;
- }
- if (this.boardWidth < oldWidth) {
- // cells were removed first
- const newHeadX = oldHeadX - (oldWidth - this.boardWidth);
- this.headXLocation = newHeadX >= 0 ? newHeadX : 0;
- }
- /* istanbul ignore next */
- if (this.boardHeight >= oldHeight) {
- // cells added first
- const newHeadY = oldHeadY + (this.boardHeight - oldHeight);
- this.headYLocation = newHeadY < this.boardHeight ? newHeadY : this.boardHeight - 1;
- }
- if (this.boardHeight < oldHeight) {
- // cells were removed first
- const newHeadY = oldHeadY - (oldHeight - this.boardHeight);
- this.headYLocation = newHeadY >= 0 ? newHeadY : 0;
- }
- } else {
- // The added case should not alter head
- if (this.boardWidth < oldWidth) {
- // cells were removed last
- this.headXLocation = oldHeadX < this.boardWidth ? oldHeadX : this.boardWidth - 1;
- }
- if (this.boardHeight < oldHeight) {
- // cells were removed last
- this.headYLocation = oldHeadY < this.boardHeight ? oldHeadY : this.boardHeight - 1;
- }
- }
- this.emit(
- Board.onSizeChanged,
- { width: this.boardWidth, height: this.boardHeight },
- [this.headXLocation, this.headYLocation],
- fromOriginCorner,
- { width: oldWidth, height: oldHeight },
- [oldHeadX, oldHeadY]
- );
- }
-
- /**
- * Retrieve a two element array with the delta value to move the head to given a
- * specific direction. The delta is considered using the `deltaValue` argument,
- * thus increasing or decreasing by that amount depending on the given direction.
- * If no deltaValue is given, the delta becomes the maximum possible value for the
- * given board, that is, the delta between the head location and the border in the
- * given direction.
- * @param direction The direction to use to calculate the delta value.
- * @param deltaValue The delta number to use when calculating, or undefined if
- * the maximum available is ought to be used.
- */
- private innerGetDeltaByDirection(direction: Direction, deltaValue?: number): [number, number] {
- switch (direction) {
- case Direction.East:
- return [deltaValue ?? this.width - 1 - this.headXLocation, 0];
- case Direction.West:
- return [deltaValue ? -deltaValue : -this.headXLocation, 0];
- case Direction.North:
- return [0, deltaValue ?? this.height - 1 - this.headYLocation];
- case Direction.South:
- return [0, deltaValue ? -deltaValue : -this.headYLocation];
- /* istanbul ignore next */
- default:
- return [0, 0];
- }
- }
-}
diff --git a/src/GobstonesLang/BoardDefinition.ts b/src/GobstonesLang/BoardDefinition.ts
deleted file mode 100644
index 3ff052d..0000000
--- a/src/GobstonesLang/BoardDefinition.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-
-/**
- * The definition of a Board as expected by the current Gobstones Interpreter.
- * This definition make heavy assumptions as for the origin of the board and
- * it's internal structure. Although this definition is left for reference,
- * the {@link Board} class (which implements this interface) should be considered
- * the new standard of what a board is, and should be used for every new development.
- *
- * @group Internal: Types
- * @internal
- */
-export interface BoardDefinition {
- /** The board format. Always: GBB/1.0 as it's derived from the GBB format */
- format: string;
- /** The width of the board */
- width: number;
- /** The height of the board */
- height: number;
- /**
- * The head location as [x, y] position, where the position should comply to:
- * ```typescript
- * 0 <= x < this.width && 0 <= y < this.height
- * ```
- */
- head: CellLocation;
- /**
- * Array of `this.width` elements, each of which is an array of `this.height` elements,
- * each of which is a cell, of the form `{"a": na, "n": nn, "r": nr, "v": nv}`,
- * in such a way that:
- * * `this.board[x][y].a` = number of blue stones at (x, y)
- * * `this.board[x][y].n` = number of black stones at (x, y)
- * * `this.board[x][y].r` = number of red stones at (x, y)
- * * `this.board[x][y].v` = number of green stones at (x, y)
- *
- * And it's assured that each element `this.board[x][y]` exists
- * for `0 <= x < this.width && 0 <= y < this.height`.
- */
- board: BoardInfo;
-}
-
-/**
- * This type represents the Board cell information where given a board satisfies
- * `board.width` elements, each of which is an array of `board.height` elements,
- * each of which is a cell, of the form `{"a": na, "n": nn, "r": nr, "v": nv}`,
- * in such a way that:
- * * `board.board[x][y].a` = number of blue stones at (x, y)
- * * `board.board[x][y].n` = number of black stones at (x, y)
- * * `board.board[x][y].r` = number of red stones at (x, y)
- * * `board.board[x][y].v` = number of green stones at (x, y)
- *
- * And it's assured that each element `this.board[x][y]` exists
- * for `0 <= x < board.width && 0 <= y < board.height`.
- *
- * @group Internal: Types
- * @internal
- */
-export type BoardInfo = CellInfo[][];
-
-/**
- * A cell location is just a two elements array (a pair)
- * in the form of `[x, y]` where `x` is the column that
- * the head is in and `y` is the row that the head is in.
- *
- * @group Internal: Types
- * @internal
- */
-export type CellLocation = [number, number];
-
-/**
- * The information of a cell such that:
- * * `a` = number of blue stones
- * * `n` = number of black stones
- * * `r` = number of red stones
- * * `v` = number of green stones
- *
- * @group Internal: Type
- * @internal
- */
-export interface CellInfo {
- a: number;
- n: number;
- r: number;
- v: number;
-}
-
-/**
- * A cell data definition consists of the location of a cell, and
- * the amount of stones for any color (if non zero, undefined may be used
- * is those attributes if zero is ought to be used for such color).
- *
- * @group Internal: Type
- * @internal
- */
-export interface CellDataDefinition extends Partial {
- x: number;
- y: number;
-}
diff --git a/src/GobstonesLang/BoardErrors.ts b/src/GobstonesLang/BoardErrors.ts
deleted file mode 100644
index 3ef5701..0000000
--- a/src/GobstonesLang/BoardErrors.ts
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-
-import { CellInfo, CellLocation } from './BoardDefinition';
-
-/**
- * The operation attempted to be performed when a {@link InvalidCellReading} error ocurred.
- *
- * @group API: Options
- * @internal
- */
-export type CellReadingActionAttempt = 'ReadCell' | 'ReadColumn' | 'ReadRow';
-/**
- * The operation attempted to be performed when a {@link LocationFallsOutsideBoard} error ocurred.
- *
- * @group API: Options
- * @internal
- */
-export type LocationChangeActionAttempt = 'Move' | 'SetLocation' | 'MoveToEdge';
-/**
- * The operation attempted to be performed when a {@link InvalidSizeChange} error ocurred.
- *
- * @group API: Options
- * @internal
- */
-export type InvalidSizeChangeAttempt = 'Resize' | 'RemoveRow' | 'RemoveColumn' | 'AddRows' | 'AddColumns';
-/**
- * The operation attempted to be performed when a {@link InvalidStonesAmount} error ocurred.
- *
- * @group API: Options
- * @internal
- */
-export type StonesChangeActionAttempt = 'AddStones' | 'RemoveStones' | 'SetStones';
-
-/**
- * The base class of the error hierarchy that is thrown when
- * an invalid operation is performed in the {@link Board}
- * class and it's associated {@link Cell}.
- *
- * @group API: Exceptions
- */
-export class BoardError extends Error {
- /** A boolean that specifies the instance as an error. Always `true`. */
- public readonly isError: boolean;
-
- public constructor(name: string, message: string) {
- super(message);
- this.name = name;
- this.isError = true;
- Object.setPrototypeOf(this, BoardError.prototype);
- }
-}
-
-/**
- * This error is thrown when attempting to create a board
- * with invalid data.
- *
- * @group API: Exceptions
- */
-export class InvalidBoardDescription extends BoardError {
- /** The height attempted to create the board with */
- private height: number;
- /** The width attempted to create the board with */
- private width: number;
- /** The cell location attempted to create the board with */
- private cellLocation: CellLocation;
-
- public constructor(height: number, width: number, cellLocation: CellLocation) {
- super(
- 'InvalidBoardDescription',
- `The values used to create the board are invalid. ` +
- ` height: ${height}, width: ${width}, cell location: ${cellLocation}`
- );
- this.height = height;
- this.width = width;
- this.cellLocation = cellLocation;
- Object.setPrototypeOf(this, InvalidBoardDescription.prototype);
- }
-}
-
-/**
- * This error is thrown when attempting to read a cell, a
- * column or a row but an invalid location is given.
- *
- * @group API: Exceptions
- */
-export class InvalidCellReading extends BoardError {
- /** The action attempted to be performed */
- public readonly attempt: CellReadingActionAttempt;
- /** The coordinate the head was attempted to set into */
- public readonly failingCoordinate: CellLocation;
-
- public constructor(attempt: CellReadingActionAttempt, failingCoordinate: CellLocation) {
- super(
- 'InvalidCellReading',
- `The attempt of ${attempt} failed for coordinate [${failingCoordinate[0]}, ${failingCoordinate[1]}].`
- );
- this.attempt = attempt;
- this.failingCoordinate = failingCoordinate;
- Object.setPrototypeOf(this, InvalidCellReading.prototype);
- }
-}
-
-/**
- * This error is thrown when attempting to move the head, but an
- * invalid location is given.
- *
- * @group API: Exceptions
- */
-export class LocationFallsOutsideBoard extends BoardError {
- /** The action attempted to be performed */
- public readonly attempt: LocationChangeActionAttempt;
- /** The coordinate the head was attempted to set into */
- public readonly failingCoordinate: CellLocation;
- /** The previous coordinate the head was in */
- public readonly previousCoordinate: CellLocation;
-
- public constructor(
- attempt: LocationChangeActionAttempt,
- failingCoordinate: CellLocation,
- previousCoordinate: CellLocation
- ) {
- super(
- 'LocationFallsOutsideBoard',
- `The attempt of ${attempt} from [${previousCoordinate[0]}, ` +
- `${previousCoordinate[1]}] falls outside the board on ` +
- `coordinate [${failingCoordinate[0]}, ${failingCoordinate[1]}].`
- );
- this.attempt = attempt;
- this.failingCoordinate = failingCoordinate;
- this.previousCoordinate = previousCoordinate;
- Object.setPrototypeOf(this, LocationFallsOutsideBoard.prototype);
- }
-}
-
-/**
- * This error is thrown when attempting to change the size of the board,
- * but an invalid size is given
- *
- * @group API: Exceptions
- */
-export class InvalidSizeChange extends BoardError {
- /** The action attempted to be performed */
- public readonly attempt: InvalidSizeChangeAttempt;
- /** The previous width of the board */
- public readonly previousWidth: number;
- /** The previous height of the board */
- public readonly previousHeight: number;
- /** The new width of the board */
- public readonly newWidth: number;
- /** The new height of the board */
- public readonly newHeight: number;
-
- public constructor(
- attempt: InvalidSizeChangeAttempt,
- previousWidth: number,
- previousHeight: number,
- newWidth: number,
- newHeight: number
- ) {
- super(
- 'InvalidSizeChange',
- `The attempt of changing size by ${attempt} from width ${previousWidth}, ` +
- `and height ${previousHeight} ends in an invalid board of width ` +
- `${newWidth} and height ${newHeight}.`
- );
- this.attempt = attempt;
- this.previousWidth = previousWidth;
- this.previousHeight = previousHeight;
- this.newWidth = newWidth;
- this.newHeight = newHeight;
- Object.setPrototypeOf(this, InvalidSizeChange.prototype);
- }
-}
-
-/**
- * This error is thrown when attempting to change the stones amount
- * with an invalid amount of stone (negative amount).
- *
- * @group API: Exceptions
- */
-export class InvalidStonesAmount extends BoardError {
- /** The action attempted to be performed */
- public readonly attempt: StonesChangeActionAttempt;
- /** The color of the stones attempted to change */
- public readonly color: string;
- /** The number of stones that was attempted to set */
- public readonly amount: number;
- /** The state the cell was previously in */
- public readonly previousCellState: CellInfo;
-
- public constructor(attempt: StonesChangeActionAttempt, color: string, amount: number, previousCellState: CellInfo) {
- super('InvalidStonesAmount', `The attempt of ${attempt} failed for color ${color} given ${amount}.`);
- this.attempt = attempt;
- this.color = color;
- this.amount = amount;
- this.previousCellState = previousCellState;
- Object.setPrototypeOf(this, InvalidStonesAmount.prototype);
- }
-}
diff --git a/src/GobstonesLang/Cell.ts b/src/GobstonesLang/Cell.ts
deleted file mode 100644
index 0be6b3c..0000000
--- a/src/GobstonesLang/Cell.ts
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-
-import { Board } from './Board';
-import { CellDataDefinition, CellInfo, CellLocation } from './BoardDefinition';
-import { InvalidStonesAmount, StonesChangeActionAttempt } from './BoardErrors';
-import { Color } from './Color';
-import { Direction } from './Direction';
-
-import { EventEmitter } from '../Events/EventEmitter';
-import { expect } from '../Expectations';
-
-/**
- * This object contains the default values for a {@link Board} and it's cells.
- * When a specific value is not given, the defaults are used.
- *
- * @group Internal: Default Values
- * @internal
- */
-const Defaults = {
- [Color.BLUE]: 0,
- [Color.BLACK]: 0,
- [Color.RED]: 0,
- [Color.GREEN]: 0
-} as unknown as CellInfo;
-
-/**
- * This type represents the function that acts as a callback of
- * the {@link Cell.onStonesChanged} event. Such an event is thrown by
- * an instance of a cell whenever an operation is performed such
- * that the cell changes the amount of cells.
- *
- * This function receives 3 arguments:
- * * the location of the cell as x, y coordinates.
- * * The amount of the stones in the cell, after the change ocurred.
- * * The previous amount of stones the cell had.
- *
- * @see {@link Cell.onStonesChanged} for more information.
- *
- * @group API: Events
- * @event
- */
-export type OnCellStonesChanged = (
- cellLocation: { x: number; y: number },
- stones: {
- [Color.BLUE]: number;
- [Color.BLACK]: number;
- [Color.RED]: number;
- [Color.GREEN]: number;
- },
- previousStones: {
- [Color.BLUE]: number;
- [Color.BLACK]: number;
- [Color.RED]: number;
- [Color.GREEN]: number;
- }
-) => void;
-
-/**
- * This interface contains the signature of the
- * events that a Cell can throw.
- *
- * @group Internal: Events
- * @internal
- */
-export interface CellEvents {
- [Cell.onStonesChanged]: OnCellStonesChanged;
-}
-
-/**
- * A cell
- *
- * @group API: Main
- */
-export class Cell extends EventEmitter implements CellInfo {
- /**
- * This event is thrown whenever an action that alters the stones in
- * the cell is performed. Listeners of this action are expected to conform to
- * {@link OnCellStonesChanged}.
- *
- * The actions that trigger this callback include:
- * * Setting the {@link a} attribute of an instance.
- * * Setting the {@link n} attribute of an instance.
- * * Setting the {@link r} attribute of an instance.
- * * Setting the {@link v} attribute of an instance.
- * * Calling {@link setStonesOf} on an instance with any color and value.
- * * Calling {@link addStones} on an instance with any color and value.
- * * Calling {@link removeStones} on an instance with any color and value.
- * * Calling {@link empty} on an instance.
- *
- * @event
- */
- public static readonly onStonesChanged: unique symbol = Symbol('onStonesChanged');
-
- /**
- * A reference to the board. A cell cannot exist independently from a Board,
- * they both know each other and work together to achieve the different actions.
- */
- private board: Board;
-
- /**
- * The amount of blue stones of this cell.
- */
- private blueStones: number;
- /**
- * The amount of black stones of this cell.
- */
- private blackStones: number;
- /**
- * The amount of red stones of this cell.
- */
- private redStones: number;
- /**
- * The amount of green stones of this cell.
- */
- private greenStones: number;
-
- /**
- * The X coordinate of the location of this cell within the board.
- */
- private locationX: number;
- /**
- * The Y coordinate of the location of this cell within the board.
- */
- private locationY: number;
-
- /**
- * Create a new instance of a cell with the given cell information.
- * A cell should be given the {@link Board} it belongs to, as a cell cannot exist
- * without a board. Additionally, at least the [x, y] coordinate of the cell
- * within the board should be passed as the cell's information, and optionally,
- * the amount of stones of the different colors in case they are not zero.
- *
- * When creating a cell and passing color information, you should prefer using
- * the Color enum as a key, instead of the enum value as a string.
- * @example
- * ```
- * new Cell(board, { x: 3, y: 2, [Color.Red]: 5, [Color.Green]: 1 });
- * ```
- * This allows for abstracting away the inner representation of the enum, and allow
- * for changes in the future without impacting your code.
- *
- * @param board The board this cell belongs to.
- * @param cellInfo The information for this cell, at least the X and Y coordinates,
- * and optionally, amount of stones for each color.
- */
- public constructor(board: Board, cellInfo: CellDataDefinition) {
- super();
- this.board = board;
-
- this.locationX = cellInfo.x;
- this.locationY = cellInfo.y;
-
- this.blueStones = cellInfo[Color.BLUE] ?? Defaults[Color.BLUE];
- this.blackStones = cellInfo[Color.BLACK] ?? Defaults[Color.BLACK];
- this.redStones = cellInfo[Color.RED] ?? Defaults[Color.RED];
- this.greenStones = cellInfo[Color.GREEN] ?? Defaults[Color.GREEN];
- }
-
- /* ************* Accessors ************** */
-
- /**
- * Get or set the X location of this cell within the board.
- *
- * @warning The getter can be used always. The setter on the other hand
- * although exported, should not be used, as it's usage is reserved
- * for internal actions of the board only (It's used exclusively on
- * recalculating coordinates when the board resizes). Avoid the
- * setter at all cost.
- *
- * @param value The new value for the X coordinate.
- *
- * @returns This cells X coordinate within the board
- */
- public get x(): number {
- return this.locationX;
- }
- public set x(value: number) {
- this.locationX = value;
- }
-
- /**
- * Get or set the Y location of this cell within the board.
- *
- * @warning The getter can be used always. The setter on the other hand
- * although exported, should not be used, as it's usage is reserved
- * for internal actions of the board only (It's used exclusively on
- * recalculating coordinates when the board resizes). Avoid the
- * setter at all cost.
- *
- * @param value The new value for the Y coordinate.
- *
- * @returns This cells Y coordinate within the board
- */
- public get y(): number {
- return this.locationY;
- }
- public set y(value: number) {
- this.locationY = value;
- }
-
- /**
- * Get the amount of {@link Color.Blue | blue} stones of this cell.
- * Or instead, set the amount of stones.
- *
- * @deprecated This is retain only for compatibility reasons.
- * If you need to access the amount of stones of a color,
- * use {@link getStonesOf} instead, passing the color as an argument.
- * So the preferred method for blue stones should be
- * ```
- * cell.getStonesOf(Color.Blue);
- * ```
- * For setting the stones of a color, use {@link setStonesOf} instead,
- * with the color and the new desired value. The preferred way for
- * blue stones should be:
- * ```
- * cell.setStonesOf(Color.Blue, amount);
- * ```
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `SetStones`
- * if the new amount of stones is lower than zero.
- *
- * @param value The new amount of {@link Color.Blue | blue} stones
- *
- * @returns The number of stones of {@link Color.Blue}.
- */
- public get a(): number {
- return this.getStonesOf(Color.Blue);
- }
- /* istanbul ignore next */
- public set a(value: number) {
- this.setStonesOf(Color.Blue, value);
- }
-
- /**
- * Get the amount of {@link Color.Black | black} stones of this cell.
- * Or instead, set the amount of stones.
- *
- * @deprecated This is retain only for compatibility reasons.
- * If you need to access the amount of stones of a color,
- * use {@link getStonesOf} instead, passing the color as an argument.
- * So the preferred method for black stones should be
- * ```
- * cell.getStonesOf(Color.Black);
- * ```
- * For setting the stones of a color, use {@link setStonesOf} instead,
- * with the color and the new desired value. The preferred way for
- * black stones should be:
- * ```
- * cell.setStonesOf(Color.Black, amount);
- * ```
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `SetStones`
- * if the new amount of stones is lower than zero.
- *
- * @param value The new amount of {@link Color.Black | black} stones
- *
- * @returns The number of stones of {@link Color.Black}.
- */
- public get n(): number {
- return this.getStonesOf(Color.Black);
- }
- /* istanbul ignore next */
- public set n(value: number) {
- this.setStonesOf(Color.Black, value);
- }
-
- /**
- * Get the amount of {@link Color.Red | red} stones of this cell.
- * Or instead, set the amount of stones.
- *
- * @deprecated This is retain only for compatibility reasons.
- * If you need to access the amount of stones of a color,
- * use {@link getStonesOf} instead, passing the color as an argument.
- * So the preferred method for red stones should be
- * ```
- * cell.getStonesOf(Color.Red);
- * ```
- * For setting the stones of a color, use {@link setStonesOf} instead,
- * with the color and the new desired value. The preferred way for
- * red stones should be:
- * ```
- * cell.setStonesOf(Color.Red, amount);
- * ```
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `SetStones`
- * if the new amount of stones is lower than zero.
- *
- * @param value The new amount of {@link Color.Red | red} stones
- *
- * @returns The number of stones of {@link Color.Red}.
- */
- public get r(): number {
- return this.getStonesOf(Color.Red);
- }
- /* istanbul ignore next */
- public set r(value: number) {
- this.setStonesOf(Color.Red, value);
- }
-
- /**
- * Get the amount of {@link Color.Green | green} stones of this cell.
- * Or instead, set the amount of stones.
- *
- * @deprecated This is retain only for compatibility reasons.
- * If you need to access the amount of stones of a color,
- * use {@link getStonesOf} instead, passing the color as an argument.
- * So the preferred method for green stones should be
- * ```
- * cell.getStonesOf(Color.Green);
- * ```
- * For setting the stones of a color, use {@link setStonesOf} instead,
- * with the color and the new desired value. The preferred way for
- * green stones should be:
- * ```
- * cell.setStonesOf(Color.Green, amount);
- * ```
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `SetStones`
- * if the new amount of stones is lower than zero.
- *
- * @param value The new amount of {@link Color.Green | green} stones
- *
- * @returns The number of stones of {@link Color.Green}.
- */
- public get v(): number {
- return this.getStonesOf(Color.Green);
- }
- /* istanbul ignore next */
- public set v(value: number) {
- this.setStonesOf(Color.Green, value);
- }
-
- /**
- * Get the current X, Y coordinate of the cell within the board,
- * as a two element array in the form `[x, y]`.
- *
- * @returns A two element array with the X and Y location of
- * this cell within the board.
- */
- public get location(): CellLocation {
- return [this.x, this.y];
- }
-
- /* ************* Cloning ************** */
-
- /**
- * Clone this cell. Pass a board in order to set the
- * associated board of the cloned cell to that element.
- *
- * @param cloneBoard The Board the cloned cell will be associated to.
- * @returns A new {@link Cell}
- */
- public clone(newBoard: Board): Cell {
- return new Cell(newBoard, {
- x: this.x,
- y: this.y,
- [Color.BLUE]: this.getStonesOf(Color.Blue),
- [Color.BLACK]: this.getStonesOf(Color.Black),
- [Color.RED]: this.getStonesOf(Color.Red),
- [Color.GREEN]: this.getStonesOf(Color.Green)
- });
- }
-
- /* ************* Managing & Querying Stones ************** */
-
- /**
- * Answer wether this cell contains stones of the given color.
- * That is, if the amount of stones of the given color is greater
- * than zero.
- *
- * @param color The color of the stones to check for existence.
- *
- * @returns `true` if the cell has stones of the given color, `false` otherwise.
- */
- public hasStonesOf(color: Color): boolean {
- return this.innerGetStones(color) > 0;
- }
-
- /**
- * Answer with the amount of stones of the given color in this cell.
- *
- * @param color The color of the stones to retrieve the amount.
- *
- * @returns The amount of stones of the given color.
- */
- public getStonesOf(color: Color): number {
- return this.innerGetStones(color);
- }
-
- /**
- * Set the amount of stones of the given color in this cell.
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `SetStones`
- * if the new amount of stones is lower than zero.
- *
- * @param color The color of the stones to set the amount.
- * @param amount The amount of stones to set.
- */
- public setStonesOf(color: Color, amount: number): void {
- this.innerSetStones(color, amount, 'SetStones');
- }
-
- /**
- * Add a given amount of stones of a particular color to this cell.
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `AddStones`
- * if the new amount of stones is lower or equal than zero.
- *
- * @param color The color of the stones to add to.
- * @param amount The amount of stones to add.
- */
- public addStones(color: Color, amount: number = 1): void {
- expect(amount)
- .toBeGreaterThan(0)
- .orThrow(new InvalidStonesAmount('AddStones', color.toString(), amount, this));
- this.innerSetStones(color, this.getStonesOf(color) + amount, 'AddStones');
- }
-
- /**
- * Remove a given amount of stones of a particular color to this cell.
- *
- * @throws {@link InvalidStonesAmount} with the attempt set to `AddStones`
- * if the new amount of stones is lower or equal than zero, or if the
- * amount of stones to remove is greater than the amount currently in
- * the cell.
- *
- * @param color The color of the stones to remove to.
- * @param amount The amount of stones to remove.
- */
- public removeStones(color: Color, amount: number = 1): void {
- expect(amount)
- .toBeGreaterThan(0)
- .orThrow(new InvalidStonesAmount('RemoveStones', color.toString(), amount, this));
- this.innerSetStones(color, this.getStonesOf(color) - amount, 'RemoveStones');
- }
-
- /**
- * Answer wether this cell is empty, that is, it has no stones of any color.
- * In other words, the amount of stones of any color is zero.
- *
- * @returns `true` if the cell is empty, `false` otherwise.
- */
- public isEmpty(): boolean {
- let hasNone = true;
- Color.foreach((color) => {
- if (this.hasStonesOf(color)) {
- hasNone = false;
- }
- });
- return hasNone;
- }
-
- /**
- * Answer wether this cell has any stones, that is, it has any stones of any color.
- * In other words, the amount of stones of any color is other than zero.
- *
- * @returns `true` if the cell has stones, `false` otherwise.
- */
- public hasStones(): boolean {
- return !this.isEmpty();
- }
-
- /**
- * Answer the amount of stones of this cell. That is the total amount of
- * stones, adding the number of stones of every color.
- *
- * @returns The total number of stones of the cell.
- */
- public getStonesAmount(): number {
- let total = 0;
- Color.foreach((color) => {
- total += this.getStonesOf(color);
- });
- return total;
- }
-
- /**
- * Empty the cell, leaving the stone amount for each color to zero.
- */
- public empty(): void {
- this.blueStones = 0;
- this.blackStones = 0;
- this.redStones = 0;
- this.greenStones = 0;
- }
-
- /* ************* Querying Location ************** */
-
- /**
- * Answer wether this cell is the cell below the head's location
- * within the board.
- *
- * @returns `true` if the cell is below the head's location, `false` otherwise.
- */
- public isHeadLocation(): boolean {
- return this.board.headX === this.x && this.board.headY === this.y;
- }
-
- /**
- * Answer wether this cell is at the border to the given direction
- * at the board.
- *
- * @returns `true` if the cell is at the border to the given direction, `false` otherwise.
- */
- public isAtBorderAt(direction: Direction): boolean {
- switch (direction) {
- case Direction.North:
- return this.y === this.board.height - 1;
- case Direction.South:
- return this.y === 0;
- case Direction.East:
- return this.x === this.board.width - 1;
- case Direction.West:
- return this.x === 0;
- /* istanbul ignore next */
- default:
- return false;
- }
- }
-
- /**
- * Return the neighbor of this cell to the given direction, that is, another cell.
- * If the cell is at the border at the given direction, then `undefined` is returned.
- *
- * @param direction The direction to which to get the neighbor from.
- *
- * @returns The neighbor cell at the given direction, or `undefined`
- * if the neighbor does not exist
- */
- public neighborTo(direction: Direction): Cell | undefined {
- const [deltaX, deltaY] = this.innerGetDeltaByDirection(direction, 1);
-
- if (this.isAtBorderAt(direction)) return undefined;
- return this.board.getCell(this.x + deltaX, this.y + deltaY);
- }
-
- /**
- * Return the neighbor of this cell to the given diagonal, that is, another cell.
- * If the cell is at the border at the given diagonal, then `undefined` is returned.
- *
- * @param vertical The vertical direction to which to get the neighbor from.
- * @param horizontal The horizontal direction to which to get the neighbor from.
- *
- * @returns The neighbor cell at the given diagonal, or `undefined`
- * if the neighbor does not exist.
- */
- public neighborDiagonalTo(vertical: Direction, horizontal: Direction): Cell | undefined {
- if (this.isAtBorderAt(vertical) || this.isAtBorderAt(horizontal)) return undefined;
-
- const verticalDelta = this.innerGetDeltaByDirection(vertical, 1)[1];
- const horizontalDelta = this.innerGetDeltaByDirection(horizontal, 1)[0];
-
- return this.board.getCell(this.x + horizontalDelta, this.y + verticalDelta);
- }
-
- /**
- * Retrieve all the neighbors of the current cell. Only existing neighbors are
- * returned. The returned neighbors may be 'orthogonal' (the default), where
- * only orthogonal neighbors are returned, 'diagonal', where only diagonal
- * diagonal neighbors are returned, or 'both' where both orthogonal and diagonal
- * neighbors are returned.
- *
- * @param location One of 'orthogonal', 'diagonal' or 'both'.
- *
- * @returns A list of neighbors of the current cell.
- */
- public neighbors(location: 'orthogonal' | 'diagonal' | 'both' = 'orthogonal'): Cell[] {
- const neighbors: Cell[] = [];
- Direction.foreach((dir) => {
- const nextDir = Direction.next(dir);
- if (!this.isAtBorderAt(dir) && location !== 'diagonal') {
- neighbors.push(this.neighborTo(dir) as Cell);
- }
- if (!this.isAtBorderAt(dir) && !this.isAtBorderAt(nextDir) && location !== 'orthogonal') {
- neighbors.push(
- this.neighborDiagonalTo(
- Direction.isVertical(dir) ? dir : nextDir,
- Direction.isVertical(dir) ? nextDir : dir
- ) as Cell
- );
- }
- });
- return neighbors;
- }
-
- /**
- * Retrieve a string representation of the cell, mainly for debugging purposes.
- */
- /* istanbul ignore next */
- public toString(): string {
- return (
- `x: ${this.x} y: ${this.y} > ` +
- `${this.getStonesOf(Color.Blue)} B ${this.getStonesOf(Color.Black)} K ` +
- `${this.getStonesOf(Color.Red)} R ${this.getStonesOf(Color.Green)} G`
- );
- }
-
- /**
- * Retrieve the amount of stones of a given color for this cell.
- *
- * @param color The color to retrieve the amount of.
- */
- private innerGetStones(color: Color): number {
- switch (color) {
- case Color.Blue:
- return this.blueStones;
- case Color.Black:
- return this.blackStones;
- case Color.Red:
- return this.redStones;
- case Color.Green:
- return this.greenStones;
- /* istanbul ignore next */
- default:
- return 0;
- }
- }
-
- /**
- * Retrieve a two element array with the delta value of a neighbor cell to a
- * specific direction. The delta is considered using the `deltaValue` argument,
- * thus increasing or decreasing by that amount depending on the given direction.
- * @param direction The direction to use to calculate the delta value.
- * @param deltaValue The delta number to use when calculating.
- */
- private innerGetDeltaByDirection(direction: Direction, deltaValue: number): [number, number] {
- switch (direction) {
- case Direction.East:
- return [deltaValue, 0];
- case Direction.West:
- return [-deltaValue, 0];
- case Direction.North:
- return [0, deltaValue];
- case Direction.South:
- return [0, -deltaValue];
- /* istanbul ignore next */
- default:
- return [0, 0];
- }
- }
-
- /**
- * Set the amount of stones of the given color for this cell, to the given amount.
- *
- * @throws {@link InvalidStonesAmount} with the given performed action, when the
- * amount of stones to set is lower than zero.
- *
- * @param color The color of the stones to set.
- * @param amount The amount to set the stones of that color.
- * @param performedAction The attempt to set the error to in case of failure.
- */
- private innerSetStones(color: Color, amount: number, performedAction: StonesChangeActionAttempt): void {
- expect(amount)
- .toBeGreaterThanOrEqual(0)
- .orThrow(new InvalidStonesAmount(performedAction, color.toString(), amount, this));
- const oldBlueStones = this.blueStones;
- const oldBlackStones = this.blackStones;
- const oldRedStones = this.redStones;
- const oldGreenStones = this.greenStones;
- switch (color) {
- case Color.Blue:
- this.blueStones = amount;
- break;
- case Color.Black:
- this.blackStones = amount;
- break;
- case Color.Red:
- this.redStones = amount;
- break;
- case Color.Green:
- this.greenStones = amount;
- break;
- /* istanbul ignore next */
- default:
- break;
- }
- this.emit(
- Cell.onStonesChanged,
- { x: this.locationX, y: this.locationY },
- {
- [Color.BLUE]: this.blueStones,
- [Color.BLACK]: this.blackStones,
- [Color.RED]: this.redStones,
- [Color.GREEN]: this.greenStones
- },
- {
- [Color.BLUE]: oldBlueStones,
- [Color.BLACK]: oldBlackStones,
- [Color.RED]: oldRedStones,
- [Color.GREEN]: oldGreenStones
- }
- );
- }
-}
diff --git a/src/GobstonesLang/Color.ts b/src/GobstonesLang/Color.ts
deleted file mode 100644
index ed3ea9d..0000000
--- a/src/GobstonesLang/Color.ts
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-
-/**
- * This enum represent the valid Gobstones Colors.
- * It provides a set of singleton cases, for each possible value,
- * as well as static accessors for each case name string (that should
- * be used as key for representing directions).
- *
- * Additionally it provides handy methods for operations that are common
- * with colors in Gobstones, such as asking for the first, the last,
- * the next or the previous.
- *
- * Note that colors are sorted in the following order, from first to last.
- * * Color.Blue
- * * Color.Black
- * * Color.Red
- * * Color.Green
- *
- * Always prefer using the provided static names as object keys when needed,
- * such as:
- *
-```
-{
- [Color.BLUE]: 5,
- [Color.BLACK]: 3,
- [Color.RED]: 7,
- [Color.GREEN]: 0
-}
-```
- *
- * @group API: Main
- */
-export class Color {
- /**
- * The Blue Color internal value.
- * @private
- */
- public static BLUE = 'a' as const;
-
- /**
- * The Black Color internal value.
- * @private
- */
- public static BLACK = 'n' as const;
-
- /**
- * The Red Color internal value.
- * @private
- */
- public static RED = 'r' as const;
-
- /**
- * The Green Color internal value.
- * @private
- */
- public static GREEN = 'v' as const;
-
- /**
- * The Blue color. Use whenever a reference to Blue is needed.
- */
- public static Blue = new Color(Color.BLUE);
-
- /**
- * The Black color. Use whenever a reference to Black is needed.
- */
- public static Black = new Color(Color.BLACK);
-
- /**
- * The Red color. Use whenever a reference to Red is needed.
- */
- public static Red = new Color(Color.RED);
-
- /**
- * The Green color. Use whenever a reference to Green is needed.
- */
- public static Green = new Color(Color.GREEN);
-
- /**
- * The smallest Color possible, currently {@link Color.Blue}
- *
- * @returns The smallest color.
- */
- public static min(): Color {
- return Color.Blue;
- }
-
- /**
- * The biggest Color possible, currently {@link Color.Green}
- *
- * @returns The biggest color.
- */
- public static max(): Color {
- return Color.Green;
- }
-
- /**
- * The next Color of a given Color. Colors are sorted
- * in the following way, from first to last:
- * * Color.Blue
- * * Color.Black
- * * Color.Red
- * * Color.Green
- *
- * And they are cyclic, that is, the next color of Green is Blue.
- *
- * @param color The color to obtain the next value from.
- *
- * @returns The next color of the given one.
- */
- public static next(color: Color): Color {
- switch (color) {
- case Color.Blue:
- return Color.Black;
- case Color.Black:
- return Color.Red;
- case Color.Red:
- return Color.Green;
- case Color.Green:
- return Color.Blue;
- /* istanbul ignore next */
- default:
- return undefined as unknown as Color;
- }
- }
-
- /**
- * The next Color of a given Color. Color are sorted
- * in the following way, from last to first:
- * * Color.Green
- * * Color.Red
- * * Color.Black
- * * Color.Blue
- *
- * And they are cyclic, that is, the previous color of Blue is Green.
- *
- * @param color The color to obtain the previous value from.
- *
- * @returns The previous color of the given one.
- */
- public static previous(color: Color): Color {
- switch (color) {
- case Color.Blue:
- return Color.Green;
- case Color.Black:
- return Color.Blue;
- case Color.Red:
- return Color.Black;
- case Color.Green:
- return Color.Red;
- /* istanbul ignore next */
- default:
- return undefined as unknown as Color;
- }
- }
-
- /**
- * Iterate over all the colors, in their defined order, from the smallest,
- * to the biggest, performing the callback over each color. A function that
- * expects a color and returns void is expected as an argument.
- *
- * @param f The callback to call on each iteration.
- */
- public static foreach(f: (color: Color) => void): void {
- let current = Color.min();
- while (current !== Color.max()) {
- f(current);
- current = Color.next(current);
- }
- f(current);
- }
-
- /**
- * The internal value of the color.
- */
- private innerValue: string;
-
- /**
- * Create a new instance of a color. This is private, as
- * colors are already provided in a singleton like pattern.
- */
- private constructor(value: string) {
- this.innerValue = value;
- }
-
- /**
- * The internal value of this element.
- * @private
- */
- public get value(): string {
- return this.innerValue;
- }
-
- /**
- * The next Color of this color. Colors are sorted
- * in the following way, from first to last:
- * * Color.Blue
- * * Color.Black
- * * Color.Red
- * * Color.Green
- *
- * And they are cyclic, that is, the next color of Green is Blue.
- *
- * @returns The next color of the given one.
- */
- public next(): Color {
- return Color.next(this);
- }
-
- /**
- * The next Color of this color. Color are sorted
- * in the following way, from last to first:
- * * Color.Green
- * * Color.Red
- * * Color.Black
- * * Color.Blue
- *
- * And they are cyclic, that is, the previous color of Blue is Green.
- *
- * @returns The previous color of the given one.
- */
- public previous(): Color {
- return Color.previous(this);
- }
-
- /** @inheritdoc */
- public toString(): string {
- return this.innerValue;
- }
-}
diff --git a/src/GobstonesLang/Direction.ts b/src/GobstonesLang/Direction.ts
deleted file mode 100644
index 92a0a94..0000000
--- a/src/GobstonesLang/Direction.ts
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-
-/**
- * This class represents the valid Gobstones Directions.
- * It provides a set of singleton cases, for each possible value,
- * as well as static accessors for each case name string (that should
- * be used as key for representing directions).
- *
- * Additionally it provides handy methods for operations that are common
- * with directions in Gobstones, such as asking for the first, the last,
- * the next, the previous or the opposite direction.
- *
- * Note that directions are sorted in the following order, from first to last.
- * * Direction.North
- * * Direction.East
- * * Direction.South
- * * Direction.West
- *
- * Always prefer using the provided static names as object keys when needed,
- * such as:
- *
-```
-{
- [Direction.NORTH]: 'Some value',
- [Direction.SOUTH]: 'Some other value'
-}
-```
- *
- * @group API: Main
- */
-export class Direction {
- /**
- * The North Direction internal value.
- * @private
- */
- public static NORTH = 'n' as const;
-
- /**
- * The East Direction internal value.
- * @private
- */
- public static EAST = 'e' as const;
-
- /**
- * The South Direction internal value.
- * @private
- */
- public static SOUTH = 's' as const;
-
- /**
- * The West Direction internal value.
- * @private
- */
- public static WEST = 'w' as const;
-
- /**
- * The North direction. Use whenever a reference to North is needed.
- */
- public static North = new Direction(Direction.NORTH);
-
- /**
- * The East direction. Use whenever a reference to East is needed.
- */
- public static East = new Direction(Direction.EAST);
-
- /**
- * The South direction. Use whenever a reference to South is needed.
- */
- public static South = new Direction(Direction.SOUTH);
-
- /**
- * The West direction. Use whenever a reference to West is needed.
- */
- public static West = new Direction(Direction.WEST);
-
- /**
- * The smallest Direction possible, currently {@link Direction.North}
- *
- * @returns The smallest direction.
- */
- public static min(): Direction {
- return Direction.North;
- }
-
- /**
- * The biggest Direction possible, currently {@link Direction.West}
- *
- * @returns The biggest direction.
- */
- public static max(): Direction {
- return Direction.West;
- }
-
- /**
- * The next Direction of a given Direction. Directions are sorted
- * in the following way, from first to last:
- * * Direction.North
- * * Direction.East
- * * Direction.South
- * * Direction.West
- *
- * And they are cyclic, that is, the next direction of West is North.
- *
- * @param dir The direction to obtain the next value from.
- *
- * @returns The next direction of the given one.
- */
- public static next(dir: Direction): Direction {
- switch (dir) {
- case Direction.North:
- return Direction.East;
- case Direction.East:
- return Direction.South;
- case Direction.South:
- return Direction.West;
- case Direction.West:
- return Direction.North;
- /* istanbul ignore next */
- default:
- return undefined as unknown as Direction;
- }
- }
-
- /**
- * The next Direction of a given Direction. Directions are sorted
- * in the following way, from last to first:
- * * Direction.West
- * * Direction.South
- * * Direction.East
- * * Direction.North
- *
- * And they are cyclic, that is, the previous direction of North is West.
- *
- * @param dir The direction to obtain the previous value from.
- *
- * @returns The previous direction of the given one.
- */
- public static previous(dir: Direction): Direction {
- switch (dir) {
- case Direction.North:
- return Direction.West;
- case Direction.East:
- return Direction.North;
- case Direction.South:
- return Direction.East;
- case Direction.West:
- return Direction.South;
- /* istanbul ignore next */
- default:
- return undefined as unknown as Direction;
- }
- }
-
- /**
- * The opposite Direction of a given Direction. Directions are opposed
- * to each other in pairs, those being:
- * * Direction.West is opposite to Direction.East and vice versa
- * * Direction.North is opposite to Direction.South and vice versa
- *
- * @param dir The direction to obtain the opposite value from.
- *
- * @returns The opposite direction of the given one.
- */
- public static opposite(dir: Direction): Direction {
- switch (dir) {
- case Direction.North:
- return Direction.South;
- case Direction.East:
- return Direction.West;
- case Direction.South:
- return Direction.North;
- case Direction.West:
- return Direction.East;
- /* istanbul ignore next */
- default:
- return undefined as unknown as Direction;
- }
- }
-
- /**
- * Answer wether or not the given direction is vertical,
- * that is, one of Direction.North or Direction.South.
- *
- * @param dir The direction to find out if it's vertical.
- *
- * @returns `true` if it's vertical, `false` otherwise.
- */
- public static isVertical(dir: Direction): boolean {
- return dir === Direction.North || dir === Direction.South;
- }
-
- /**
- * Answer wether or not the given direction is horizontal,
- * that is, one of Direction.East or Direction.West.
- *
- * @param dir The direction to find out if it's horizontal.
- *
- * @returns `true` if it's horizontal, `false` otherwise.
- */
- public static isHorizontal(dir: Direction): boolean {
- return !Direction.isVertical(dir);
- }
-
- /**
- * Iterate over all the directions, in their defined order, from the smallest,
- * to the biggest, performing the callback over each direction. A function that
- * expects a direction and returns void is expected as an argument.
- *
- * @param f The callback to call on each iteration.
- */
- public static foreach(f: (dir: Direction) => void): void {
- let current = Direction.min();
- while (current !== Direction.max()) {
- f(current);
- current = Direction.next(current);
- }
- f(current);
- }
-
- /**
- * The internal value of the direction.
- */
- private innerValue: string;
-
- /**
- * Create a new instance of a direction. This is private, as
- * directions are already provided in a singleton like pattern.
- */
- private constructor(value: string) {
- this.innerValue = value;
- }
-
- /**
- * The internal value of this element.
- * @private
- */
- public get value(): string {
- return this.innerValue;
- }
-
- /**
- * The next Direction of this direction. Directions are sorted
- * in the following way, from first to last:
- * * Direction.North
- * * Direction.East
- * * Direction.South
- * * Direction.West
- *
- * And they are cyclic, that is, the next direction of West is North.
- *
- * @param dir The direction to obtain the next value from.
- *
- * @returns The next direction of the given one.
- */
- public next(): Direction {
- return Direction.next(this);
- }
-
- /**
- * The next Direction of this one. Directions are sorted
- * in the following way, from last to first:
- * * Direction.West
- * * Direction.South
- * * Direction.East
- * * Direction.North
- *
- * And they are cyclic, that is, the previous direction of North is West.
- *
- * @param dir The direction to obtain the previous value from.
- *
- * @returns The previous direction of the given one.
- */
- public previous(): Direction {
- return Direction.previous(this);
- }
-
- /**
- * The opposite Direction of this one. Directions are opposed
- * to each other in pairs, those being:
- * * Direction.West is opposite to Direction.East and vice versa
- * * Direction.North is opposite to Direction.South and vice versa
- *
- * @returns The opposite direction of the given one.
- */
- public opposite(): Direction {
- return Direction.opposite(this);
- }
-
- /**
- * Answer wether or not this direction is vertical,
- * that is, one of Direction.North or Direction.South.
- *
- * @returns `true` if it's vertical, `false` otherwise.
- */
- public isVertical(): boolean {
- return Direction.isVertical(this);
- }
-
- /**
- * Answer wether or not this direction is horizontal,
- * that is, one of Direction.East or Direction.West.
- *
- * @returns `true` if it's horizontal, `false` otherwise.
- */
- public isHorizontal(): boolean {
- return Direction.isHorizontal(this);
- }
-
- /** @inheritdoc */
- public toString(): string {
- return this.innerValue;
- }
-}
diff --git a/src/GobstonesLang/IdentifierRegexp.ts b/src/GobstonesLang/IdentifierRegexp.ts
deleted file mode 100644
index b27bfe1..0000000
--- a/src/GobstonesLang/IdentifierRegexp.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-/* eslint-disable max-len */
-
-/**
- * Numbers are only ASCII characters for digits
- *
- * @group API: Regexp
- */
-export const number = /[0-9][0-9]*/;
-
-/**
- * Any word starting with an uppercase letter (or titlecase for some languages),
- * that may be followed by any amount of unicode letters or decimal numbers, or ASCII underscore.
- *
- * ES Form:
- * ```
- * /(\p{Uppercase_Letter}|\p{Titlecase_Letter})[\p{Letter}\p{Decimal_Number}_]* /u;
- * ```
- *
- * @group API: Regexp
- */
-export const upperId =
- /((?:[A-Z\xC0-\xD6\xD8-\xDE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1C90-\u1CBA\u1CBD-\u1CBF\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\uA7BA\uA7BC\uA7BE\uA7C2\uA7C4-\uA7C7\uA7C9\uA7F5\uFF21-\uFF3A]|\uD801[\uDC00-\uDC27\uDCB0-\uDCD3]|\uD803[\uDC80-\uDCB2]|\uD806[\uDCA0-\uDCBF]|\uD81B[\uDE40-\uDE5F]|\uD835[\uDC00-\uDC19\uDC34-\uDC4D\uDC68-\uDC81\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB5\uDCD0-\uDCE9\uDD04\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD38\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD6C-\uDD85\uDDA0-\uDDB9\uDDD4-\uDDED\uDE08-\uDE21\uDE3C-\uDE55\uDE70-\uDE89\uDEA8-\uDEC0\uDEE2-\uDEFA\uDF1C-\uDF34\uDF56-\uDF6E\uDF90-\uDFA8\uDFCA]|\uD83A[\uDD00-\uDD21])|[\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC])(?:[0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BEF\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D66-\u0D6F\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F29\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDD30-\uDD39\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC66-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF39]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])*/;
-
-/**
- * Any word starting with an lowercase letter, that may be followed
- * by any amount of unicode letters or decimal numbers, or ASCII underscore.
- *
- * ES Form:
- * ```
- * /\p{Lowercase_Letter}[\p{Letter}\p{Decimal_Number}_]* /u;
- * ```
- *
- * @group API: Regexp
- */
-export const lowerId =
- /(?:[a-z\xB5\xDF-\xF6\xF8-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0560-\u0588\u10D0-\u10FA\u10FD-\u10FF\u13F8-\u13FD\u1C80-\u1C88\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD0-\u1FD3\u1FD6\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u210A\u210E\u210F\u2113\u212F\u2134\u2139\u213C\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7BB\uA7BD\uA7BF\uA7C3\uA7C8\uA7CA\uA7F6\uA7FA\uAB30-\uAB5A\uAB60-\uAB68\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A]|\uD801[\uDC28-\uDC4F\uDCD8-\uDCFB]|\uD803[\uDCC0-\uDCF2]|\uD806[\uDCC0-\uDCDF]|\uD81B[\uDE60-\uDE7F]|\uD835[\uDC1A-\uDC33\uDC4E-\uDC54\uDC56-\uDC67\uDC82-\uDC9B\uDCB6-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDCCF\uDCEA-\uDD03\uDD1E-\uDD37\uDD52-\uDD6B\uDD86-\uDD9F\uDDBA-\uDDD3\uDDEE-\uDE07\uDE22-\uDE3B\uDE56-\uDE6F\uDE8A-\uDEA5\uDEC2-\uDEDA\uDEDC-\uDEE1\uDEFC-\uDF14\uDF16-\uDF1B\uDF36-\uDF4E\uDF50-\uDF55\uDF70-\uDF88\uDF8A-\uDF8F\uDFAA-\uDFC2\uDFC4-\uDFC9\uDFCB]|\uD83A[\uDD22-\uDD43])(?:[0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BEF\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D66-\u0D6F\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F29\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDD30-\uDD39\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC66-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF39]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])*/;
-
-/**
- * Any word starting with a non upper, title or lowercase letter (that is, a letter
- * in a scripting that do not distinguishes between upper and lowercase forms),
- * that may be followed by any amount of unicode letters or decimal numbers, or ASCII underscore.
- *
- * ES Form:
- * ```
- * /\p{Other_Letter}[\p{Letter}\p{Decimal_Number}_]* /u;
- * ```
- *
- * @group API: Regexp
- */
-export const nonAlphabeticId =
- /(?:[\xAA\xBA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05EF-\u05F2\u0620-\u063F\u0641-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E45\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1100-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC50-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF4A\uDF50]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD838[\uDD00-\uDD2C\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])(?:[0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BEF\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D66-\u0D6F\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F29\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDD30-\uDD39\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC66-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF39]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])*/;
-
-/**
- * Any word starting with an underscore and followed by a non upper, title or lowercase
- * letter (that is, a letter in a scripting that do not distinguishes between upper and
- * lowercase forms), that may be followed by any amount of unicode letters or decimal
- * numbers, or ASCII underscore.
- *
- * ES Form:
- * ```
- * /_\p{Other_Letter}[\p{Letter}\p{Decimal_Number}_]* /u;
- * ```
- *
- * @group API: Regexp
- */
-export const sigiledNonAlphabeticId =
- /_(?:[\xAA\xBA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05EF-\u05F2\u0620-\u063F\u0641-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E45\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1100-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC50-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF4A\uDF50]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD838[\uDD00-\uDD2C\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])(?:[0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BEF\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D66-\u0D6F\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F29\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDD30-\uDD39\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC66-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF39]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])*/;
-
-/**
- * This helper matches any of the above identifiers, that is, anything that is a word.
- *
- * ES Form:
- * ```
- * /(\p{Letter}|_)[\p{Letter}\p{Decimal_Number}_]* /u;
- * ```
- *
- * @group API: Regexp
- */
-export const identifier =
- /((?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])|_)(?:[0-9A-Z_a-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BEF\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C66-\u0C6F\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D66-\u0D6F\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F29\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDD30-\uDD39\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFB0-\uDFC4\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC66-\uDC6F\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF39]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCE9\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])*/;
diff --git a/src/GobstonesLang/index.ts b/src/GobstonesLang/index.ts
deleted file mode 100644
index 0ec968c..0000000
--- a/src/GobstonesLang/index.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * This module provides the {@link Board} class, which models a Gobstones Board
- * and all the associated behavior.
- *
- * The {@link Board} class is expected to be used all through the Gobstones Platform
- * and all Gobstones plugins whenever a Board should be used (e.g. the
- * [gobstones-gbb-parser](https://github.com/gobstones/gobstones-gbb-parser)
- * returns a Board from this module)
- *
- * Toghether with such class it provides additional helper classes for it's behavior
- * such as {@link Cell}, {@link Color} and {@link Direction}, a set of error classes
- * that may occur when invalid arguments are given.
- *
- * This module also provides a set of types that identify the information of a board
- * and it's parts (cell locations, cell contents and others).
- * This types are used by the Gobstones Interpreter and the Gobstones GBB Parser,
- * and it's main type is implemented by the {@link Board} class. Yet, this
- * definitions are internal to Gobstones Projects, and their usage should
- * be avoided as most as possible. External projects such as plugins should
- * be avoided in favor of using the {@link Board} class.
- *
- * @module API.GobstonesLang
- * @author Alan Rodas Bonjour
- */
-
-export * from './Board';
-export * from './Cell';
-export * from './Color';
-export * from './Direction';
-export * from './BoardErrors';
-export * from './BoardDefinition';
diff --git a/src/History/Changeable.ts b/src/History/Changeable.ts
index db5264d..e9ab318 100644
--- a/src/History/Changeable.ts
+++ b/src/History/Changeable.ts
@@ -10,6 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
+/**
+ * @module History
+ * @author Pablo E. --Fidel-- Martínez López
+ */
+
/**
* A {@link Changeable} is a data structure used to register changes over a certain value
* of a given type.
diff --git a/src/History/Compactable.ts b/src/History/Compactable.ts
index 356f8ae..eef87bc 100644
--- a/src/History/Compactable.ts
+++ b/src/History/Compactable.ts
@@ -10,6 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
+/**
+ * @module History
+ * @author Pablo E. --Fidel-- Martínez López
+ */
+
/**
* A {@link Compactable} is a data structure that changes over time, and incorporates the possibility
* to compact all changes, leaving the structure as if the current value was used at creation.
diff --git a/src/History/History.ts b/src/History/History.ts
index e3eb04c..a66b54c 100644
--- a/src/History/History.ts
+++ b/src/History/History.ts
@@ -10,6 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
+/**
+ * @module History
+ * @author Pablo E. --Fidel-- Martínez López
+ */
+
import { Changeable } from './Changeable';
import { Compactable } from './Compactable';
import { Transactional } from './Transactional';
@@ -112,11 +118,12 @@ export class History implements Changeable, Compactable, Undoable, Tran
* the current version of it.
* Also transactions can be started and rolled back, and all changes can be compacted.
*
- * @param e the initial value of the history.
+ * @param e - the initial value of the history.
*/
public constructor(e: A) {
this._initializeWith(e);
}
+
// ----------------------------------------------------
// #endregion } API: Constructor
// ----------------------------------------------------
@@ -144,6 +151,7 @@ export class History implements Changeable, Compactable, Undoable, Tran
this._changes.splice(newSize, size - newSize);
}
}
+
// ----------------------------------------------------
// #endregion } API: Change management
// ----------------------------------------------------
@@ -206,6 +214,7 @@ export class History implements Changeable, Compactable, Undoable, Tran
public numRedos(): number {
return this._changes.length - this._currentValueIndex - 1;
}
+
// ----------------------------------------------------
// #endregion } Undoing operations
// ----------------------------------------------------
diff --git a/src/History/Transactional.ts b/src/History/Transactional.ts
index 2d10390..c21ac5d 100644
--- a/src/History/Transactional.ts
+++ b/src/History/Transactional.ts
@@ -10,6 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
+/**
+ * @module History
+ * @author Pablo E. --Fidel-- Martínez López
+ */
+
/**
* A {@link Transactional} is a data structure that changes over time, with the possibility
* to group changes and later rollback those groups of changes as a whole.
diff --git a/src/History/Undoable.ts b/src/History/Undoable.ts
index 1a199fc..8eda27c 100644
--- a/src/History/Undoable.ts
+++ b/src/History/Undoable.ts
@@ -10,6 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
+/**
+ * @module History
+ * @author Pablo E. --Fidel-- Martínez López
+ */
+
/**
* An {@link Undoable} is a data structure that changes over time, and incorporates the possibility
* to undo some changes and later redo them (if no other changing operation was done in between).
diff --git a/src/History/index.ts b/src/History/index.ts
index 868a709..1a15e89 100644
--- a/src/History/index.ts
+++ b/src/History/index.ts
@@ -10,6 +10,15 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
+/**
+ * This module provides a set of function, interfaces and classes that allow
+ * to manage an object through a history, that is, save it's state, allow to
+ * undo state transformations, redo them, and so on.
+ *
+ * @module History
+ * @author Pablo E. --Fidel-- Martínez López
+ */
export * from './History';
export * from './Changeable';
export * from './Compactable';
diff --git a/src/SourceReader/SourcePositions/AbstractDocumentSourcePosition.ts b/src/SourceReader/SourcePositions/AbstractDocumentSourcePosition.ts
index 2e0987f..4893e32 100644
--- a/src/SourceReader/SourcePositions/AbstractDocumentSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/AbstractDocumentSourcePosition.ts
@@ -10,17 +10,16 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { AbstractKnownSourcePosition } from './AbstractKnownSourcePosition';
import { SourceReader } from '../SourceReader';
-// ===============================================
-// #region AbstractDocumentSourcePosition {
-// -----------------------------------------------
/**
* An {@link AbstractDocumentSourcePosition} points to a particular position,
* that is well known, and belongs to a particular document.
@@ -42,40 +41,26 @@ import { SourceReader } from '../SourceReader';
* can answer, such as inquiring for the document name, and the contents
* of the document.
*
- * @group Internals: Source Positions
- * @private
+ * @privateRemarks
+ * Among the different operations provided in this class there are a few
+ * operations used to determine context of the source input surrounding
+ * the current position:
+ * {@link AbstractDocumentSourcePosition.documentContextBefore | documentContextBefore}, and
+ * {@link AbstractDocumentSourcePosition.documentContextAfter | documentContextAfter}.
+ * The implementation of all these is achieved by a
+ * [Template Method Pattern](https://en.wikipedia.org/wiki/Template_method_pattern)
+ * to provide a common validation and different logics depending on the actual subclass.
+ * Protected methods
+ * {@link SourceReader/SourcePositions.AbstractKnownSourcePosition._documentContextBefore | _documentContextBefore },
+ * and
+ * {@link SourceReader/SourcePositions.AbstractKnownSourcePosition._documentContextAfter | _documentContextAfter },
+ * are used to implement the aforementioned pattern.
*/
export abstract class AbstractDocumentSourcePosition extends AbstractKnownSourcePosition {
- // ===============================================
- // #region Implementation Details {
- // -----------------------------------------------
- /**
- * Among the different operations provided in this class there are a few
- * operations used to determine context of the source input surrounding
- * the current position:
- * {@link AbstractDocumentSourcePosition.documentContextBefore | documentContextBefore}, and
- * {@link AbstractDocumentSourcePosition.documentContextAfter | documentContextAfter}.
- * The implementation of all these is achieved by a
- * [Template Method Pattern](https://en.wikipedia.org/wiki/Template_method_pattern)
- * to provide a common validation and different logics depending on the actual subclass.
- * Protected methods
- * {@link AbstractKnownSourcePosition._documentContextBefore | _documentContextBefore },
- * and
- * {@link AbstractKnownSourcePosition._documentContextAfter | _documentContextAfter },
- * are used to implement the aforementioned pattern.
- *
- * @group Internal: Implementation Details
- * @private
- */
- // -----------------------------------------------
- // #endregion } Implementation Details
- // ===============================================
-
// ===============================================
// #region API: Properties {
// -----------------------------------------------
/**
- * @group API: Properties
* @inheritdoc
*/
public readonly isEndOfInput = false;
@@ -95,14 +80,14 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
* * all numbers are >= 0
* * numbers are consistent with the reader state
*
- * @param sourceReader The {@link SourceReader} of the input this position belongs to.
- * @param line The line number of this position in the current input.
+ * @param sourceReader - The {@link SourceReader} of the input this position belongs to.
+ * @param line - The line number of this position in the current input.
* It will be modified only by the constructor.
* **INVARIANT:** `line >=1`, and it is a valid line in that reader.
- * @param column The column number of this position in the current input.
+ * @param column - The column number of this position in the current input.
* It will be modified only by the constructor.
* **INVARIANT:** `column >= 1` and it is a valid column in that reader.
- * @param regions The regions the position in the current input belongs to.
+ * @param regions - The regions the position in the current input belongs to.
* It will be modified only by the constructor.
* **INVARIANT:** the regions are valid in the position's reader.
* @param _documentIndex The index with information about the input document
@@ -116,22 +101,15 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
* **INVARIANT:** `visibleCharIndex >= 0` and it is a valid index in
* that reader.
*
- * @group Internal: Constructors
* @private
*/
public constructor(
sourceReader: SourceReader,
- /** @group API: Access */
public readonly line: number,
- /** @group API: Access */
public readonly column: number,
- /** @group API: Access */
public readonly regions: string[],
- /** @group Internal: Properties @private */
public readonly _documentIndex: number,
- /** @group Internal: Properties @private */
public readonly _charIndex: number,
- /** @group Internal: Properties @private */
public readonly _visibleCharIndex: number
) {
super(sourceReader);
@@ -142,7 +120,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group API: Contents access
*/
public get fullDocumentContents(): string {
return this.sourceReader._fullDocumentContentsAt(this._documentIndex);
@@ -150,7 +127,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group API: Access
*/
public get documentName(): string {
return this.sourceReader._documentNameAt(this._documentIndex);
@@ -158,7 +134,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group API: Contents access
*/
public get visibleDocumentContents(): string {
return this.sourceReader._visibleDocumentContentsAt(this._documentIndex);
@@ -176,10 +151,8 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
* of {@link AbstractDocumentSourcePosition.documentContextBefore | documentContextBefore}.
* It must be reimplemented by subclasses.
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the at the end of input.
- *
- * @group Internal: Helpers
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the at the end of input.
*/
protected abstract _documentContextBefore(lines: number): string[];
@@ -194,10 +167,8 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
* of {@link AbstractDocumentSourcePosition.documentContextBefore | documentContextBefore}.
* It must be reimplemented by subclasses.
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the at the end of input.
- *
- * @group Internal: Helpers
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the at the end of input.
*/
protected abstract _documentContextAfter(lines: number): string[];
@@ -215,7 +186,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group API: Contents access
*/
public documentContextBefore(lines: number): string[] {
return this._documentContextBefore(lines);
@@ -223,7 +193,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group API: Contents access
*/
public documentContextAfter(lines: number): string[] {
return this._documentContextAfter(lines);
@@ -237,8 +206,7 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
// -----------------------------------------------
/**
* @inheritdoc
- * @group Internal: Helpers
- * @private
+ * @internal
*/
public _internalDocumentIndex(): number {
return this._documentIndex;
@@ -246,8 +214,7 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group Internal: Helpers
- * @private
+ * @internal
*/
public _internalCharacterIndex(visible: boolean): number {
return visible ? this._visibleCharIndex : this._charIndex;
@@ -255,7 +222,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group Internal: Helpers
*/
protected _fullContentsTo(to: AbstractKnownSourcePosition): string {
return this.sourceReader._inputFromToIn(
@@ -269,7 +235,6 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
/**
* @inheritdoc
- * @group Internal: Helpers
*/
protected _visibleContentsTo(to: AbstractKnownSourcePosition): string {
return this.sourceReader._inputFromToIn(
@@ -284,6 +249,3 @@ export abstract class AbstractDocumentSourcePosition extends AbstractKnownSource
// #endregion } Internal: Helpers
// ===============================================
}
-// -----------------------------------------------
-// #endregion } AbstractDocumentSourcePosition
-// ===============================================
diff --git a/src/SourceReader/SourcePositions/AbstractKnownSourcePosition.ts b/src/SourceReader/SourcePositions/AbstractKnownSourcePosition.ts
index ecdcd94..b648540 100644
--- a/src/SourceReader/SourcePositions/AbstractKnownSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/AbstractKnownSourcePosition.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
@@ -22,9 +23,6 @@ import { expect } from '../../Expectations';
import { SourceReader } from '../SourceReader';
import { InvalidOperationAtUnknownPositionError, MismatchedInputsError } from '../SourceReaderErrors';
-// ===============================================
-// #region AbstractKnownSourcePosition {
-// -----------------------------------------------
/**
* A {@link AbstractKnownSourcePosition} points to a position in a specific
* {@link SourceReader}. It should only be created using the
@@ -43,9 +41,6 @@ import { InvalidOperationAtUnknownPositionError, MismatchedInputsError } from '.
* As all instances of {@link AbstractKnownSourcePosition} represent a known
* position, they may be queried to obtain the line, column, regions and
* surrounding contents.
- *
- * @group Internals: Source Positions
- * @private
*/
export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition {
// ===============================================
@@ -71,7 +66,6 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* {@link AbstractKnownSourcePosition._fullContentsFrom | _fullContentsFrom },
* are used to implement the aforementioned pattern.
*
- * @group Internal: Implementation Details
* @private
*/
// -----------------------------------------------
@@ -83,13 +77,11 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Properties
*/
public abstract readonly isEndOfInput: boolean;
/**
* @inheritdoc
- * @group API: Properties
*/
public readonly isUnknown = false;
@@ -108,15 +100,9 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* * all numbers are >= 0
* * numbers are consistent with the reader's state
*
- * @param sourceReader The {@link SourceReader} of the input this position belongs to.
- *
- * @group Internal: Constructors
- * @private
+ * @param sourceReader - The {@link SourceReader} of the input this position belongs to.
*/
- public constructor(
- /** @group API: Access */
- public readonly sourceReader: SourceReader
- ) {
+ public constructor(public readonly sourceReader: SourceReader) {
super();
}
// -----------------------------------------------
@@ -131,8 +117,7 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* corresponds is stored.
* It may be one longer that the lenght, in case the position is EOI.
*
- * @group Internal: Helpers
- * @private
+ * @internal
*/
public abstract _internalDocumentIndex(): number;
@@ -141,8 +126,7 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* character which this positions corresponds to is stored.
* It may be one longer thant the lenght, in case the position is EOD.
*
- * @group Internal: Helpers
- * @private
+ * @internal
*/
public abstract _internalCharacterIndex(visible: boolean): number;
@@ -159,12 +143,10 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* **PRECONDITION:** both positions correspond to the same reader (not
* validated, as it is a protected operation).
*
- * @param to A {@link AbstractKnownSourcePosition} related with the same
+ * @param to - A {@link AbstractKnownSourcePosition} related with the same
* {@link SourceReader} that the receiver.
* It indicates a final position to consult (not included),
* where the receiver is the first.
- *
- * @group Internal: Helpers
*/
protected abstract _fullContentsTo(to: AbstractKnownSourcePosition): string;
@@ -181,18 +163,15 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* **PRECONDITION:** both positions correspond to the same reader (not
* validated, as it is a protected operation).
*
- * @param to A {@link AbstractKnownSourcePosition} related with the same
+ * @param to - A {@link AbstractKnownSourcePosition} related with the same
* {@link SourceReader} that the receiver.
* It indicates the final position to consult (not included),
* where the receiver is the first.
- *
- * @group Internal: Helpers
*/
protected abstract _visibleContentsTo(to: AbstractKnownSourcePosition): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public fullContentsFrom(from: SourcePosition): string {
this._validateSourceReaders(from, 'fullContentsFrom', 'AbstractKnownSourcePosition');
@@ -201,7 +180,6 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
/**
* @inheritdoc
- * @group API: Contents access
*/
public fullContentsTo(to: SourcePosition): string {
this._validateSourceReaders(to, 'fullContentsTo', 'AbstractKnownSourcePosition');
@@ -210,7 +188,6 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
/**
* @inheritdoc
- * @group API: Contents access
*/
public visibleContentsTo(to: SourcePosition): string {
this._validateSourceReaders(to, 'visibleContentsTo', 'AbstractKnownSourcePosition');
@@ -219,7 +196,6 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
/**
* @inheritdoc
- * @group API: Contents access
*/
public visibleContentsFrom(from: SourcePosition): string {
this._validateSourceReaders(from, 'visibleContentsFrom', 'AbstractKnownSourcePosition');
@@ -239,12 +215,10 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
*
* Implements a common validation for the Template Method Pattern.
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver or the argument positions are unknown.
- * @throws {@link MismatchedInputsError}
+ * @throws {@link SourceReader/Errors.MismatchedInputsError}
* if the receiver and the argument positions do not belong to the same reader.
- *
- * @group Internal: Helpers
*/
protected _validateSourceReaders(that: SourcePosition, operation: string, context: string): void {
expect(that.isUnknown).toBeFalse().orThrow(new InvalidOperationAtUnknownPositionError(operation, context));
@@ -267,12 +241,10 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* * both positions correspond to the same reader
* (not validated, as it is a protected operation).
*
- * @param from An {@link AbstractKnownSourcePosition} related with the same
+ * @param from - An {@link AbstractKnownSourcePosition} related with the same
* {@link SourceReader} that the receiver.
* It indicates the starting position to consult,
* where the receiver is the last (not included).
- *
- * @group Internal: Helpers
*/
protected _fullContentsFrom(from: AbstractKnownSourcePosition): string {
return this.sourceReader._inputFromToIn(
@@ -297,12 +269,10 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
* **PRECONDITION:** both positions correspond to the same reader (not
* validated, as it is a protected operation).
*
- * @param from A {@link AbstractKnownSourcePosition} related with the same
- * {@link SourceReader} that the receiver.
+ * @param from - A {@link AbstractKnownSourcePosition} related with the same
+ * {@link SourceReader.SourceReader} that the receiver.
* It indicates the starting position to consult,
* where the receiver is the last (not included).
- *
- * @group Internal: Helpers
*/
protected _visibleContentsFrom(from: AbstractKnownSourcePosition): string {
return this.sourceReader._inputFromToIn(
@@ -317,6 +287,3 @@ export abstract class AbstractKnownSourcePosition extends AbstractSourcePosition
// #endregion } Internal: Helpers
// ===============================================
}
-// -----------------------------------------------
-// #endregion } AbstractKnownSourcePosition
-// ===============================================
diff --git a/src/SourceReader/SourcePositions/AbstractSourcePosition.ts b/src/SourceReader/SourcePositions/AbstractSourcePosition.ts
index 3f188f3..ae53a26 100644
--- a/src/SourceReader/SourcePositions/AbstractSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/AbstractSourcePosition.ts
@@ -10,10 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { SourcePosition } from './SourcePosition';
/**
@@ -21,98 +23,70 @@ import { SourcePosition } from './SourcePosition';
* its purpose is to be the top of the hierarchy of different kinds of positions.
* Subclasses determine if the position is unknown or known, and in this last case,
* its different types.
- *
- * @group Internals: Source Positions
- * @private
*/
export abstract class AbstractSourcePosition implements SourcePosition {
- /**
- * @group Internal: Constructors
- * @private
- */
- // This empty declaration is needed for its documentation.
- // If the documentation does not appear, it takes the default (public, Constructor)
- // instead of the same as all the others in the hierarchy.
- // eslint-disable-next-line @typescript-eslint/no-empty-function
- public constructor() {}
/**
* @inheritdoc
- * @group API: Properties
*/
public abstract get isUnknown(): boolean;
/**
* @inheritdoc
- * @group API: Properties
*/
public abstract get isEndOfInput(): boolean;
/**
* @inheritdoc
- * @group API: Properties
*/
public abstract get isEndOfDocument(): boolean;
/**
* @inheritdoc
- * @group API: Access
*/
public abstract get line(): number;
/**
* @inheritdoc
- * @group API: Access
*/
public abstract get column(): number;
/**
* @inheritdoc
- * @group API: Access
*/
public abstract get regions(): string[];
/**
* @inheritdoc
- * @group API: Access
*/
public abstract get documentName(): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract get fullDocumentContents(): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract get visibleDocumentContents(): string;
/**
* @inheritdoc
- * @group API: Printing
*/
public abstract toString(): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract fullContentsFrom(from: SourcePosition): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract fullContentsTo(from: SourcePosition): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract visibleContentsFrom(from: SourcePosition): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract visibleContentsTo(to: SourcePosition): string;
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract documentContextBefore(lines: number): string[];
/**
* @inheritdoc
- * @group API: Contents access
*/
public abstract documentContextAfter(lines: number): string[];
}
diff --git a/src/SourceReader/SourcePositions/DocumentSourcePosition.ts b/src/SourceReader/SourcePositions/DocumentSourcePosition.ts
index 97ffd39..0dfa9fd 100644
--- a/src/SourceReader/SourcePositions/DocumentSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/DocumentSourcePosition.ts
@@ -10,41 +10,27 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { AbstractDocumentSourcePosition } from './AbstractDocumentSourcePosition';
import { SourcePosition } from './SourcePosition';
import { SourceReader } from '../SourceReader';
-// ===============================================
-// #region DocumentSourcePosition {
-// -----------------------------------------------
/**
* A {@link DocumentSourcePosition} points to a particular position, different
* from EndOfDocument, inside a particular document.
- *
- * @group Internals: Source Positions
- * @private
*/
export class DocumentSourcePosition extends AbstractDocumentSourcePosition implements SourcePosition {
- // ===============================================
- // #region API: Properties {
- // -----------------------------------------------
/**
* @inheritdoc
- * @group API: Properties
*/
public readonly isEndOfDocument: boolean = false;
- // -----------------------------------------------
- // #endregion } API: Properties
- // ===============================================
- // ===============================================
- // #region Internal: Constructors {
- // -----------------------------------------------
/**
* Constructs a defined position different from the end of a document in an
* input source.
@@ -53,8 +39,6 @@ export class DocumentSourcePosition extends AbstractDocumentSourcePosition imple
* **PRECONDITIONS:** (not verified during execution)
* * all numbers are >= 0
* * numbers are consistent with the reader state
- * @group Internal: Constructors
- * @private
*/
public constructor(
sourceReader: SourceReader,
@@ -67,16 +51,9 @@ export class DocumentSourcePosition extends AbstractDocumentSourcePosition imple
) {
super(sourceReader, line, column, regions, documentIndex, charIndex, visibleCharIndex);
}
- // -----------------------------------------------
- // #endregion } Internal: Constructors
- // ===============================================
- // ===============================================
- // #region API: Printing {
- // -----------------------------------------------
/**
* @inheritdoc
- * @group API: Printing
*/
public toString(): string {
// if (
@@ -89,16 +66,9 @@ export class DocumentSourcePosition extends AbstractDocumentSourcePosition imple
// }
return `@<${this.documentName}:${this.line},${this.column}>`;
}
- // -----------------------------------------------
- // #endregion } API: Printing
- // ===============================================
- // ===============================================
- // #region Internal: Helpers {
- // -----------------------------------------------
/**
* @inheritdoc
- * @group Internal: Helpers
*/
protected _documentContextBefore(lines: number): string[] {
return this.sourceReader._documentContextBeforeOf(
@@ -110,7 +80,6 @@ export class DocumentSourcePosition extends AbstractDocumentSourcePosition imple
/**
* @inheritdoc
- * @group Internal: Helpers
*/
protected _documentContextAfter(lines: number): string[] {
return this.sourceReader._documentContextAfterOf(
@@ -119,10 +88,4 @@ export class DocumentSourcePosition extends AbstractDocumentSourcePosition imple
lines
);
}
- // -----------------------------------------------
- // #endregion } Internal: Helpers
- // ===============================================
}
-// -----------------------------------------------
-// #endregion } EndOfDocumentSourcePosition
-// ===============================================
diff --git a/src/SourceReader/SourcePositions/EndOfDocumentSourcePosition.ts b/src/SourceReader/SourcePositions/EndOfDocumentSourcePosition.ts
index 15c0335..51ae1a5 100644
--- a/src/SourceReader/SourcePositions/EndOfDocumentSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/EndOfDocumentSourcePosition.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
import { AbstractDocumentSourcePosition } from './AbstractDocumentSourcePosition';
@@ -19,9 +20,6 @@ import { SourcePosition } from './SourcePosition';
import { SourceReader } from '../SourceReader';
-// ===============================================
-// #region EndOfDocumentSourcePosition {
-// -----------------------------------------------
/**
* An {@link EndOfDocumentSourcePosition} points to a position that is right
* after the last character in a specific document of a {@link SourceReader}.
@@ -30,26 +28,13 @@ import { SourceReader } from '../SourceReader';
* next document.
* It is a special position, because it does not point to a particular position
* inside a document in the source input, but to the end of one of the documents in it.
- *
- * @group Internals: Source Positions
- * @private
*/
export class EndOfDocumentSourcePosition extends AbstractDocumentSourcePosition implements SourcePosition {
- // ===============================================
- // #region API: Properties {
- // -----------------------------------------------
/**
* @inheritdoc
- * @group API: Properties
*/
public readonly isEndOfDocument: boolean = true;
- // -----------------------------------------------
- // #endregion } API: Properties
- // ===============================================
- // ===============================================
- // #region Internal: Constructors {
- // -----------------------------------------------
/**
* Constructs an end of document position in an input source.
* It is intended to be used only by {@link SourceReader}.
@@ -58,29 +43,26 @@ export class EndOfDocumentSourcePosition extends AbstractDocumentSourcePosition
* * all numbers are >= 0
* * numbers are consistent with the reader state
*
- * @param sourceReader The {@link SourceReader} of the input this position belongs to.
- * @param line The line number of this position in the current input.
+ * @param sourceReader - The {@link SourceReader} of the input this position belongs to.
+ * @param line - The line number of this position in the current input.
* It will be modified only by the constructor.
* **INVARIANT:** `line >=1`, and it is a valid line in that reader.
- * @param column The column number of this position in the current input.
+ * @param column - The column number of this position in the current input.
* It will be modified only by the constructor.
* **INVARIANT:** `column >= 1` and it is a valid column in that reader.
- * @param regions The regions the position in the current input belongs to.
+ * @param regions - The regions the position in the current input belongs to.
* It will be modified only by the constructor.
* **INVARIANT:** the regions are valid in the position's reader.
- * @param documentIndex The index with information about the input document
+ * @param documentIndex - The index with information about the input document
* in the `_sourceReader`. **INVARIANT**: `documentIndex >= 0` and it
* is a valid index in that reader.
- * @param charIndex The index with information about the exact char pointed
+ * @param charIndex - The index with information about the exact char pointed
* to by this position in the input document. **INVARIANT:**
* `charIndex >= 0` and it is a valid index in that reader.
- * @param visibleCharIndex The index with information about the exact char
+ * @param visibleCharIndex - The index with information about the exact char
* pointed to by this position in the visible input document.
* **INVARIANT:** `visibleCharIndex >= 0` and it is a valid index in
* that reader.
- *
- * @group Internal: Contructors
- * @private
*/
public constructor(
sourceReader: SourceReader,
@@ -93,30 +75,16 @@ export class EndOfDocumentSourcePosition extends AbstractDocumentSourcePosition
) {
super(sourceReader, line, column, regions, documentIndex, charIndex, visibleCharIndex);
}
- // -----------------------------------------------
- // #endregion } Internal: Constructors
- // ===============================================
- // ===============================================
- // #region API: Printing {
- // -----------------------------------------------
/**
* @inheritdoc
- * @group API: Printing
*/
public toString(): string {
return '@';
}
- // -----------------------------------------------
- // #endregion } API: Printing
- // ===============================================
- // ===============================================
- // #region Internal: Helpers {
- // -----------------------------------------------
/**
* @inheritdoc
- * @group Internal: Helpers
*/
protected _documentContextBefore(lines: number): string[] {
return this.sourceReader._documentContextBeforeOf(
@@ -128,15 +96,8 @@ export class EndOfDocumentSourcePosition extends AbstractDocumentSourcePosition
/**
* @inheritdoc
- * @group Internal: Helpers
*/
- protected _documentContextAfter(lines: number): string[] {
+ protected _documentContextAfter(_lines: number): string[] {
return [''];
}
- // -----------------------------------------------
- // #endregion } Internal: Helpers
- // ===============================================
}
-// -----------------------------------------------
-// #endregion } EndOfDocumentSourcePosition
-// ===============================================
diff --git a/src/SourceReader/SourcePositions/EndOfInputSourcePosition.ts b/src/SourceReader/SourcePositions/EndOfInputSourcePosition.ts
index 5b79219..dec9481 100644
--- a/src/SourceReader/SourcePositions/EndOfInputSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/EndOfInputSourcePosition.ts
@@ -10,10 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { AbstractKnownSourcePosition } from './AbstractKnownSourcePosition';
import { SourcePosition } from './SourcePosition';
@@ -26,9 +28,6 @@ import { InvalidOperationAtEOIError } from '../SourceReaderErrors';
* That position is reached when all input documents have been processed.
* It is a special position, because it does not point to a particular position
* inside a document in the source input, but to the end of it.
- *
- * @group Internals: Source Positions
- * @private
*/
export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implements SourcePosition {
// ===============================================
@@ -54,9 +53,7 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
* * all numbers are >= 0
* * numbers are consistent with the reader state
*
- * @param sourceReader The {@link SourceReader} of the input this position belongs to.
- * @group Internal: Constructors
- * @private
+ * @param sourceReader - The {@link SourceReader} of the input this position belongs to.
*/
public constructor(sourceReader: SourceReader) {
super(sourceReader);
@@ -70,7 +67,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Properties
*/
public get isEndOfDocument(): boolean {
throw new InvalidOperationAtEOIError('isEndOfDocument', 'EndOfInputSourcePosition');
@@ -84,7 +80,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Access
*/
public get line(): number {
throw new InvalidOperationAtEOIError('line', 'EndOfInputSourcePosition');
@@ -92,7 +87,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
/**
* @inheritdoc
- * @group API: Access
*/
public get column(): number {
throw new InvalidOperationAtEOIError('column', 'EndOfInputSourcePosition');
@@ -100,7 +94,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
/**
* @inheritdoc
- * @group API: Access
*/
public get regions(): string[] {
throw new InvalidOperationAtEOIError('regions', 'EndOfInputSourcePosition');
@@ -108,7 +101,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
/**
* @inheritdoc
- * @group API: Access
*/
public get documentName(): string {
throw new InvalidOperationAtEOIError('documentName', 'EndOfInputSourcePosition');
@@ -122,7 +114,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Contents access
*/
public get fullDocumentContents(): string {
throw new InvalidOperationAtEOIError('fullDocumentContents', 'EndOfInputSourcePosition');
@@ -130,7 +121,6 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
/**
* @inheritdoc
- * @group API: Contents access
*/
public get visibleDocumentContents(): string {
throw new InvalidOperationAtEOIError('visibleDocumentContents', 'EndOfInputSourcePosition');
@@ -138,17 +128,15 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
/**
* @inheritdoc
- * @group API: Contents access
*/
- public documentContextBefore(lines: number): string[] {
+ public documentContextBefore(_lines: number): string[] {
throw new InvalidOperationAtEOIError('documentContextBefore', 'EndOfInputSourcePosition');
}
/**
* @inheritdoc
- * @group API: Contents access
*/
- public documentContextAfter(lines: number): string[] {
+ public documentContextAfter(_lines: number): string[] {
throw new InvalidOperationAtEOIError('documentContextAfter', 'EndOfInputSourcePosition');
}
// -----------------------------------------------
@@ -160,22 +148,17 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Printing
*/
public toString(): string {
return '@';
}
- // -----------------------------------------------
- // #endregion } API: Printing
- // ===============================================
// ===============================================
// #region Internal: Helpers {
// -----------------------------------------------
/**
* @inheritdoc
- * @group Internal: Helpers
- * @private
+ * @internal
*/
public _internalDocumentIndex(): number {
return this.sourceReader.documentsNames.length - 1;
@@ -183,26 +166,23 @@ export class EndOfInputSourcePosition extends AbstractKnownSourcePosition implem
/**
* @inheritdoc
- * @group Internal: Helpers
- * @private
+ * @internal
*/
- public _internalCharacterIndex(visible: boolean): number {
+ public _internalCharacterIndex(_visible: boolean): number {
return this.sourceReader._fullDocumentContentsAt(this._internalDocumentIndex()).length;
}
/**
* @inheritdoc
- * @group Internal: Helpers
*/
- protected _fullContentsTo(to: AbstractKnownSourcePosition): string {
+ protected _fullContentsTo(_to: AbstractKnownSourcePosition): string {
return '';
}
/**
* @inheritdoc
- * @group Internal: Helpers
*/
- protected _visibleContentsTo(to: AbstractKnownSourcePosition): string {
+ protected _visibleContentsTo(_to: AbstractKnownSourcePosition): string {
return '';
}
// -----------------------------------------------
diff --git a/src/SourceReader/SourcePositions/SourcePosition.ts b/src/SourceReader/SourcePositions/SourcePosition.ts
index ea9e475..3821c0a 100644
--- a/src/SourceReader/SourcePositions/SourcePosition.ts
+++ b/src/SourceReader/SourcePositions/SourcePosition.ts
@@ -10,23 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
-// These imports are needed for typedoc to find the references
-import {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- InvalidOperationAtUnknownPositionError,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- InvalidOperationAtEOIError,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- MismatchedInputsError
-} from '../SourceReaderErrors';
-// ===============================================
-// #region SourcePosition {
-// -----------------------------------------------
/**
* {@link SourcePosition}s point to particular positions in the source given by a
* {@link SourceReader}.
@@ -44,7 +33,6 @@ import {
* A typical use of {@link SourcePosition}s is relating nodes of an AST
* representation of code to particular positions in the string version of the
* source code (that may come from several input documents).
- * @group API: Main
*/
export interface SourcePosition {
// ===============================================
@@ -53,8 +41,6 @@ export interface SourcePosition {
/**
* Answers if this position correspond to one in some {@link SourceReader},
* or if it is unknown.
- *
- * @group API: Properties
*/
readonly isUnknown: boolean;
@@ -66,9 +52,7 @@ export interface SourcePosition {
* **PRECONDITIONS:**
* * the position is known
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- *
- * @group API: Properties
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
*/
readonly isEndOfInput: boolean;
@@ -83,10 +67,8 @@ export interface SourcePosition {
* * the position is not unknown
* * the position is not at the end of input
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Properties
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
readonly isEndOfDocument: boolean;
// -----------------------------------------------
@@ -103,10 +85,8 @@ export interface SourcePosition {
* * the position is not unknown
* * the position is not at the end of input
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Access
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
readonly documentName: string;
@@ -119,10 +99,8 @@ export interface SourcePosition {
*
* **INVARIANT:** `line >=1`, and it is a valid line in that reader.
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Access
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
readonly line: number;
@@ -134,10 +112,8 @@ export interface SourcePosition {
* * the position is not at the end of input
*
* **INVARIANT:** `column >= 1` and it is a valid column in that reader.
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Access
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
readonly column: number;
@@ -149,10 +125,8 @@ export interface SourcePosition {
* * the position is not at the end of input
*
* **INVARIANT:** the regions are valid in the position's reader.
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Access
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
readonly regions: string[];
// -----------------------------------------------
@@ -170,12 +144,10 @@ export interface SourcePosition {
* * the position is not unknown
* * the position is not at the end of input
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver is unknown.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the receiver is the end of input.
- *
- * @group API: Contents access
*/
readonly fullDocumentContents: string;
@@ -186,12 +158,10 @@ export interface SourcePosition {
* * the position is not unknown
* * the position is not at the end of input
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver is unknown.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the receiver is the end of input.
- *
- * @group API: Contents access
*/
readonly visibleDocumentContents: string;
@@ -206,19 +176,17 @@ export interface SourcePosition {
* * both positions correspond to the same reader
* * the receiver is not at the end of input
*
- * @param from
+ * @param from -
* A {@link SourcePosition} related with the same {@link SourceReader}
* that the receiver.
* It indicates a starting position to consult, where the receiver is the last.
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver or the argument positions are unknown.
- * @throws {@link MismatchedInputsError}
+ * @throws {@link SourceReader/Errors.MismatchedInputsError}
* if the receiver and the argument positions do not belong to the same reader.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the receiver is the end of input.
- *
- * @group API: Contents access
*/
fullContentsFrom(from: SourcePosition): string;
@@ -232,19 +200,17 @@ export interface SourcePosition {
* * both positions correspond to the same reader
* * the receiver is not at the end of input
*
- * @param to
+ * @param to -
* A {@link SourcePosition} related with the same {@link SourceReader} that
* the receiver.
* It indicates a final position to consult, where the receiver is the first.
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver or the argument positions are unknown.
- * @throws {@link MismatchedInputsError}
+ * @throws {@link SourceReader/Errors.MismatchedInputsError}
* if the receiver and the argument positions do not belong to the same reader.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the receiver is the end of input.
- *
- * @group API: Contents access
*/
fullContentsTo(to: SourcePosition): string;
@@ -258,19 +224,17 @@ export interface SourcePosition {
* * both positions correspond to the same reader
* * the receiver is not at the end of input
*
- * @param from
+ * @param from -
* A {@link SourcePosition} related with the same {@link SourceReader} that
* the receiver.
* It indicates a starting position to consult, where the receiver is the last.
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver or the argument positions are unknown.
- * @throws {@link MismatchedInputsError}
+ * @throws {@link SourceReader/Errors.MismatchedInputsError}
* if the receiver and the argument positions do not belong to the same reader.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the receiver is the end of input.
- *
- * @group API: Contents access
*/
visibleContentsFrom(from: SourcePosition): string;
@@ -284,19 +248,17 @@ export interface SourcePosition {
* * both positions correspond to the same reader
* * the receiver is not at the end of input
*
- * @param to
+ * @param to -
* A {@link SourcePosition} related with the same {@link SourceReader} that
* the receiver.
* It indicates a final position to consult, where the receiver is the first.
*
- * @throws {@link InvalidOperationAtUnknownPositionError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError}
* if the receiver or the argument positions are unknown.
- * @throws {@link MismatchedInputsError}
+ * @throws {@link SourceReader/Errors.MismatchedInputsError}
* if the receiver and the argument positions do not belong to the same reader.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the receiver is the end of input.
- *
- * @group API: Contents access
*/
visibleContentsTo(to: SourcePosition): string;
@@ -310,10 +272,8 @@ export interface SourcePosition {
* * the position is not unknown
* * the position is not at the end of input
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Contents access
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
documentContextBefore(lines: number): string[];
@@ -327,10 +287,8 @@ export interface SourcePosition {
* * the position is not unknown
* * the position is not at the end of input
*
- * @throws {@link InvalidOperationAtUnknownPositionError} if the position is unknown.
- * @throws {@link InvalidOperationAtEOIError} if the position is at the end of input.
- *
- * @group API: Contents access
+ * @throws {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} if the position is unknown.
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError} if the position is at the end of input.
*/
documentContextAfter(lines: number): string[];
// -----------------------------------------------
@@ -343,14 +301,9 @@ export interface SourcePosition {
/**
* Gives a string representation of the position.
* It is NOT useful for persistence, as it may loose information.
- *
- * @group API: Printing
*/
toString(): string;
// -----------------------------------------------
// #endregion } API: Printing
// ===============================================
}
-// -----------------------------------------------
-// #endregion } SourcePosition
-// ===============================================
diff --git a/src/SourceReader/SourcePositions/SourcePositions.ts b/src/SourceReader/SourcePositions/SourcePositions.ts
index 242255c..577692d 100644
--- a/src/SourceReader/SourcePositions/SourcePositions.ts
+++ b/src/SourceReader/SourcePositions/SourcePositions.ts
@@ -10,10 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { DocumentSourcePosition } from './DocumentSourcePosition';
import { EndOfDocumentSourcePosition } from './EndOfDocumentSourcePosition';
import { EndOfInputSourcePosition } from './EndOfInputSourcePosition';
@@ -25,9 +27,6 @@ import { SourceReader } from '../SourceReader';
* The constant implementing the
* [Abstract Factory Pattern](https://en.wikipedia.org/wiki/Abstract_factory_pattern)
* for {@link SourcePosition}s.
- *
- * @group Internal: Main
- * @private
*/
export const SourcePositions = {
Unknown: () => UnknownSourcePosition.instance,
diff --git a/src/SourceReader/SourcePositions/SourceSpan.ts b/src/SourceReader/SourcePositions/SourceSpan.ts
index d6d9e56..ad3e0f8 100644
--- a/src/SourceReader/SourcePositions/SourceSpan.ts
+++ b/src/SourceReader/SourcePositions/SourceSpan.ts
@@ -10,51 +10,39 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { SourcePosition } from './SourcePosition';
import { SourcePositions } from './SourcePositions';
/**
- * A {@link SourceSpan} delimitates a span in a {@link SourceInput}.
+ * A {@link SourceSpan} delimitates a span in a {@link SourceReader.SourceInput}.
* To do that, it has {@link SourceSpan.start | start} and {@link SourceSpan.end | end} positions, indicating
* where the span of input starts and ends, respectively.
*
* **REPRESENTATION INVARIANT: (not verified)**
* * both start and end positions belongs to the same {@link SourceReader}
* * start position appears before end position, if both of them are not Unkwnown.
- * @group API: Main
+ *
+ * @privateRemarks
+ * Properties {@link SourceSpan.start | start} and {@link SourceSpan.end | end} indicate
+ * where the span of input starts and ends, respectively.
+ * If the span only spans over 1 characters, the end position may not be specified.
+ * If the start position is unknown, the end position should also be unknown.
+ * Those conditions are guaranteed on construction.
*/
export class SourceSpan {
- // ===============================================
- // #region Implementation Details {
- // -----------------------------------------------
- /**
- * Properties {@link SourceSpan.start | start} and {@link SourceSpan.end | end} indicate
- * where the span of input starts and ends, respectively.
- * If the span only spans over 1 characters, the end position may not be specified.
- * If the start position is unknown, the end position should also be unknown.
- * Those conditions are guaranteed on construction.
- * @group Implementation Details
- * @private
- */
- // -----------------------------------------------
- // #endregion } Implementation Details
- // ===============================================
-
- // ===============================================
- // #region API {
- // -----------------------------------------------
/**
* The start position of the span.
- * @group API
*/
public readonly start: SourcePosition = SourcePositions.Unknown();
+
/**
* The end position of the span.
- * @group API
*/
public readonly end: SourcePosition = SourcePositions.Unknown();
@@ -64,13 +52,9 @@ export class SourceSpan {
* If end is unknown but not the start, they are made equal (the span is a single position).
* If start is unknown but not the end, the end is considered an incorrect value,
* and made unknown.
- * @group API
*/
public constructor(start?: SourcePosition, end?: SourcePosition) {
this.start = start ?? SourcePositions.Unknown();
- this.end = start ? end ?? this.start : this.start;
+ this.end = start ? (end ?? this.start) : this.start;
}
- // -----------------------------------------------
- // #endregion } Implementation Details
- // ===============================================
}
diff --git a/src/SourceReader/SourcePositions/UnknownSourcePosition.ts b/src/SourceReader/SourcePositions/UnknownSourcePosition.ts
index b3f90c2..be94944 100644
--- a/src/SourceReader/SourcePositions/UnknownSourcePosition.ts
+++ b/src/SourceReader/SourcePositions/UnknownSourcePosition.ts
@@ -10,18 +10,17 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
*/
+
import { AbstractSourcePosition } from './AbstractSourcePosition';
import { SourcePosition } from './SourcePosition';
import { InvalidOperationAtUnknownPositionError } from '../SourceReaderErrors';
-// ===============================================
-// #region UnknownSourcePosition {
-// -----------------------------------------------
/**
* An {@link UnknownSourcePosition} represents an unknown source position,
* that is, it does not point to any position in any source reader.
@@ -37,9 +36,6 @@ import { InvalidOperationAtUnknownPositionError } from '../SourceReaderErrors';
* This class has a single instance, accessible through the
* {@link UnknownSourcePosition.instance | instance} static field,
* and cannot be further instantiated.
- *
- * @group Internals: Source Positions
- * @private
*/
export class UnknownSourcePosition extends AbstractSourcePosition implements SourcePosition {
// ===============================================
@@ -47,8 +43,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// -----------------------------------------------
/**
* Returns the single instance of this class.
- * @group Internal: Constructors
- * @private
*/
public static readonly instance = new UnknownSourcePosition();
// -----------------------------------------------
@@ -60,7 +54,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Properties
*/
public readonly isUnknown: boolean = true;
// -----------------------------------------------
@@ -73,9 +66,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
/**
* Returns an instance of this class.
* Made private to follow the singleton pattern.
- *
- * @group Internal: Constructors
- * @private
*/
private constructor() {
super();
@@ -89,7 +79,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Properties
*/
public get isEndOfInput(): boolean {
throw new InvalidOperationAtUnknownPositionError('isEndOfInput', 'UnknownSourcePosition');
@@ -97,7 +86,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
/**
* @inheritdoc
- * @group API: Properties
*/
public get isEndOfDocument(): boolean {
throw new InvalidOperationAtUnknownPositionError('isEndOfDocument', 'UnknownSourcePosition');
@@ -111,7 +99,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Access
*/
public get line(): number {
throw new InvalidOperationAtUnknownPositionError('line', 'UnknownSourcePosition');
@@ -119,7 +106,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
/**
* @inheritdoc
- * @group API: Access
*/
public get column(): number {
throw new InvalidOperationAtUnknownPositionError('column', 'UnknownSourcePosition');
@@ -135,7 +121,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
/**
* @inheritdoc
- * @group API: Access
*/
public get documentName(): string {
throw new InvalidOperationAtUnknownPositionError('documentName', 'UnknownSourcePosition');
@@ -149,7 +134,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Content access
*/
public get fullDocumentContents(): string {
throw new InvalidOperationAtUnknownPositionError('fullDocumentContents', 'UnknownSourcePosition');
@@ -157,7 +141,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
/**
* @inheritdoc
- * @group API: Content access
*/
public get visibleDocumentContents(): string {
throw new InvalidOperationAtUnknownPositionError('visibleDocumentContents', 'UnknownSourcePosition');
@@ -165,49 +148,43 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
/**
* @inheritdoc
- * @group API: Content access
*/
- public fullContentsFrom(from: SourcePosition): string {
+ public fullContentsFrom(_from: SourcePosition): string {
throw new InvalidOperationAtUnknownPositionError('fullContentsFrom', 'UnknownSourcePosition');
}
/**
* @inheritdoc
- * @group API: Content access
*/
- public fullContentsTo(from: SourcePosition): string {
+ public fullContentsTo(_from: SourcePosition): string {
throw new InvalidOperationAtUnknownPositionError('fullContentsTo', 'UnknownSourcePosition');
}
/**
* @inheritdoc
- * @group API: Content access
*/
- public visibleContentsFrom(from: SourcePosition): string {
+ public visibleContentsFrom(_from: SourcePosition): string {
throw new InvalidOperationAtUnknownPositionError('visibleContentsFrom', 'UnknownSourcePosition');
}
/**
* @inheritdoc
- * @group API: Content access
*/
- public visibleContentsTo(from: SourcePosition): string {
+ public visibleContentsTo(_from: SourcePosition): string {
throw new InvalidOperationAtUnknownPositionError('visibleContentsTo', 'UnknownSourcePosition');
}
/**
* @inheritdoc
- * @group API: Content access
*/
- public documentContextBefore(lines: number): string[] {
+ public documentContextBefore(_lines: number): string[] {
throw new InvalidOperationAtUnknownPositionError('documentContextBefore', 'UnknownSourcePosition');
}
/**
* @inheritdoc
- * @group API: Content access
*/
- public documentContextAfter(lines: number): string[] {
+ public documentContextAfter(_lines: number): string[] {
throw new InvalidOperationAtUnknownPositionError('documentContextAfter', 'UnknownSourcePosition');
}
// -----------------------------------------------
@@ -219,7 +196,6 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// -----------------------------------------------
/**
* @inheritdoc
- * @group API: Printing
*/
public toString(): string {
return '@>';
@@ -228,6 +204,3 @@ export class UnknownSourcePosition extends AbstractSourcePosition implements Sou
// #endregion } API: Printing
// ===============================================
}
-// -----------------------------------------------
-// #endregion } UnknownSourcePosition
-// ===============================================
diff --git a/src/SourceReader/SourcePositions/index.ts b/src/SourceReader/SourcePositions/index.ts
index c5febfd..cde03bc 100644
--- a/src/SourceReader/SourcePositions/index.ts
+++ b/src/SourceReader/SourcePositions/index.ts
@@ -11,8 +11,14 @@
* *****************************************************************************
*/
/**
- * @module API.SourceReader
+ * This module exposes the source position elements that are used by the
+ * {@link SourceReader}. This module is internal, thus, the user should not
+ * instantiate the classes here but through the {@link SourcePositions} factory.
+ *
+ * @module SourceReader/SourcePositions
* @author Alan Rodas Bonjour
+ *
+ * @internal
*/
export * from './SourceSpan';
export * from './SourcePosition';
diff --git a/src/SourceReader/SourceReader.ts b/src/SourceReader/SourceReader.ts
index f9ea2e5..05b7599 100644
--- a/src/SourceReader/SourceReader.ts
+++ b/src/SourceReader/SourceReader.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * @module SourceReader
* @author Pablo E. --Fidel-- Martínez López,
*/
import { SourcePosition, SourcePositions } from './SourcePositions';
@@ -53,8 +54,6 @@ import { and, expect } from '../Expectations';
* ```
* new SourceReader(input, '\n');
* ```
- *
- * @group API: Main
*/
export type SourceInput = string | Record | string[];
// -----------------------------------------------
@@ -64,7 +63,7 @@ export type SourceInput = string | Record | string[];
// ===============================================
// #region class SourceReader { TO DO: Update
// -----------------------------------------------
-/** TO DO: Update
+/**
* A {@link SourceReader} allows you to read input from some source, either one
* single document of content or several named or index source documents, in
* such a way that each character read registers its position in the source as a
@@ -81,13 +80,13 @@ export type SourceInput = string | Record | string[];
* parts with ease.
*
* A {@link SourceReader} is created using a {@link SourceInput} and then
- * {@link SourcePosition}s can be read from it.
+ * {@link SourceReader/SourcePositions.SourcePosition}s can be read from it.
* Possible interactions with a {@link SourceReader} include:
* - peek a character, with {@link SourceReader.peek | peek},
* - check if a given strings occurs at the beginning of the text in the
* current document, without skipping it, with
* {@link SourceReader.startsWith | startsWith},
- * - get the current position as a {@link SourcePosition}, with
+ * - get the current position as a {@link SourceReader/SourcePositions.SourcePosition}, with
* {@link SourceReader.getPosition | getPosition},
* - detect if the end of input was reached, with
* {@link SourceReader.atEndOfInput | atEndOfInput},
@@ -119,8 +118,6 @@ export type SourceInput = string | Record | string[];
* A {@link SourceReader} also has a special position,
* {@link SourceReader.UnknownPosition | UnknownPosition}, as a static member of
* the class, indicating that the position is not known.
- * This special position can also be obtaind from instances using
- * {@link SourceReader.getUnknownPosition | getUnknownPosition}.
*
* Characters from the input are classified as either visible or non visible.
* Visible characters affect the line and column calculation, and, conversely, non visible
@@ -211,92 +208,80 @@ export type SourceInput = string | Record | string[];
* For that reason document is better to use {@link SourceReader.startsWith | startsWith}
* to verify if the input starts with some character (or string), when peeking
* for something specific.
- * @group API: Main
+ *
+ * @privateRemarks
+ * The implementation of {@link SourceReader} keeps:
+ * * an object associating input document names to input document contents,
+ * {@link SourceReader._documents | _documents},
+ * * an object associating input document names to visible input document
+ * contents,
+ * {@link SourceReader._visibleDocumentContents | _visibleDocumentContents},
+ * * an array of the keys of that object for sequential access,
+ * {@link SourceReader.documentsNames | _documentsNames},
+ * * an index to the current input document in the array of inputs names,
+ * {@link SourceReader._documentIndex | _documentIndex},
+ * * an index to the current visible input document in the array of inputs
+ * names (because it may be different from the document index),
+ * {@link SourceReader._charIndex | _charIndex},
+ * * the current line and column in the current input document,
+ * {@link SourceReader._line | _line} and
+ * {@link SourceReader._column | _column},
+ * * a stack of strings representing the regions' IDs,
+ * {@link SourceReader._regions | _regions}, and
+ * * the characters used to determine line ends,
+ * {@link SourceReader.lineEnders | _lineEnders}.
+ *
+ * The object of {@link SourceReader._documents | _documents } cannot be
+ * empty (with no input document), and all the {@link SourceInput} forms are
+ * converted to `Record` for ease of access.
+ * The {@link SourceReader._charIndex | _charIndex } either points to a valid
+ * position in an input document, or at the end of an input document, or the
+ * end of input was reached (that is, when there are no more input documents
+ * to read).
+ *
+ * Line and column numbers are adjusted depending on which characters are
+ * considered as ending a line, as given by the property
+ * {@link SourceReader.lineEnders | _lineEnders}, and which characters are
+ * considered visible, as indicating by the user through
+ * {@link SourceReader.skip | skip}.
+ * When changing from one document to the next, line and column numbers are reset.
+ *
+ * The visible input is conformed by those characters of the input that has
+ * been skipped normally. As visible and non visible characters can be
+ * interleaved with no restrictions, it is better to keep a copy of the
+ * visible parts: characters are copied to the visible inputs attribute when
+ * skipped normally. Visible inputs always have a copy of those characters
+ * that have been processed as visible; unprocessed characters do not appear
+ * (yet) on visible inputs.
+ *
+ * This class is tightly coupled with {@link SourceReader/SourcePositions.SourcePosition}'s implementations,
+ * because of instances of that class represent different positions in the source
+ * inputs kept by a {@link SourceReader}.
+ * The operations
+ * {@link SourceReader._documentNameAt | _documentNameAt},
+ * {@link SourceReader._visibleDocumentContentsAt | _visibleDocumentContentsAt},
+ * {@link SourceReader._fullDocumentContentsAt | _fullDocumentContentsAt},
+ * {@link SourceReader._inputFromToIn | _inputFromToIn},
+ * {@link SourceReader._documentContextBeforeOf | _fullInputFromTo} and
+ * {@link SourceReader._documentContextAfterOf | _fullDocumentContentsAt}
+ * are meant to be used only by {@link SourceReader/SourcePositions.SourcePosition}, to complete
+ * their operations, and so they are grouped as Protected.
+ *
+ * The remaining auxiliary operations are meant for internal usage, to
+ * provide readability or to avoid code duplication.
+ * The auxiliary operation {@link SourceReader._cloneRegions | _cloneRegions }
+ * is needed because each new position produced with
+ * {@link SourceReader.getPosition | getPosition } need to have a snapshot
+ * of the region stack, and not a mutable reference.
*/
export class SourceReader {
- // ===============================================
- // #region Implementation Details { TO DO: Update
- // -----------------------------------------------
- /** TO DO: Update
- * The implementation of {@link SourceReader} keeps:
- * * an object associating input document names to input document contents,
- * {@link SourceReader._documents | _documents},
- * * an object associating input document names to visible input document
- * contents,
- * {@link SourceReader._visibleDocumentContents | _visibleDocumentContents},
- * * an array of the keys of that object for sequential access,
- * {@link SourceReader.documentsNames | _documentsNames},
- * * an index to the current input document in the array of inputs names,
- * {@link SourceReader._documentIndex | _documentIndex},
- * * an index to the current visible input document in the array of inputs
- * names (because it may be different from the document index),
- * {@link SourceReader._charIndex | _charIndex},
- * * the current line and column in the current input document,
- * {@link SourceReader._line | _line} and
- * {@link SourceReader._column | _column},
- * * a stack of strings representing the regions' IDs,
- * {@link SourceReader._regions | _regions}, and
- * * the characters used to determine line ends,
- * {@link SourceReader.lineEnders | _lineEnders}.
- *
- * The object of {@link SourceReader._documents | _documents } cannot be
- * empty (with no input document), and all the {@link SourceInput} forms are
- * converted to `Record` for ease of access.
- * The {@link SourceReader._charIndex | _charIndex } either points to a valid
- * position in an input document, or at the end of an input document, or the
- * end of input was reached (that is, when there are no more input documents
- * to read).
- *
- * Line and column numbers are adjusted depending on which characters are
- * considered as ending a line, as given by the property
- * {@link SourceReader.lineEnders | _lineEnders}, and which characters are
- * considered visible, as indicating by the user through
- * {@link SourceReader.skip | skip}.
- * When changing from one document to the next, line and column numbers are reset.
- *
- * The visible input is conformed by those characters of the input that has
- * been skipped normally. As visible and non visible characters can be
- * interleaved with no restrictions, it is better to keep a copy of the
- * visible parts: characters are copied to the visible inputs attribute when
- * skipped normally. Visible inputs always have a copy of those characters
- * that have been processed as visible; unprocessed characters do not appear
- * (yet) on visible inputs.
- *
- * This class is tightly coupled with {@link SourcePosition}'s implementations,
- * because of instances of that class represent different positions in the source
- * inputs kept by a {@link SourceReader}.
- * The operations
- * {@link SourceReader._documentNameAt | _documentNameAt},
- * {@link SourceReader._visibleDocumentContentsAt | _visibleDocumentContentsAt} and
- * {@link SourceReader._visibleInputFromTo | _visibleInputFromTo },
- * {@link SourceReader._fullDocumentContentsAt | _fullDocumentContentsAt} and
- * {@link SourceReader._fullInputFromTo | _fullInputFromTo}, and
- * {@link SourceReader._documentContextBeforeOf | _fullInputFromTo} and
- * {@link SourceReader._documentContextAfterOf | _fullDocumentContentsAt}
- * are meant to be used only by {@link SourcePosition}, to complete
- * their operations, and so they are grouped as Protected.
- *
- * The remaining auxiliary operations are meant for internal usage, to
- * provide readability or to avoid code duplication.
- * The auxiliary operation {@link SourceReader._cloneRegions | _cloneRegions }
- * is needed because each new position produced with
- * {@link SourceReader.getPosition | getPosition } need to have a snapshot
- * of the region stack, and not a mutable reference.
- *
- * @group Implementation Details
- * @private
- */
- // -----------------------------------------------
- // #endregion } Implementation Details
- // ===============================================
-
// ===============================================
// #region API: Static Properties {
// -----------------------------------------------
/**
* A special position indicating that the position is not known.
*
- * @group API: Static Properties
+ * @group Properties (Static)
*/
public static readonly UnknownPosition: SourcePosition = SourcePositions.Unknown();
@@ -304,7 +289,7 @@ export class SourceReader {
* The string to use as a name for unnamed input documents.
* It is intended to be used only by instances.
*
- * @group API: Static Properties
+ * @group Properties (Static)
*/
public static readonly defaultDocumentNamePrefix: string = 'doc';
// -----------------------------------------------
@@ -316,16 +301,12 @@ export class SourceReader {
// -----------------------------------------------
/**
* The names with which input documents are identified.
- *
- * @group API: Properties
*/
public readonly documentsNames: string[];
/**
* The characters used to indicate the end of a line.
* These characters affect the calculation of line and column numbers for positions.
- *
- * @group API: Properties
*/
public readonly lineEnders: string;
// -----------------------------------------------
@@ -341,7 +322,6 @@ export class SourceReader {
*
* **INVARIANT:** it is always and object (not a string).
*
- * @group Implementation: Properties
* @private
*/
private _documents: Record;
@@ -354,7 +334,6 @@ export class SourceReader {
*
* **INVARIANT:** `0 <= _documentIndex <= _documentsNames.length`
*
- * @group Implementation: Properties
* @private
*/
private _documentIndex: number;
@@ -366,7 +345,6 @@ export class SourceReader {
* * if `_documentIndex < _documentsNames.length`
* then `0 <= _charIndex < _documents[_documentsNames[_documentIndex]].length`
*
- * @group Implementation: Properties
* @private
*/
private _charIndex: number;
@@ -381,7 +359,6 @@ export class SourceReader {
* * the values of each key are contained in the values of the
* corresponding key at `_documents`
*
- * @group Implementation: Properties
* @private
*/
private _visibleDocumentContents: Record;
@@ -394,7 +371,6 @@ export class SourceReader {
* * if `_documentIndex < _documentsNames.length`
* then `_line < _documents[_documentsNames[_documentIndex]].length`
*
- * @group Implementation: Properties
* @private
*/
private _line: number;
@@ -407,7 +383,6 @@ export class SourceReader {
* * if `_documentIndex < _documentsNames.length`
* then `_column < _documents[_documentsNames[_documentIndex]].length`
*
- * @group Implementation: Properties
* @private
*/
private _column: number;
@@ -415,7 +390,6 @@ export class SourceReader {
/**
* The active regions in the current input document.
*
- * @group Implementation: Properties
* @private
*/
private _regions: string[];
@@ -437,16 +411,14 @@ export class SourceReader {
*
* **PRECONDITION:** there is at least one input document.
*
- * @param input The source input. See {@link SourceInput} for explanation
+ * @param input - The source input. See {@link SourceInput} for explanation
* and examples of how to understand this parameter.
- * @param lineEnders A string of which characters will be used to determine
+ * @param lineEnders - A string of which characters will be used to determine
* the end of a line.
*
- * @throws {@link NoInputError} if the arguments are undefined or has no documents.
- *
- * @group API: Creation
+ * @throws {@link SourceReader/Errors.NoInputError} if the arguments are undefined or has no documents.
*/
- public constructor(input: SourceInput, lineEnders: string = '\n') {
+ public constructor(input: SourceInput, lineEnders = '\n') {
// No input document is not a valid option
and(
expect(input).not.toBeUndefined(),
@@ -459,13 +431,13 @@ export class SourceReader {
if (typeof input === 'string') {
// Single unnamed input case:
// will be referred as "doc1" afterwards.
- this._documents = { [SourceReader.defaultDocumentNamePrefix + 1]: input };
+ this._documents = { [SourceReader.defaultDocumentNamePrefix + String(1)]: input };
} else if (typeof input === 'object' && Array.isArray(input)) {
// Multiple unnamed input case:
// will be referred as "doc1", "doc2", ..., "docN" afterwards.
const tmp = {};
for (let i = 0; i < input.length; i++) {
- tmp[SourceReader.defaultDocumentNamePrefix + (i + 1)] = input[i];
+ tmp[SourceReader.defaultDocumentNamePrefix + String(i + 1)] = input[i];
}
this._documents = tmp;
} else {
@@ -500,7 +472,7 @@ export class SourceReader {
/**
* Answers if there are no more characters to read from the input.
*
- * @group API: Access
+ * @group Functions: Access
*/
public atEndOfInput(): boolean {
return !this._hasMoreDocuments();
@@ -509,7 +481,7 @@ export class SourceReader {
/**
* Answers if there are no more characters to read from the current document.
*
- * @group API: Access
+ * @group Functions: Access
*/
public atEndOfDocument(): boolean {
return this._hasMoreDocuments() && !this._hasMoreCharsAtCurrentDocument();
@@ -520,10 +492,10 @@ export class SourceReader {
*
* **PRECONDITION:** `!this.atEndOfInput()`
*
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the source reader is at EndOfDocument in the current position.
*
- * @group API: Access
+ * @group Functions: Access
*/
public currentDocumentName(): string {
expect(this._hasMoreDocuments()).toBeTrue().orThrow(new InvalidOperationAtEOIError('peek', 'SourceReader'));
@@ -536,12 +508,12 @@ export class SourceReader {
*
* **PRECONDITION:** `!this.atEndOfInput() && !this.atEndOfDocument`
*
- * @throws {@link InvalidOperationAtEODError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEODError}
* if the source reader is at EndOfInput in the current position.
- * @throws {@link InvalidOperationAtEOIError}
+ * @throws {@link SourceReader/Errors.InvalidOperationAtEOIError}
* if the source reader is at EndOfDocument in the current position.
*
- * @group API: Access
+ * @group Functions: Access
*/
public peek(): string {
expect(this._hasMoreDocuments()).toBeTrue().orThrow(new InvalidOperationAtEOIError('peek', 'SourceReader'));
@@ -557,9 +529,9 @@ export class SourceReader {
* documents -- that is, only the current input document is checked.
* See {@link SourceReader} documentation for an example.
*
- * @param str The string to verify the current input, starting at the current char.
+ * @param str - The string to verify the current input, starting at the current char.
*
- * @group API: Access
+ * @group Functions: Access
*/
public startsWith(str: string): boolean {
// The input ALWAYS starts with nothing, even at the end of input
@@ -582,14 +554,14 @@ export class SourceReader {
}
/**
- * Gives the current position as a {@link SourcePosition}.
+ * Gives the current position as a {@link SourceReader/SourcePositions.SourcePosition}.
* See {@link SourceReader} documentation for an example.
*
* **NOTE:**
* the special positions at the end of each input document, and at the end of the
- * input can be accessed by {@link SourceReader.getPosition}, but they cannot be peeked.
+ * input can be accessed by {@link SourceReader/SourcePositions.SourceReader.getPosition}, but they cannot be peeked.
*
- * @group API: Access
+ * @group Functions: Access
*/
public getPosition(): SourcePosition {
/* istanbul ignore next */
@@ -644,18 +616,18 @@ export class SourceReader {
*
* See {@link SourceReader} for an example of visible `skip`s.
*
- * @param howMuch An indication of how many characters have to be skipped.
+ * @param howMuch - An indication of how many characters have to be skipped.
* It may be given as a number or as a string. In this last
* case, the length of the string is used (the contents are
* ignored). If it is not given, it is assumed 1.
- * @param silently A boolean indicating if the skip must be silent. If it is
+ * @param silently - A boolean indicating if the skip must be silent. If it is
* not given, it is assumed `false`, that is, a visible
* skip. If the skip is visible, the char is added to the
* visible input.
*
- * @group API: Modification
+ * @group Functions: Modification
*/
- public skip(howMuch: number | string = 1, silently: boolean = false): void {
+ public skip(howMuch: number | string = 1, silently = false): void {
const amountToSkip: number = typeof howMuch === 'string' ? howMuch.length : howMuch;
for (let i = 0; i < amountToSkip && this._hasMoreDocuments(); i++) {
this._skipOne(silently);
@@ -671,17 +643,17 @@ export class SourceReader {
* satisfy the predicate.
* It does not go beyond the end of the current document, if starting inside one.
*
- * @param contCondition A predicate on strings, indicating the chars to read.
- * @param silently A boolean indicating if the reading must be silent. If it
+ * @param contCondition - A predicate on strings, indicating the chars to read.
+ * @param silently - A boolean indicating if the reading must be silent. If it
* is not given, it is assumed `false`, that is, a visible
* read. If the read is visible, the char is added to the
* visible input.
- * @result The string read from the initial position until the character that do not
+ * @returns The string read from the initial position until the character that do not
* satisfy the condition or the end of the current string.
*
- * @group API: Modification
+ * @group Functions: Modification
*/
- public takeWhile(contCondition: (ch: string) => boolean, silently: boolean = false): string {
+ public takeWhile(contCondition: (ch: string) => boolean, silently = false): string {
if (!this._hasMoreDocuments() || !this._hasMoreCharsAtCurrentDocument()) {
return '';
}
@@ -703,7 +675,7 @@ export class SourceReader {
* Pushes a region in the stack of regions.
* It does not work at the EndOfInput or the EndOfDocument (it does nothing).
*
- * @group API: Modification
+ * @group Functions: Modification
*/
public beginRegion(regionId: string): void {
// Optimized by inlining: if (!this.atEndOfInput() && !this.atEndOfDocument())
@@ -715,7 +687,7 @@ export class SourceReader {
/**
* Pops a region from the stack of regions.
* It does nothing if there are no regions in the stack.
- * @group API: Modification
+ * @group Functions: Modification
*/
public endRegion(): void {
if (this._regions.length > 0) {
@@ -731,7 +703,7 @@ export class SourceReader {
// -----------------------------------------------
/**
* Gives the name of the input document at the given index.
- * It is intended to be used only by {@link SourcePosition}s.
+ * It is intended to be used only by {@linkSourceReader/SourcePositions.SourcePosition}s.
*
* **PRECONDITION:**
* `index <= this._documentsNames.length` (not verified)
@@ -739,8 +711,8 @@ export class SourceReader {
* As it is a protected operation, it is not expectable to receive invalid indexes.
* It is not taken into account which are the results if that happens.
*
- * @group Implementation: Protected for Source Positions
- * @private
+ * @group Functions: Querying
+ * @internal
*/
public _documentNameAt(index: number): string {
return this.documentsNames[index];
@@ -749,7 +721,7 @@ export class SourceReader {
/**
* Gives the contents of the input document at the given index, both visible
* and non-visible.
- * It is intended to be used only by {@link SourcePosition}s.
+ * It is intended to be used only by {@link SourceReader/SourcePositions.SourcePosition}s.
*
* **PRECONDITION:**
* `index < this._documentsNames.length` (not verified)
@@ -757,8 +729,8 @@ export class SourceReader {
* As it is a protected operation, it is not expectable to receive invalid indexes.
* It is not taken into account which are the results if that happens.
*
- * @group Implementation: Protected for Source Positions
- * @private
+ * @group Functions: Querying
+ * @internal
*/
public _fullDocumentContentsAt(index: number): string {
return this._documents[this.documentsNames[index]];
@@ -766,7 +738,7 @@ export class SourceReader {
/**
* Gives the contents of the visible input document at the given index. It
- * is intended to be used only by {@link SourcePosition}s.
+ * is intended to be used only by {@link SourceReader/SourcePositions.SourcePosition}s.
*
* **PRECONDITION:**
* `index < this._documentsNames.length` (not verified).
@@ -774,8 +746,8 @@ export class SourceReader {
* As it is a protected operation, it is not expectable to receive invalid indexes.
* It is not taken into account which are the results if that happens.
*
- * @group Implementation: Protected for Source Positions
- * @private
+ * @group Functions: Querying
+ * @internal
*/
public _visibleDocumentContentsAt(index: number): string {
return this._visibleDocumentContents[this.documentsNames[index]];
@@ -784,8 +756,8 @@ export class SourceReader {
/**
* Returns the next character in the reader.
*
- * @group Implementation: Protected for Source Positions
- * @private
+ * @group Functions: Querying
+ * @internal
*/
public _peek(): string {
return this._fullDocumentContentsAt(this._documentIndex)[this._charIndex];
@@ -810,8 +782,8 @@ export class SourceReader {
* * The index of the document is valid (not checked)
* * The number of lines is not lower than 0 (not checked)
*
- * @group Implementation: Protected for Source Positions
- * @private
+ * @group Functions: Querying
+ * @internal
*/
public _documentContextBeforeOf(docIndex: number, charIndex: number, lines: number): string[] {
const docContents: string = this._fullDocumentContentsAt(docIndex);
@@ -843,8 +815,8 @@ export class SourceReader {
*
* The char at the given position is the first one in the solution.
*
- * @group Implementation: Protected for Source Positions
- * @private
+ * @group Functions: Querying
+ * @internal
*/
public _documentContextAfterOf(docIndex: number, charIndex: number, lines: number): string[] {
const docContents: string = this._fullDocumentContentsAt(docIndex);
@@ -877,8 +849,8 @@ export class SourceReader {
* **PRECONDITIONS:**
* * both positions correspond to this reader (and so are >= 0 -- not verified)
*
- * @group Implementation: Auxiliaries
- * @private
+ * @group Functions: Auxiliaries
+ * @internal
*/
public _inputFromToIn(
inputFrom: number,
@@ -920,9 +892,9 @@ export class SourceReader {
*
* **PRECONDITION:** `!this.atEndOfInput()` (not verified)
*
- * @param silently A boolean indicating if the skip must be silent.
+ * @param silently - A boolean indicating if the skip must be silent.
*
- * @group Implementation: Auxiliaries
+ * @group Function: Auxiliaries
* @private
*/
private _skipOne(silently: boolean): void {
@@ -952,7 +924,7 @@ export class SourceReader {
*
* **PRECONDITION:** `!this.atEndOfInput() && this.atEndOfDocument()`
*
- * @group Implementation: Auxiliaries
+ * @group Function: Auxiliaries
* @private
*/
private _skipToNextDocument(): void {
@@ -969,7 +941,7 @@ export class SourceReader {
/**
* Answers if there are more input documents to be read.
*
- * @group Implementation: Auxiliaries
+ * @group Function: Auxiliaries
* @private
*/
private _hasMoreDocuments(): boolean {
@@ -981,7 +953,7 @@ export class SourceReader {
*
* **PRECONDITION:** `this._hasMoreDocuments()`
*
- * @group Implementation: Auxiliaries
+ * @group Function: Auxiliaries
* @private
*/
private _hasMoreCharsAtCurrentDocument(): boolean {
@@ -992,7 +964,7 @@ export class SourceReader {
* Answers if the given char is recognized as an end of line indicator,
* according to the configuration of the reader.
*
- * @group Implementation: Auxiliaries
+ * @group Function: Auxiliaries
* @private
*/
private _isEndOfLine(ch: string): boolean {
@@ -1001,11 +973,11 @@ export class SourceReader {
/**
* Gives a clone of the stack of regions.
- * Auxiliary for {@link SourceReader.getPosition | getPosition}.
- * It is necessary because regions of {@link SourcePosition} must correspond
+ * Auxiliary for {@link SourceReader/SourcePositions.SourceReader.getPosition | getPosition}.
+ * It is necessary because regions of {@link SourceReader/SourcePositions.SourcePosition} must correspond
* to those at that position and do not change with changes in reader state.
*
- * @group Implementation: Auxiliaries
+ * @group Function: Auxiliaries
* @private
*/
private _cloneRegions(): string[] {
diff --git a/src/SourceReader/SourceReaderErrors.ts b/src/SourceReader/SourceReaderErrors.ts
index 64cc93a..4b341f0 100644
--- a/src/SourceReader/SourceReaderErrors.ts
+++ b/src/SourceReader/SourceReaderErrors.ts
@@ -10,16 +10,19 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.SourceReader
+ * This module exports error classes used by the {@link SourceReader.SourceReader} module.
+ *
+ * @module SourceReader/Errors
* @author Pablo E. --Fidel-- Martínez López,
*/
+
/**
* The superclass for all {@link SourceReader} errors.
- * It provides internationalization of error messages through a {@link API.Translator!Translator}.
* It also restores the prototype chain.
*
- * @group API: Main
+ * @group Errors
*/
export class SourceReaderError extends Error {
/**
@@ -29,7 +32,7 @@ export class SourceReaderError extends Error {
* from this level are supposed to be catched and rethrown or handled
* properly.
*
- * @param message A string message to show.
+ * @param message - A string message to show.
*/
public constructor(message: string) {
super(message);
@@ -41,7 +44,7 @@ export class SourceReaderError extends Error {
* The error to produce when a {@link SourceReader} is called with no input
* (an empty object or array).
*
- * @group API: Errors
+ * @group Errors
*/
export class NoInputError extends SourceReaderError {
/**
@@ -56,15 +59,15 @@ export class NoInputError extends SourceReaderError {
* The error to produce when two positions related with different readers are
* used to determine a portion of the contents.
*
- * @group API: Errors
+ * @group Errors
*/
export class MismatchedInputsError extends SourceReaderError {
/**
* The constructor for
* {@link MismatchedInputsError | MismatchedInputsError} errors.
*
- * @param operation A string indicating which function inform as the producer of the error.
- * @param context A string indicating the context in which the function produce the error.
+ * @param operation - A string indicating which function inform as the producer of the error.
+ * @param context - A string indicating the context in which the function produce the error.
*/
public constructor(
public readonly operation: string,
@@ -78,14 +81,14 @@ export class MismatchedInputsError extends SourceReaderError {
* The error to produce when a function that is not supposed to be used at
* an unknown position, but was called.
*
- * @group API: Errors
+ * @group Errors
*/
export class InvalidOperationAtUnknownPositionError extends SourceReaderError {
/**
- * The constructor for {@link InvalidOperationAtUnknownPositionError} errors.
+ * The constructor for {@link SourceReader/Errors.InvalidOperationAtUnknownPositionError} errors.
*
- * @param operation A string indicating which function produced the error.
- * @param context A string indicating the context in which the function produced the error.
+ * @param operation - A string indicating which function produced the error.
+ * @param context - A string indicating the context in which the function produced the error.
*/
public constructor(
public readonly operation: string,
@@ -98,14 +101,14 @@ export class InvalidOperationAtUnknownPositionError extends SourceReaderError {
/**
* The error to produce when a function that is not supposed to be used at EndOfInput is called.
*
- * @group API: Errors
+ * @group Errors
*/
export class InvalidOperationAtEOIError extends SourceReaderError {
/**
- * The constructor for {@link InvalidOperationAtEOIError} errors.
+ * The constructor for {@link SourceReader/Errors.InvalidOperationAtEOIError} errors.
*
- * @param operation A string indicating which function produced the error.
- * @param context A string indicating the context in which the function produced the error.
+ * @param operation - A string indicating which function produced the error.
+ * @param context - A string indicating the context in which the function produced the error.
*/
public constructor(
public readonly operation: string,
@@ -118,14 +121,14 @@ export class InvalidOperationAtEOIError extends SourceReaderError {
/**
* The error to produce when a function that is not supposed to be used at EndOfDocument is called.
*
- * @group API: Errors
+ * @group Errors
*/
export class InvalidOperationAtEODError extends SourceReaderError {
/**
* The constructor for {@link InvalidOperationAtEODError} errors.
*
- * @param operation A string indicating which function produced the error.
- * @param context A string indicating the context in which the function produced the error.
+ * @param operation - A string indicating which function produced the error.
+ * @param context - A string indicating the context in which the function produced the error.
*/
public constructor(
public readonly operation: string,
diff --git a/src/SourceReader/index.ts b/src/SourceReader/index.ts
index 8b67e0a..96e53dd 100644
--- a/src/SourceReader/index.ts
+++ b/src/SourceReader/index.ts
@@ -10,10 +10,7 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
-/**
- * @module API.SourceReader
- * @author Alan Rodas Bonjour
- */
+
/**
* A {@link SourceReader} allows you to read input from some source, either one single document of
* content or several named or indexed source documents, in such a way that each character read
@@ -27,23 +24,20 @@
* * to allow the relationship of parts of the input with identifiers naming "regions", thus
* making it possible for external tools to identify those parts with ease.
*
- * A {@link SourceReader} is created using a {@link SourceInput} and then {@link SourcePosition}s,
- * in particular {@link KnownSourcePosition}s, can be read from it.
+ * A {@link SourceReader} is created using a {@link SourceInput} and then {@link SourceReader/SourcePositions.SourcePosition}s,
+ * in particular {@link SourceReader/SourcePositions.AbstractKnownSourcePosition}s, can be read from it.
* Possible interactions with a {@link SourceReader} includes:
- * - {@link SourceReader.peek | peek}, peeking a character,
- * - {@link SourceReader.startsWith | startsWith}, checking if a given strings occurs at the
+ * * {@link SourceReader.peek | peek}, peeking a character,
+ * * {@link SourceReader.startsWith | startsWith}, checking if a given strings occurs at the
* beginning of the text in the current document, without skipping it,
- * - {@link SourceReader.getPosition | getPosition}
- * - {@link SourceReader.getDocumentPosition | getDocumentPosition}, getting the current position
- * as a {@link KnownSourcePosition} or (provided the end of input was not reached)
- * {@link DocumentSourcePosition}, respectively,
- * - {@link SourceReader.atEndOfInput | atEndOfInput}, detecting if the end of input was reached,
- * - {@link SourceReader.atEndOfDocument | atEndOfDocument}, detecting if the end of the current
+ * * {@link SourceReader.getPosition | getPosition}
+ * * {@link SourceReader.atEndOfInput | atEndOfInput}, detecting if the end of input was reached,
+ * * {@link SourceReader.atEndOfDocument | atEndOfDocument}, detecting if the end of the current
* document was reached,
- * - {@link SourceReader.skip | skip}, skipping one or more characters,
- * - {@link SourceReader.takeWhile | takeWhile}, reading some characters from the current document
+ * * {@link SourceReader.skip | skip}, skipping one or more characters,
+ * * {@link SourceReader.takeWhile | takeWhile}, reading some characters from the current document
* based on a condition, and
- * - {@link SourceReader.beginRegion | beginRegion} and
+ * * {@link SourceReader.beginRegion | beginRegion} and
* {@link SourceReader.endRegion | endRegion}, manipulating "regions".
* When reading from sources with multiple documents of input, skipping moves inside a document
* until there are no more characters, then an end of document position is reached (a special
@@ -60,25 +54,27 @@
*
* ## Source positions
*
- * {@link SourcePosition}s point to particular positions in the source given by a
+ * {@link SourceReader/SourcePositions.SourcePosition}s point to particular positions in the source given by a
* {@link SourceReader}.
- * All {@link SourcePosition}s are created only through {@link SourceReader}.
+ * All {@link SourceReader/SourcePositions.SourcePosition}s are created only through {@link SourceReader}.
*
* A source position may be known (pointing to a particular position into a
* {@link SourceReader}) or unknown (if a position cannot be determined).
- * The boolean property {@link SourcePosition.isUnknown | isUnknown}
+ * The boolean property {@link SourceReader/SourcePositions.SourcePosition.isUnknown | isUnknown}
* indicates which is the case.
*
- * Additionally, a string representation of any {@link SourcePosition}
- * can be obtained through {@link SourcePosition.toString | toString}
+ * Additionally, a string representation of any {@link SourceReader/SourcePositions.SourcePosition}
+ * can be obtained through {@link SourceReader/SourcePositions.SourcePosition.toString | toString}
* for internal use purposes.
*
- * A typical use of {@link SourcePosition}s is relating nodes of an AST
+ * A typical use of {@link SourceReader/SourcePositions.SourcePosition}s is relating nodes of an AST
* representation of code to particular positions in the string version of the
* source code (that may come from several input documents).
*
* @module SourceReader
+ * @author Alan Rodas Bonjour
*/
+
export * from './SourceReader';
export { SourcePosition, SourceSpan } from './SourcePositions';
export * from './SourceReaderErrors';
diff --git a/src/Translations/Translator.ts b/src/Translations/Translator.ts
deleted file mode 100644
index 199e04a..0000000
--- a/src/Translations/Translator.ts
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * *****************************************************************************
- * Copyright (C) National University of Quilmes 2018-2024
- * Gobstones (TM) is a trademark of the National University of Quilmes.
- *
- * This program is free software distributed under the terms of the
- * GNU Affero General Public License version 3.
- * Additional terms added in compliance to section 7 of such license apply.
- *
- * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
- * *****************************************************************************
- */
-/**
- * @module API.Translator
- * @author Alan Rodas Bonjour
- */
-import { flatten } from '../Functions/flatten';
-
-/**
- * A Translator consist of an object that hold the state of the current
- * locale being used, and allows for switching between different locales
- * and obtain translated strings.
- *
- * The translator expects a locale to be given as the language definition,
- * and, if constructed with the flatten options, flattens it to allow
- * dot notation access to the different strings in the locale object.
- *
- * Note that this object does not provide mechanisms for maintaining
- * multiple languages registered, nor should be used to hold the user defined
- * language as a state object. Rather, this should be created once, setted
- * with the desired language, and used always through the full library.
- *
- * @group API: Main
- */
-export class Translator> {
- /**
- * All the registered translations avaiable.
- */
- private availableTranslations: Record;
- /**
- * The default locale
- */
- private defaultLocale: string;
- /**
- * The current locale being used.
- * Types to any, as may be flatten or not.
- */
- private currentLocale: any;
- /**
- * The current locale name being used.
- */
- private currentLocaleName: string;
- /**
- * Whether or not use flatten when accessing elements to translate.
- */
- private flatten: boolean;
-
- /**
- * Create a new instance of this translator that uses the
- *
- */
- public constructor(
- availableTranslations: Record,
- defaultLocale: string,
- shouldFlat = true,
- currentLocale?: string
- ) {
- if (!availableTranslations) {
- throw new Error(`The translations cannot be null nor undefined`);
- }
- if (!defaultLocale) {
- throw new Error(`The default translation cannot be null nor undefined`);
- }
- if (!availableTranslations[defaultLocale]) {
- throw new Error(`The default translation must be one of the translations available`);
- }
- this.availableTranslations = availableTranslations;
- this.defaultLocale = defaultLocale;
- this.currentLocaleName = defaultLocale;
- this.flatten = shouldFlat;
- this.setLocale(currentLocale ?? defaultLocale);
- }
-
- /**
- * Get the default locale name
- *
- * @returns The default locale.
- */
- public getDefaultLocale(): string {
- return this.defaultLocale;
- }
-
- /**
- * Get all the available translations
- *
- * @returns The default locale.
- */
- public getAvailableTranslations(): Record {
- return this.availableTranslations;
- }
-
- /**
- * Get the current using locale
- *
- * @returns The current locale name.
- */
- public getLocale(): string {
- return this.currentLocaleName;
- }
-
- /**
- * Answer wether or not a given locale name is registered.
- *
- * @param locale The locale name to check for existence.
- *
- * @returns `true` if the locale exists, `false`otherwise.
- */
- public hasLocale(locale: string): boolean {
- return !!this.availableTranslations[locale];
- }
- /**
- * Set the current language to the given locale.
- *
- * @param locale A locale to use as the current language.
- */
- public setLocale(locale: string): void {
- if (!this.availableTranslations[locale]) {
- throw new Error(`The locale "${locale}" is not available`);
- }
- this.currentLocaleName = locale;
- this.currentLocale = this.flatten
- ? flatten(this.availableTranslations[this.currentLocaleName])
- : this.availableTranslations[this.currentLocaleName];
- }
-
- /**
- * Translate a specific key to the currently used locale, replacing
- * any interpolation matchers by the given interpolations.
- *
- * @param key The key to use to obtain the translated text
- * @param interpolations If given, keys of this object will be used
- * to replace any interpolation matcher in the translated text
- * (any text in between $\{\}) by the value of the corresponding key.
- *
- * @returns A translated string
- */
- public translate(key: string, interpolations?: Record): string {
- let value = this.currentLocale[key];
- if (!value || typeof value !== 'string') {
- return key;
- }
- const replacements = interpolations ?? [];
- for (const each in replacements) {
- value = value.replace(`\${${each}}`, `${replacements[each]}`);
- }
- return value;
- }
-
- /**
- * Translate a specific key to the currently used locale, by selecting the
- * corresponding pluralization, determined by the amount given and replacing
- * any interpolation matchers by the given interpolations.
- * Pluralization is selected based on the las part of the key in such a form
- * that it contains the amount as part of the key, or "n" for other number.
- * .e.g. given the key "test.key" plurals attempt to match "test.key.0",
- * "test.key.1" and so on, or "test.key.n".
- *
- * @param amount The amount given for pluralization
- * @param key The key to use to obtain the translated text
- * @param interpolations If given, keys of this object will be used
- * to replace any interpolation matcher in the translated text
- * (any text in $\{\}) by the value of the corresponding key.
- *
- * @returns A translated string
- */
- public pluralize(amount: number, key: string, interpolations?: Record): string {
- if (!Number.isInteger(amount)) {
- throw new Error('pluralization can only be used for integers');
- }
- if (this.currentLocale[`${key}.${amount.toString()}`]) {
- return this.translate(this.currentLocale[`${key}.${amount.toString()}`], interpolations);
- }
- if (this.currentLocale[`${key}.n`]) {
- return this.translate(this.currentLocale[`${key}.n`], interpolations);
- }
- return key;
- }
-}
diff --git a/src/Types/AnyFunction.ts b/src/Types/AnyFunction.ts
new file mode 100644
index 0000000..871d3b6
--- /dev/null
+++ b/src/Types/AnyFunction.ts
@@ -0,0 +1,26 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Types
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * This type represents a function that can
+ * take any number of arguments, and return any value or not return at all.
+ * It's a useful type definition for places where a function is expected, but
+ * it's shape may be any.
+ */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export type AnyFunction = (...args: readonly any[]) => any;
diff --git a/src/Types/BiMap.ts b/src/Types/BiMap.ts
index f2fcc73..6b7ef7c 100644
--- a/src/Types/BiMap.ts
+++ b/src/Types/BiMap.ts
@@ -10,8 +10,9 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Types
+ * @module Types
* @author Alan Rodas Bonjour
*/
@@ -61,10 +62,8 @@
* given key or value in the map where they are values, if they appear there, and the
* association of a new pair key-value, deleting the old associations for both, if they exist.
*
- * @param K The type of the keys.
- * @param V The type of the values.
- *
- * @group API: Main
+ * @param K - The type of the keys.
+ * @param V - The type of the values.
*/
export class BiMap {
/**
@@ -104,7 +103,7 @@ export class BiMap {
* ```
*
* @group Constructors
- * @param map Optional list of associations to contain in the new BiMap.
+ * @param map - Optional list of associations to contain in the new BiMap.
*/
public constructor(map?: [K, V][]) {
this.mapKV = new Map();
@@ -139,7 +138,7 @@ export class BiMap {
* Answer if this BiMap has the given key associated with a value.
*
* @group Querying
- * @param key The key to search
+ * @param key - The key to search
* @returns true if the key is present, false otherwise.
*/
public hasKey(key: K): boolean {
@@ -151,7 +150,7 @@ export class BiMap {
* undefined if the key is not associated with any value.
*
* @group Querying
- * @param key The key to retrieve the associated value
+ * @param key - The key to retrieve the associated value
* @returns true if the key is present, false otherwise.
*/
public getByKey(key: K): V | undefined {
@@ -163,8 +162,8 @@ export class BiMap {
* If any of both have previous associations, they are lost.
*
* @group Manipulation
- * @param key The key to associate with the value
- * @param value The value to associate with the key
+ * @param key - The key to associate with the value
+ * @param value - The value to associate with the key
*/
public setByKey(key: K, value: V): void {
this.biassociateKeyAndValue(key, value);
@@ -174,7 +173,7 @@ export class BiMap {
* Delete the association between the given key and its value, if it exists.
*
* @group Manipulation
- * @param key The key to delete its association
+ * @param key - The key to delete its association
*/
public deleteByKey(key: K): void {
this.reverseDeleteKey(key);
@@ -185,7 +184,7 @@ export class BiMap {
* Answer if this BiMap has the given value associated with a key.
*
* @group Querying
- * @param value The value to search
+ * @param value - The value to search
*/
public hasValue(value: V): boolean {
return !!this.mapVK.has(value); // !! transforms falsy values into booleans
@@ -196,7 +195,7 @@ export class BiMap {
* undefined if the value is not associated with any key.
*
* @group Querying
- * @param value The value to retrieve the associated key
+ * @param value - The value to retrieve the associated key
*/
public getByValue(value: V): K | undefined {
return this.mapVK.get(value);
@@ -207,8 +206,8 @@ export class BiMap {
* If any of both have previous associations, they are lost.
*
* @group Manipulation
- * @param value The value to associate with the key
- * @param key The key to associate with the value
+ * @param value - The value to associate with the key
+ * @param key - The key to associate with the value
*/
public setByValue(value: V, key: K): void {
this.biassociateKeyAndValue(key, value);
@@ -218,7 +217,7 @@ export class BiMap {
* Delete the association between the given key and its value, if it exists.
*
* @group Manipulation
- * @param value The value to delete its association.
+ * @param value - The value to delete its association.
*/
public deleteByValue(value: V): void {
this.reverseDeleteValue(value);
@@ -271,16 +270,18 @@ export class BiMap {
* @group Printing
*/
public toString(): string {
- let str: string = 'BiMap:{ ';
+ let str = 'BiMap:{ ';
const entries = this.entries();
if (entries.length > 0) {
let k: K;
let v: V;
for (let i = 0; i < entries.length - 1; i++) {
[k, v] = entries[i];
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
str += k + ' <-> ' + v + ', ';
}
[k, v] = entries[entries.length - 1];
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
str += k + ' <-> ' + v + ' ';
}
str += '}';
diff --git a/src/Types/Join.ts b/src/Types/Join.ts
new file mode 100644
index 0000000..d40de90
--- /dev/null
+++ b/src/Types/Join.ts
@@ -0,0 +1,31 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Types
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * This type represents the joining of two types, separated by a string, defaulting to dot.
+ *
+ * @remarks
+ * This type is useful when you have separate field representing types, and you need
+ * to represent the idea of a full path. So if you have the types `foo` and `bar`, you
+ * may use Join to provide the type `foo.bar`.
+ */
+export type Join = K extends string | number
+ ? P extends string | number
+ ? `${K}${'' extends P ? '' : S}${P}`
+ : never
+ : never;
diff --git a/src/Types/Leaves.ts b/src/Types/Leaves.ts
new file mode 100644
index 0000000..0f2cd68
--- /dev/null
+++ b/src/Types/Leaves.ts
@@ -0,0 +1,32 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Types
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * This type represent all the possible leaves of an object type.
+ *
+ * @remarks
+ * A leaf consists of a path that leads ultimately to a simple value. So for example
+ * let' say we have an object with the form `{ foo: { bar: 5, baz: 'hello' } }`, then
+ * the Leaves of it's type are `foo.bar` and `foo.baz`.
+ *
+ * This type is useful if you need to type things such as paths in an object that
+ * lead to a particular value, such as the types of a translation in a json file.
+ */
+export type Leaves = T extends object
+ ? { [K in keyof T]: `${Exclude}${Leaves extends never ? '' : `.${Leaves}`}` }[keyof T]
+ : never;
diff --git a/src/Types/Paths.ts b/src/Types/Paths.ts
new file mode 100644
index 0000000..88b0b42
--- /dev/null
+++ b/src/Types/Paths.ts
@@ -0,0 +1,32 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) National University of Quilmes 2018-2024
+ * Gobstones (TM) is a trademark of the National University of Quilmes.
+ *
+ * This program is free software distributed under the terms of the
+ * GNU Affero General Public License version 3.
+ * Additional terms added in compliance to section 7 of such license apply.
+ *
+ * You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
+ * *****************************************************************************
+ */
+
+/**
+ * @module Types
+ * @author Alan Rodas Bonjour
+ */
+
+/**
+ * This type represent all the possible paths of an object type.
+ *
+ * @remarks
+ * A path consists of a path that leads to a simple or complex value. So for example
+ * let' say we have an object with the form `{ foo: { bar: 5, baz: 'hello' } }`, then
+ * the Paths of it's type are `foo`, `foo.bar` and `foo.baz`.
+ *
+ * This type is useful if you need to type things such as paths in an object that
+ * lead to a particular value, such as the types of a translation in a json file.
+ */
+export type Paths = T extends object
+ ? { [K in keyof T]: `${Exclude}${'' | `.${Paths}`}` }[keyof T]
+ : never;
diff --git a/src/Types/Subset.ts b/src/Types/Subset.ts
index 14bf69a..adedbf0 100644
--- a/src/Types/Subset.ts
+++ b/src/Types/Subset.ts
@@ -11,7 +11,7 @@
* *****************************************************************************
*/
/**
- * @module API.Types
+ * @module Types
* @author Pablo E. --Fidel-- Martínez López
*/
@@ -22,8 +22,6 @@
* {@link https://grrr.tech/posts/2021/typescript-partial/ | blog by Harmen Janssen}, posted
* on November 29, 2021.
* See that blog for an explanation on the code.
- *
- * @group API: Main
*/
export type Subset = {
[attr in keyof K]?: K[attr] extends object
diff --git a/src/Types/WithRequired.ts b/src/Types/WithRequired.ts
index a344ca0..bcca886 100644
--- a/src/Types/WithRequired.ts
+++ b/src/Types/WithRequired.ts
@@ -10,10 +10,12 @@
* You may read the full license at https://gobstones.github.io/gobstones-guidelines/LICENSE.
* *****************************************************************************
*/
+
/**
- * @module API.Types
+ * @module Types
* @author Alan Rodas Bonjour