Compare commits

...

73 Commits

Author SHA1 Message Date
Michael B. Gale
b24bd4a46f Don't fail post start-proxy action if killing the proxy process fails
Otherwise logs won't get uploaded as artifact, even in debug mode
2025-04-25 16:53:21 +01:00
Michael B. Gale
6e35f86a20 Add proxy_binary input to start-proxy Action
This allows a custom binary to be used. Mainly for testing.
2025-04-25 16:53:09 +01:00
Michael B. Gale
f843d94177 Merge pull request #2869 from github/mbg/proxy/use-2.21.1-artifacts
Use proxy artifacts for `v2.21.1`
2025-04-25 16:50:50 +01:00
Michael B. Gale
2264a4ecc1 Merge branch 'main' into mbg/proxy/use-2.21.1-artifacts 2025-04-25 14:25:57 +01:00
Michael B. Gale
d3b65fcaf0 Merge pull request #2870 from github/mbg/ci/retire-ubuntu-20.04
Remove ubuntu-20.04 and add ubuntu-24.04
2025-04-25 14:25:40 +01:00
Michael B. Gale
eea52ddc4e Remove ubuntu-20.04 and add ubuntu-24.04 2025-04-25 13:03:25 +01:00
Michael B. Gale
6ef9b921b1 Use proxy artifacts for v2.21.1 2025-04-24 18:20:31 +01:00
Ian Lynagh
4ffa2364a0 Merge pull request #2867 from github/mergeback/v3.28.16-to-main-28deaeda
Mergeback v3.28.16 refs/heads/releases/v3 into main
2025-04-23 13:34:31 +01:00
github-actions[bot]
7e00290d34 Update checked-in dependencies 2025-04-23 12:17:11 +00:00
github-actions[bot]
259434501f Update changelog and version after v3.28.16 2025-04-23 12:10:49 +00:00
Ian Lynagh
28deaeda66 Merge pull request #2865 from github/update-v3.28.16-2a8cbadc0
Merge main into releases/v3
2025-04-23 13:10:18 +01:00
github-actions[bot]
03c5d71c11 Update changelog for v3.28.16 2025-04-23 10:40:48 +00:00
Ian Lynagh
2a8cbadc02 Merge pull request #2863 from github/update-bundle/codeql-bundle-v2.21.1
Update default bundle to 2.21.1
2025-04-22 12:30:12 +01:00
github-actions[bot]
f76eaf51a6 Add changelog note 2025-04-16 16:54:18 +00:00
github-actions[bot]
e63b3f5166 Update default bundle to codeql-bundle-v2.21.1 2025-04-16 16:54:11 +00:00
Andrew Eisenberg
4c3e536282 Merge pull request #2853 from github/dependabot/npm_and_yarn/npm-7d84c66b66
build(deps-dev): bump the npm group with 3 updates
2025-04-10 16:31:21 -07:00
Nick Fyson
56dd02f26d Merge pull request #2852 from github/dependabot/github_actions/actions-4575878e06
build(deps): bump actions/create-github-app-token from 1.12.0 to 2.0.2 in the actions group
2025-04-09 17:18:03 +01:00
Nick Fyson
192406dd84 Merge branch 'main' into dependabot/github_actions/actions-4575878e06 2025-04-09 16:59:59 +01:00
Nick Fyson
c7dbb2084e Merge pull request #2857 from github/nickfyson/address-vulns
move use of input variables into env vars
2025-04-09 16:05:04 +01:00
nickfyson
9a45cd8c50 move use of input variables into env vars 2025-04-09 14:13:35 +01:00
Andrew Eisenberg
d26c46acea Merge pull request #2855 from github/mergeback/v3.28.15-to-main-45775bd8
Mergeback v3.28.15 refs/heads/releases/v3 into main
2025-04-07 14:48:19 -07:00
github-actions[bot]
51c83e1588 Update checked-in dependencies 2025-04-07 21:34:58 +00:00
github-actions[bot]
8774e3f945 Update changelog and version after v3.28.15 2025-04-07 21:32:19 +00:00
Andrew Eisenberg
45775bd823 Merge pull request #2854 from github/update-v3.28.15-a35ae8c38
Merge main into releases/v3
2025-04-07 14:31:50 -07:00
Andrew Eisenberg
dd78aab407 Update CHANGELOG.md with bug fix details 2025-04-07 14:15:05 -07:00
github-actions[bot]
e40af59174 Update changelog for v3.28.15 2025-04-07 21:05:03 +00:00
Chuan-kai Lin
a35ae8c380 Merge pull request #2843 from github/cklin/diff-informed-compat
Set checkPresence in diff-range data extension
2025-04-07 13:29:16 -07:00
github-actions[bot]
5bddbeb2bf Update checked-in dependencies 2025-04-07 17:59:50 +00:00
dependabot[bot]
c7102cdca1 build(deps-dev): bump the npm group with 3 updates
Bumps the npm group with 3 updates: [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js), [nock](https://github.com/nock/nock) and [typescript](https://github.com/microsoft/TypeScript).


Updates `@eslint/js` from 9.23.0 to 9.24.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.24.0/packages/js)

Updates `nock` from 14.0.2 to 14.0.3
- [Release notes](https://github.com/nock/nock/releases)
- [Changelog](https://github.com/nock/nock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nock/nock/compare/v14.0.2...v14.0.3)

Updates `typescript` from 5.8.2 to 5.8.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.24.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: nock
  dependency-version: 14.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 17:59:17 +00:00
dependabot[bot]
a1ca4846bc build(deps): bump actions/create-github-app-token in the actions group
Bumps the actions group with 1 update: [actions/create-github-app-token](https://github.com/actions/create-github-app-token).


Updates `actions/create-github-app-token` from 1.12.0 to 2.0.2
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/v1.12.0...v2.0.2)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-version: 2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-07 17:53:11 +00:00
Andrew Eisenberg
bb59df6c17 Merge pull request #2842 from github/henrymercer/zip64
Raise the file limit for debug artifacts by producing zip64 files where necessary
2025-04-07 10:50:46 -07:00
Arthur Baars
4b508f5964 Merge pull request #2845 from github/mergeback/v3.28.14-to-main-fc7e4a0f
Mergeback v3.28.14 refs/heads/releases/v3 into main
2025-04-07 13:04:29 +02:00
github-actions[bot]
ca00afb5f1 Update checked-in dependencies 2025-04-07 09:33:21 +00:00
github-actions[bot]
2969c78ce0 Update changelog and version after v3.28.14 2025-04-07 09:27:28 +00:00
Arthur Baars
fc7e4a0fa0 Merge pull request #2844 from github/update-v3.28.14-362ef4ce2
Merge main into releases/v3
2025-04-07 11:26:56 +02:00
github-actions[bot]
be0175c800 Update changelog for v3.28.14 2025-04-07 09:09:01 +00:00
Andrew Eisenberg
a8be43c24e Don't throw error for ENOENT 2025-04-04 13:42:00 -07:00
Chuan-kai Lin
94102d99b0 Set checkPresence in diff-range data extension
This commit updates the diff-range data extension to use the new
checkPresence field being introduced in CodeQL CLI 2.21.0, so that
diff-informed analysis no longer fails when a query pack does not have
the restrictAlertsTo extensible predicate.
2025-04-04 08:41:50 -07:00
github-actions[bot]
fd8685f16e Update checked-in dependencies 2025-04-04 13:46:53 +00:00
Henry Mercer
56feaac968 Raise file limit in debug artifacts by using zip64 2025-04-04 14:40:53 +01:00
Arthur Baars
362ef4ce20 Merge pull request #2838 from github/update-bundle/codeql-bundle-v2.21.0
Update default bundle to 2.21.0
2025-04-03 15:40:24 +02:00
Arthur Baars
2b85c00718 Merge branch 'main' into update-bundle/codeql-bundle-v2.21.0 2025-04-03 15:28:09 +02:00
Angela P Wen
41aa437638 Merge pull request #2841 from github/angelapwen/log-init-post-telemetry
Add logs around status report telemetry in `init-post` step
2025-04-03 14:51:03 +02:00
Angela P Wen
92864f48b0 Add logs around status report telemetry in init-post step 2025-04-03 14:37:27 +02:00
Fotis Koutoulakis
e13fe0dd2d Merge pull request #2833 from github/NlightNFotis/reclassify_upload_sarif_issues
feat: further error re-classification
2025-04-02 20:09:36 +01:00
Fotis Koutoulakis
06703ce3e5 Merge branch 'main' into NlightNFotis/reclassify_upload_sarif_issues 2025-04-02 19:06:45 +01:00
Fotis Koutoulakis (@NlightNFotis)
676a422916 review-comments: nest validateSariFileSchema into try-catch block to better discriminate error thrown 2025-04-02 19:06:31 +01:00
Fotis Koutoulakis (@NlightNFotis)
498c7f37e8 review-comments: unwrap error in upload-sarif-action and re-classify as ConfigurationError if in known error category 2025-04-02 15:20:03 +01:00
Fotis Koutoulakis (@NlightNFotis)
efd29bef22 refactor: revert getActionsStatus taking an extra argument 2025-04-02 15:13:00 +01:00
Angela P Wen
dab8a02091 Merge pull request #2836 from github/dependabot/github_actions/actions-02c935407f
build(deps): bump the actions group with 2 updates
2025-04-02 14:57:29 +02:00
Angela P Wen
10771737a9 Merge pull request #2840 from github/dependabot/npm_and_yarn/npm-05c8aca45e
build(deps-dev): bump the npm group across 1 directory with 4 updates
2025-04-02 14:56:55 +02:00
Angela P Wen
17379bcd20 Manually update PR check workflow 2025-04-02 14:43:55 +02:00
github-actions[bot]
dbb232a3d8 Update checked-in dependencies 2025-04-02 12:43:14 +00:00
dependabot[bot]
4b72bef651 build(deps-dev): bump the npm group across 1 directory with 4 updates
Bumps the npm group with 4 updates in the / directory: [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver), [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) and [nock](https://github.com/nock/nock).


Updates `@types/semver` from 7.5.8 to 7.7.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Updates `@typescript-eslint/eslint-plugin` from 8.28.0 to 8.29.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.29.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.28.0 to 8.29.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.29.0/packages/parser)

Updates `nock` from 14.0.1 to 14.0.2
- [Release notes](https://github.com/nock/nock/releases)
- [Changelog](https://github.com/nock/nock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nock/nock/compare/v14.0.1...v14.0.2)

---
updated-dependencies:
- dependency-name: "@types/semver"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: nock
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 12:42:37 +00:00
Fotis Koutoulakis (@NlightNFotis)
b53826d56d review-comments: remove syntax-error handling for SARIF from upload-lib 2025-04-01 15:10:16 +01:00
Fotis Koutoulakis (@NlightNFotis)
55ee663d5f review-comments: refactor getActionsStatus to accept an extra parameter designating if the analysis is third-party 2025-04-01 14:58:59 +01:00
github-actions[bot]
a27e401674 Add changelog note 2025-04-01 13:51:07 +00:00
github-actions[bot]
a69f5113b7 Update default bundle to codeql-bundle-v2.21.0 2025-04-01 13:51:03 +00:00
dependabot[bot]
b6f76bd566 build(deps): bump the actions group with 2 updates
Bumps the actions group with 2 updates: [ruby/setup-ruby](https://github.com/ruby/setup-ruby) and [actions/create-github-app-token](https://github.com/actions/create-github-app-token).


Updates `ruby/setup-ruby` from 1.227.0 to 1.229.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](1a615958ad...354a1ad156)

Updates `actions/create-github-app-token` from 1.11.7 to 1.12.0
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](https://github.com/actions/create-github-app-token/compare/v1.11.7...v1.12.0)

---
updated-dependencies:
- dependency-name: ruby/setup-ruby
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: actions/create-github-app-token
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-31 17:16:14 +00:00
Fotis Koutoulakis (@NlightNFotis)
01f1a1f2c9 Merge branch 'main' into NlightNFotis/reclassify_upload_sarif_issues 2025-03-31 16:29:02 +01:00
Chuan-kai Lin
efffb483ec Merge pull request #2831 from github/cklin/diff-informed-query-filtering
Respect `exclude-from-incremental` query tag for diff-informed analysis
2025-03-31 08:00:50 -07:00
Fotis Koutoulakis (@NlightNFotis)
f21cf0bbd7 feat: reclassify InvalidSarifUploadError as a user-error when final status report is produced 2025-03-31 12:22:18 +01:00
Fotis Koutoulakis (@NlightNFotis)
72a2b1295e feat: classify some observed SARIF errors as InvalidSarifUploadError 2025-03-31 12:17:23 +01:00
Fotis Koutoulakis (@NlightNFotis)
a022653e2d feat: classify more HTTP errors as configuration errors in api-client 2025-03-31 11:54:16 +01:00
Fotis Koutoulakis (@NlightNFotis)
3c42562190 fix: update comment for test to state correct expected outcome 2025-03-31 11:51:11 +01:00
Chuan-kai Lin
e4ca874973 build: refresh js files 2025-03-28 12:30:40 -07:00
Chuan-kai Lin
e7f67e2e61 Redefine shouldPerformDiffInformedAnalysis()
This commit renames the original shouldPerformDiffInformedAnalysis(),
which returns `PullRequestBranches | undefined`, to
getDiffInformedAnalysisBranches(). It also adds a new
shouldPerformDiffInformedAnalysis() function that returns boolean.

Separating these two functions makes it clear what the intended uses and
return values should be for each.
2025-03-28 12:29:28 -07:00
Chuan-kai Lin
71ab101d38 Set default query filter for diff-informed analysis 2025-03-27 14:06:40 -07:00
Chuan-kai Lin
da967b1ade AugmentationProperties: add defaultQueryFilters
This commit adds a defaultQueryFilters field to AugmentationProperties
and incorporates its value into the augmented Code Scanning config.
However, in this commit defaultQueryFilters is always empty, so there is
not yet any actual behavior change.
2025-03-27 13:44:47 -07:00
Chuan-kai Lin
3c4533916b Call shouldPerformDiffInformedAnalysis() outside setupDiffInformedQueryRun() 2025-03-27 10:27:24 -07:00
Chuan-kai Lin
1994ea768e Move shouldPerformDiffInformedAnalysis() 2025-03-27 10:27:24 -07:00
Chuan-kai Lin
534bc63d5e Rename diff-filtering-utils.ts to diff-informed-analysis-utils.ts 2025-03-27 10:27:23 -07:00
Chuan-kai Lin
3fbee52426 Extract shouldPerformDiffInformedAnalysis() 2025-03-27 10:27:23 -07:00
1528 changed files with 212005 additions and 5215 deletions

View File

@@ -29,24 +29,27 @@ runs:
- id: get-url
name: Determine URL
shell: bash
env:
VERSION: ${{ inputs.version }}
USE_ALL_PLATFORM_BUNDLE: ${{ inputs.use-all-platform-bundle }}
run: |
set -e # Fail this Action if `gh release list` fails.
if [[ ${{ inputs.version }} == "linked" ]]; then
if [[ "$VERSION" == "linked" ]]; then
echo "tools-url=linked" >> "$GITHUB_OUTPUT"
exit 0
elif [[ ${{ inputs.version }} == "default" ]]; then
elif [[ "$VERSION" == "default" ]]; then
echo "tools-url=" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ ${{ inputs.version }} == "nightly-latest" && "$RUNNER_OS" != "Windows" ]]; then
if [[ "$VERSION" == "nightly-latest" && "$RUNNER_OS" != "Windows" ]]; then
extension="tar.zst"
else
extension="tar.gz"
fi
if [[ ${{ inputs.use-all-platform-bundle }} == "true" ]]; then
if [[ "$USE_ALL_PLATFORM_BUNDLE" == "true" ]]; then
artifact_name="codeql-bundle.$extension"
elif [[ "$RUNNER_OS" == "Linux" ]]; then
artifact_name="codeql-bundle-linux64.$extension"
@@ -59,14 +62,14 @@ runs:
exit 1
fi
if [[ ${{ inputs.version }} == "nightly-latest" ]]; then
if [[ "$VERSION" == "nightly-latest" ]]; then
tag=`gh release list --repo dsp-testing/codeql-cli-nightlies -L 1 | cut -f 3`
echo "tools-url=https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/$tag/$artifact_name" >> $GITHUB_OUTPUT
elif [[ ${{ inputs.version }} == *"nightly"* ]]; then
version=`echo ${{ inputs.version }} | sed -e 's/^.*\-//'`
elif [[ "$VERSION" == *"nightly"* ]]; then
version=`echo "$VERSION" | sed -e 's/^.*\-//'`
echo "tools-url=https://github.com/dsp-testing/codeql-cli-nightlies/releases/download/codeql-bundle-$version/$artifact_name" >> $GITHUB_OUTPUT
elif [[ ${{ inputs.version }} == *"stable"* ]]; then
version=`echo ${{ inputs.version }} | sed -e 's/^.*\-//'`
elif [[ "$VERSION" == *"stable"* ]]; then
version=`echo "$VERSION" | sed -e 's/^.*\-//'`
echo "tools-url=https://github.com/github/codeql-action/releases/download/codeql-bundle-$version/$artifact_name" >> $GITHUB_OUTPUT
else
echo "::error::Unrecognized version specified!"

View File

@@ -18,8 +18,11 @@ runs:
using: "composite"
steps:
- id: branches
env:
MAJOR_VERSION: ${{ inputs.major_version }}
LATEST_TAG: ${{ inputs.latest_tag }}
run: |
python ${{ github.action_path }}/release-branches.py \
--major-version ${{ inputs.major_version }} \
--latest-tag ${{ inputs.latest_tag }}
--major-version "$MAJOR_VERSION" \
--latest-tag "$LATEST_TAG"
shell: bash

View File

@@ -46,7 +46,7 @@ jobs:
use-all-platform-bundle: 'false'
setup-kotlin: 'true'
- name: Set up Ruby
uses: ruby/setup-ruby@1a615958ad9d422dd932dc1d5823942ee002799f # v1.227.0
uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1.229.0
with:
ruby-version: 2.6
- name: Install Code Scanning integration

View File

@@ -75,7 +75,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04,ubuntu-22.04,windows-2019,windows-2022,macos-13,macos-14]
os: [ubuntu-22.04,ubuntu-24.04,windows-2019,windows-2022,macos-13,macos-14]
tools: ${{ fromJson(needs.check-codeql-versions.outputs.versions) }}
runs-on: ${{ matrix.os }}

View File

@@ -168,7 +168,7 @@ jobs:
--draft
- name: Generate token
uses: actions/create-github-app-token@v1.11.7
uses: actions/create-github-app-token@v2.0.2
id: app-token
with:
app-id: ${{ vars.AUTOMATION_APP_ID }}

View File

@@ -124,7 +124,7 @@ jobs:
pull-requests: write # needed to create pull request
steps:
- name: Generate token
uses: actions/create-github-app-token@v1.11.7
uses: actions/create-github-app-token@v2.0.2
id: app-token
with:
app-id: ${{ vars.AUTOMATION_APP_ID }}

View File

@@ -6,6 +6,18 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
No user facing changes.
## 3.28.16 - 23 Apr 2025
- Update default CodeQL bundle version to 2.21.1. [#2863](https://github.com/github/codeql-action/pull/2863)
## 3.28.15 - 07 Apr 2025
- Fix bug where the action would fail if it tried to produce a debug artifact with more than 65535 files. [#2842](https://github.com/github/codeql-action/pull/2842)
## 3.28.14 - 07 Apr 2025
- Update default CodeQL bundle version to 2.21.0. [#2838](https://github.com/github/codeql-action/pull/2838)
## 3.28.13 - 24 Mar 2025
No user facing changes.

6
lib/analyze-action.js generated
View File

@@ -50,6 +50,7 @@ const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils");
const database_upload_1 = require("./database-upload");
const dependency_caching_1 = require("./dependency-caching");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const environment_1 = require("./environment");
const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages");
@@ -193,7 +194,10 @@ async function run() {
util.checkActionVersion(actionsUtil.getActionVersion(), gitHubVersion);
const features = new feature_flags_1.Features(gitHubVersion, repositoryNwo, actionsUtil.getTemporaryDirectory(), logger);
const memory = util.getMemoryFlag(actionsUtil.getOptionalInput("ram") || process.env["CODEQL_RAM"], logger);
const diffRangePackDir = await (0, analyze_1.setupDiffInformedQueryRun)(codeql, logger, features);
const branches = await (0, diff_informed_analysis_utils_1.getDiffInformedAnalysisBranches)(codeql, features, logger);
const diffRangePackDir = branches
? await (0, analyze_1.setupDiffInformedQueryRun)(branches, logger)
: undefined;
await (0, analyze_1.warnIfGoInstalledAfterInit)(config, logger);
await runAutobuildIfLegacyGoWorkflow(config, logger);
dbCreationTimings = await (0, analyze_1.runFinalize)(outputDir, threads, memory, codeql, config, logger);

File diff suppressed because one or more lines are too long

42
lib/analyze.js generated
View File

@@ -47,7 +47,6 @@ exports.runCleanup = runCleanup;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const perf_hooks_1 = require("perf_hooks");
const github = __importStar(require("@actions/github"));
const io = __importStar(require("@actions/io"));
const del_1 = __importDefault(require("del"));
const yaml = __importStar(require("js-yaml"));
@@ -57,7 +56,7 @@ const autobuild_1 = require("./autobuild");
const codeql_1 = require("./codeql");
const dependency_caching_1 = require("./dependency-caching");
const diagnostics_1 = require("./diagnostics");
const diff_filtering_utils_1 = require("./diff-filtering-utils");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const environment_1 = require("./environment");
const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages");
@@ -160,47 +159,13 @@ async function finalizeDatabaseCreation(codeql, config, threadsFlag, memoryFlag,
trap_import_duration_ms: Math.round(trapImportTime),
};
}
function getPullRequestBranches() {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label,
};
}
// PR analysis under Default Setup does not have the pull_request context,
// but it should set CODE_SCANNING_REF and CODE_SCANNING_BASE_BRANCH.
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef,
};
}
return undefined;
}
/**
* Set up the diff-informed analysis feature.
*
* @returns Absolute path to the directory containing the extension pack for
* the diff range information, or `undefined` if the feature is disabled.
*/
async function setupDiffInformedQueryRun(codeql, logger, features) {
if (!(await features.getValue(feature_flags_1.Feature.DiffInformedQueries, codeql))) {
return undefined;
}
const branches = getPullRequestBranches();
if (!branches) {
logger.info("Not performing diff-informed analysis " +
"because we are not analyzing a pull request.");
return undefined;
}
async function setupDiffInformedQueryRun(branches, logger) {
return await (0, logging_1.withGroupAsync)("Generating diff range extension pack", async () => {
logger.info(`Calculating diff ranges for ${branches.base}...${branches.head}`);
const diffRanges = await getPullRequestEditedDiffRanges(branches, logger);
@@ -393,6 +358,7 @@ extensions:
- addsTo:
pack: codeql/util
extensible: restrictAlertsTo
checkPresence: false
data:
`;
let data = ranges
@@ -414,7 +380,7 @@ extensions:
logger.debug(`Wrote pr-diff-range extension pack to ${extensionFilePath}:\n${extensionContents}`);
// Write the diff ranges to a JSON file, for action-side alert filtering by the
// upload-lib module.
(0, diff_filtering_utils_1.writeDiffRangesJsonFile)(logger, ranges);
(0, diff_informed_analysis_utils_1.writeDiffRangesJsonFile)(logger, ranges);
return diffRangeDir;
}
// Runs queries and creates sarif files in the given folder

File diff suppressed because one or more lines are too long

5
lib/api-client.js generated
View File

@@ -206,9 +206,14 @@ function wrapApiConfigurationError(e) {
if ((0, util_1.isHTTPError)(e)) {
if (e.message.includes("API rate limit exceeded for installation") ||
e.message.includes("commit not found") ||
e.message.includes("Resource not accessible by integration") ||
/ref .* not found in this repository/.test(e.message)) {
return new util_1.ConfigurationError(e.message);
}
else if (e.message.includes("Bad credentials") ||
e.message.includes("Not Found")) {
return new util_1.ConfigurationError("Please check that your token is valid and has the required permissions: contents: read, security-events: write");
}
}
return e;
}

File diff suppressed because one or more lines are too long

10
lib/api-client.test.js generated
View File

@@ -145,5 +145,15 @@ function mockGetMetaVersionHeader(versionHeader) {
const apiRateLimitError = new util.HTTPError("API rate limit exceeded for installation", 403);
res = api.wrapApiConfigurationError(apiRateLimitError);
t.deepEqual(res, new util.ConfigurationError("API rate limit exceeded for installation"));
const tokenSuggestionMessage = "Please check that your token is valid and has the required permissions: contents: read, security-events: write";
const badCredentialsError = new util.HTTPError("Bad credentials", 401);
res = api.wrapApiConfigurationError(badCredentialsError);
t.deepEqual(res, new util.ConfigurationError(tokenSuggestionMessage));
const notFoundError = new util.HTTPError("Not Found", 404);
res = api.wrapApiConfigurationError(notFoundError);
t.deepEqual(res, new util.ConfigurationError(tokenSuggestionMessage));
const resourceNotAccessibleError = new util.HTTPError("Resource not accessible by integration", 403);
res = api.wrapApiConfigurationError(resourceNotAccessibleError);
t.deepEqual(res, new util.ConfigurationError("Resource not accessible by integration"));
});
//# sourceMappingURL=api-client.test.js.map

File diff suppressed because one or more lines are too long

7
lib/codeql.js generated
View File

@@ -809,6 +809,13 @@ async function generateCodeScanningConfig(config, logger) {
if (Array.isArray(augmentedConfig.packs) && !augmentedConfig.packs.length) {
delete augmentedConfig.packs;
}
augmentedConfig["query-filters"] = [
...(config.augmentationProperties.defaultQueryFilters || []),
...(augmentedConfig["query-filters"] || []),
];
if (augmentedConfig["query-filters"]?.length === 0) {
delete augmentedConfig["query-filters"];
}
logger.info(`Writing augmented user configuration file to ${codeScanningConfigFile}`);
logger.startGroup("Augmented user configuration file contents");
logger.info(yaml.dump(augmentedConfig));

File diff suppressed because one or more lines are too long

16
lib/config-utils.js generated
View File

@@ -64,6 +64,7 @@ const yaml = __importStar(require("js-yaml"));
const semver = __importStar(require("semver"));
const api = __importStar(require("./api-client"));
const caching_utils_1 = require("./caching-utils");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const feature_flags_1 = require("./feature-flags");
const languages_1 = require("./languages");
const trap_caching_1 = require("./trap-caching");
@@ -79,6 +80,7 @@ exports.defaultAugmentationProperties = {
packsInputCombines: false,
packsInput: undefined,
queriesInput: undefined,
defaultQueryFilters: [],
};
function getPacksStrInvalid(packStr, configFile) {
return configFile
@@ -227,7 +229,7 @@ async function getRawLanguages(languagesInput, repository, logger) {
async function getDefaultConfig({ languagesInput, queriesInput, packsInput, buildModeInput, dbLocation, trapCachingEnabled, dependencyCachingEnabled, debugMode, debugArtifactName, debugDatabaseName, repository, tempDir, codeql, githubVersion, features, logger, }) {
const languages = await getLanguages(codeql, languagesInput, repository, logger);
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
const augmentationProperties = calculateAugmentation(packsInput, queriesInput, languages);
const augmentationProperties = await calculateAugmentation(codeql, features, packsInput, queriesInput, languages, logger);
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
return {
languages,
@@ -277,7 +279,7 @@ async function loadConfig({ languagesInput, queriesInput, packsInput, buildModeI
}
const languages = await getLanguages(codeql, languagesInput, repository, logger);
const buildMode = await parseBuildModeInput(buildModeInput, languages, features, logger);
const augmentationProperties = calculateAugmentation(packsInput, queriesInput, languages);
const augmentationProperties = await calculateAugmentation(codeql, features, packsInput, queriesInput, languages, logger);
const { trapCaches, trapCacheDownloadTime } = await downloadCacheWithTime(trapCachingEnabled, codeql, languages, logger);
return {
languages,
@@ -303,11 +305,14 @@ async function loadConfig({ languagesInput, queriesInput, packsInput, buildModeI
* and the CLI does not know about these inputs so we need to inject them into
* the config file sent to the CLI.
*
* @param codeql The CodeQL object.
* @param features The feature enablement object.
* @param rawPacksInput The packs input from the action configuration.
* @param rawQueriesInput The queries input from the action configuration.
* @param languages The languages that the config file is for. If the packs input
* is non-empty, then there must be exactly one language. Otherwise, an
* error is thrown.
* @param logger The logger to use for logging.
*
* @returns The properties that need to be augmented in the config file.
*
@@ -315,16 +320,21 @@ async function loadConfig({ languagesInput, queriesInput, packsInput, buildModeI
* not have exactly one language.
*/
// exported for testing.
function calculateAugmentation(rawPacksInput, rawQueriesInput, languages) {
async function calculateAugmentation(codeql, features, rawPacksInput, rawQueriesInput, languages, logger) {
const packsInputCombines = shouldCombine(rawPacksInput);
const packsInput = parsePacksFromInput(rawPacksInput, languages, packsInputCombines);
const queriesInputCombines = shouldCombine(rawQueriesInput);
const queriesInput = parseQueriesFromInput(rawQueriesInput, queriesInputCombines);
const defaultQueryFilters = [];
if (await (0, diff_informed_analysis_utils_1.shouldPerformDiffInformedAnalysis)(codeql, features, logger)) {
defaultQueryFilters.push({ exclude: { tags: "exclude-from-incremental" } });
}
return {
packsInputCombines,
packsInput: packsInput?.[languages[0]],
queriesInput,
queriesInputCombines,
defaultQueryFilters,
};
}
function parseQueriesFromInput(rawQueriesInput, queriesInputCombines) {

File diff suppressed because one or more lines are too long

View File

@@ -624,7 +624,7 @@ const packSpecPrettyPrintingMacro = ava_1.default.macro({
const mockLogger = (0, logging_1.getRunnerLogger)(true);
const calculateAugmentationMacro = ava_1.default.macro({
exec: async (t, _title, rawPacksInput, rawQueriesInput, languages, expectedAugmentationProperties) => {
const actualAugmentationProperties = configUtils.calculateAugmentation(rawPacksInput, rawQueriesInput, languages);
const actualAugmentationProperties = await configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, languages, mockLogger);
t.deepEqual(actualAugmentationProperties, expectedAugmentationProperties);
},
title: (_, title) => `Calculate Augmentation: ${title}`,
@@ -634,34 +634,39 @@ const calculateAugmentationMacro = ava_1.default.macro({
queriesInput: undefined,
packsInputCombines: false,
packsInput: undefined,
defaultQueryFilters: [],
});
(0, ava_1.default)(calculateAugmentationMacro, "With queries", undefined, " a, b , c, d", [languages_1.Language.javascript], {
queriesInputCombines: false,
queriesInput: [{ uses: "a" }, { uses: "b" }, { uses: "c" }, { uses: "d" }],
packsInputCombines: false,
packsInput: undefined,
defaultQueryFilters: [],
});
(0, ava_1.default)(calculateAugmentationMacro, "With queries combining", undefined, " + a, b , c, d ", [languages_1.Language.javascript], {
queriesInputCombines: true,
queriesInput: [{ uses: "a" }, { uses: "b" }, { uses: "c" }, { uses: "d" }],
packsInputCombines: false,
packsInput: undefined,
defaultQueryFilters: [],
});
(0, ava_1.default)(calculateAugmentationMacro, "With packs", " codeql/a , codeql/b , codeql/c , codeql/d ", undefined, [languages_1.Language.javascript], {
queriesInputCombines: false,
queriesInput: undefined,
packsInputCombines: false,
packsInput: ["codeql/a", "codeql/b", "codeql/c", "codeql/d"],
defaultQueryFilters: [],
});
(0, ava_1.default)(calculateAugmentationMacro, "With packs combining", " + codeql/a, codeql/b, codeql/c, codeql/d", undefined, [languages_1.Language.javascript], {
queriesInputCombines: false,
queriesInput: undefined,
packsInputCombines: true,
packsInput: ["codeql/a", "codeql/b", "codeql/c", "codeql/d"],
defaultQueryFilters: [],
});
const calculateAugmentationErrorMacro = ava_1.default.macro({
exec: async (t, _title, rawPacksInput, rawQueriesInput, languages, expectedError) => {
t.throws(() => configUtils.calculateAugmentation(rawPacksInput, rawQueriesInput, languages), { message: expectedError });
await t.throwsAsync(() => configUtils.calculateAugmentation((0, codeql_1.getCachedCodeQL)(), (0, testing_utils_1.createFeatures)([]), rawPacksInput, rawQueriesInput, languages, mockLogger), { message: expectedError });
},
title: (_, title) => `Calculate Augmentation Error: ${title}`,
});

File diff suppressed because one or more lines are too long

19
lib/debug-artifacts.js generated
View File

@@ -46,7 +46,7 @@ const path = __importStar(require("path"));
const artifact = __importStar(require("@actions/artifact"));
const artifactLegacy = __importStar(require("@actions/artifact-legacy"));
const core = __importStar(require("@actions/core"));
const adm_zip_1 = __importDefault(require("adm-zip"));
const archiver_1 = __importDefault(require("archiver"));
const del_1 = __importDefault(require("del"));
const actions_util_1 = require("./actions-util");
const analyze_1 = require("./analyze");
@@ -250,9 +250,20 @@ async function createPartialDatabaseBundle(config, language) {
if (fs.existsSync(databaseBundlePath)) {
await (0, del_1.default)(databaseBundlePath, { force: true });
}
const zip = new adm_zip_1.default();
zip.addLocalFolder(databasePath);
zip.writeZip(databaseBundlePath);
const output = fs.createWriteStream(databaseBundlePath);
const zip = (0, archiver_1.default)("zip");
zip.on("error", (err) => {
throw err;
});
zip.on("warning", (err) => {
// Ignore ENOENT warnings. There's nothing anyone can do about it.
if (err.code !== "ENOENT") {
throw err;
}
});
zip.pipe(output);
zip.directory(databasePath, false);
await zip.finalize();
return databaseBundlePath;
}
/**

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"bundleVersion": "codeql-bundle-v2.20.7",
"cliVersion": "2.20.7",
"priorBundleVersion": "codeql-bundle-v2.20.6",
"priorCliVersion": "2.20.6"
"bundleVersion": "codeql-bundle-v2.21.1",
"cliVersion": "2.21.1",
"priorBundleVersion": "codeql-bundle-v2.21.0",
"priorCliVersion": "2.21.0"
}

View File

@@ -1 +0,0 @@
{"version":3,"file":"diff-filtering-utils.js","sourceRoot":"","sources":["../src/diff-filtering-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,0DAUC;AAED,wDAaC;AAzCD,uCAAyB;AACzB,2CAA6B;AAE7B,4DAA8C;AAS9C,SAAS,yBAAyB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,qBAAqB,EAAE,EAAE,oBAAoB,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,uBAAuB,CACrC,MAAc,EACd,MAAwB;IAExB,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,yBAAyB,EAAE,CAAC;IACjD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CACV,oCAAoC,YAAY,MAAM,YAAY,EAAE,CACrE,CAAC;AACJ,CAAC;AAED,SAAgB,sBAAsB,CACpC,MAAc;IAEd,MAAM,YAAY,GAAG,yBAAyB,EAAE,CAAC;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,2CAA2C,YAAY,EAAE,CAAC,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,CACV,qCAAqC,YAAY,MAAM,YAAY,EAAE,CACtE,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAqB,CAAC;AACtD,CAAC"}

View File

@@ -33,11 +33,65 @@ var __importStar = (this && this.__importStar) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.shouldPerformDiffInformedAnalysis = shouldPerformDiffInformedAnalysis;
exports.getDiffInformedAnalysisBranches = getDiffInformedAnalysisBranches;
exports.writeDiffRangesJsonFile = writeDiffRangesJsonFile;
exports.readDiffRangesJsonFile = readDiffRangesJsonFile;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const github = __importStar(require("@actions/github"));
const actionsUtil = __importStar(require("./actions-util"));
const feature_flags_1 = require("./feature-flags");
function getPullRequestBranches() {
const pullRequest = github.context.payload.pull_request;
if (pullRequest) {
return {
base: pullRequest.base.ref,
// We use the head label instead of the head ref here, because the head
// ref lacks owner information and by itself does not uniquely identify
// the head branch (which may be in a forked repository).
head: pullRequest.head.label,
};
}
// PR analysis under Default Setup does not have the pull_request context,
// but it should set CODE_SCANNING_REF and CODE_SCANNING_BASE_BRANCH.
const codeScanningRef = process.env.CODE_SCANNING_REF;
const codeScanningBaseBranch = process.env.CODE_SCANNING_BASE_BRANCH;
if (codeScanningRef && codeScanningBaseBranch) {
return {
base: codeScanningBaseBranch,
// PR analysis under Default Setup analyzes the PR head commit instead of
// the merge commit, so we can use the provided ref directly.
head: codeScanningRef,
};
}
return undefined;
}
/**
* Check if the action should perform diff-informed analysis.
*/
async function shouldPerformDiffInformedAnalysis(codeql, features, logger) {
return ((await getDiffInformedAnalysisBranches(codeql, features, logger)) !==
undefined);
}
/**
* Get the branches to use for diff-informed analysis.
*
* @returns If the action should perform diff-informed analysis, return
* the base and head branches that should be used to compute the diff ranges.
* Otherwise return `undefined`.
*/
async function getDiffInformedAnalysisBranches(codeql, features, logger) {
if (!(await features.getValue(feature_flags_1.Feature.DiffInformedQueries, codeql))) {
return undefined;
}
const branches = getPullRequestBranches();
if (!branches) {
logger.info("Not performing diff-informed analysis " +
"because we are not analyzing a pull request.");
}
return branches;
}
function getDiffRangesJsonFilePath() {
return path.join(actionsUtil.getTemporaryDirectory(), "pr-diff-range.json");
}
@@ -57,4 +111,4 @@ function readDiffRangesJsonFile(logger) {
logger.debug(`Read pr-diff-range JSON file from ${jsonFilePath}:\n${jsonContents}`);
return JSON.parse(jsonContents);
}
//# sourceMappingURL=diff-filtering-utils.js.map
//# sourceMappingURL=diff-informed-analysis-utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"diff-informed-analysis-utils.js","sourceRoot":"","sources":["../src/diff-informed-analysis-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,8EASC;AASD,0EAiBC;AAYD,0DAUC;AAED,wDAaC;AArHD,uCAAyB;AACzB,2CAA6B;AAE7B,wDAA0C;AAE1C,4DAA8C;AAE9C,mDAA6D;AAQ7D,SAAS,sBAAsB;IAC7B,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC;IACxD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO;YACL,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG;YAC1B,uEAAuE;YACvE,uEAAuE;YACvE,yDAAyD;YACzD,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK;SAC7B,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,qEAAqE;IACrE,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACtD,MAAM,sBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;IACrE,IAAI,eAAe,IAAI,sBAAsB,EAAE,CAAC;QAC9C,OAAO;YACL,IAAI,EAAE,sBAAsB;YAC5B,yEAAyE;YACzE,6DAA6D;YAC7D,IAAI,EAAE,eAAe;SACtB,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,iCAAiC,CACrD,MAAc,EACd,QAA2B,EAC3B,MAAc;IAEd,OAAO,CACL,CAAC,MAAM,+BAA+B,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjE,SAAS,CACV,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,+BAA+B,CACnD,MAAc,EACd,QAA2B,EAC3B,MAAc;IAEd,IAAI,CAAC,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,uBAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CACT,wCAAwC;YACtC,8CAA8C,CACjD,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD,SAAS,yBAAyB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,qBAAqB,EAAE,EAAE,oBAAoB,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,uBAAuB,CACrC,MAAc,EACd,MAAwB;IAExB,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,yBAAyB,EAAE,CAAC;IACjD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CACV,oCAAoC,YAAY,MAAM,YAAY,EAAE,CACrE,CAAC;AACJ,CAAC;AAED,SAAgB,sBAAsB,CACpC,MAAc;IAEd,MAAM,YAAY,GAAG,yBAAyB,EAAE,CAAC;IACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,2CAA2C,YAAY,EAAE,CAAC,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,CAAC,KAAK,CACV,qCAAqC,YAAY,MAAM,YAAY,EAAE,CACtE,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAqB,CAAC;AACtD,CAAC"}

3
lib/feature-flags.js generated
View File

@@ -96,8 +96,7 @@ exports.featureConfig = {
[Feature.DiffInformedQueries]: {
defaultValue: false,
envVar: "CODEQL_ACTION_DIFF_INFORMED_QUERIES",
minimumVersion: undefined,
toolsFeature: tools_features_1.ToolsFeature.DatabaseInterpretResultsSupportsSarifRunProperty,
minimumVersion: "2.21.0",
},
[Feature.DisableCsharpBuildless]: {
defaultValue: false,

File diff suppressed because one or more lines are too long

View File

@@ -87,7 +87,9 @@ async function runWrapper() {
...uploadFailedSarifResult,
job_status: initActionPostHelper.getFinalJobStatus(),
};
logger.info("Sending status report for init-post step.");
await (0, status_report_1.sendStatusReport)(statusReport);
logger.info("Status report sent for init-post step.");
}
}
void runWrapper();

View File

@@ -1 +1 @@
{"version":3,"file":"init-action-post.js","sourceRoot":"","sources":["../src/init-action-post.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,oDAAsC;AAEtC,iDAIwB;AACxB,6CAAgD;AAChD,iDAAmD;AACnD,kEAAoD;AACpD,mDAA2C;AAC3C,gFAAkE;AAClE,uCAA6C;AAC7C,6CAAgD;AAChD,mDAOyB;AACzB,iCAA8E;AAO9E,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,IAAI,MAA0B,CAAC;IAC/B,IAAI,uBAES,CAAC;IACd,IAAI,CAAC;QACH,qCAAqC;QACrC,IAAA,4BAAa,GAAE,CAAC;QAEhB,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,MAAM,aAAa,GAAG,IAAA,6BAAgB,GAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,wBAAQ,CAC3B,aAAa,EACb,aAAa,EACb,IAAA,oCAAqB,GAAE,EACvB,MAAM,CACP,CAAC;QAEF,MAAM,GAAG,MAAM,IAAA,wBAAS,EAAC,IAAA,oCAAqB,GAAE,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,OAAO,CACZ,iGAAiG,CAClG,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,uBAAuB,GAAG,MAAM,oBAAoB,CAAC,GAAG,CACtD,cAAc,CAAC,mCAAmC,EAClD,6BAAc,EACd,MAAM,EACN,aAAa,EACb,QAAQ,EACR,MAAM,CACP,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,IAAA,gBAAS,EAAC,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE9B,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,QAAQ,EACnB,IAAA,gCAAgB,EAAC,KAAK,CAAC,EACvB,SAAS,EACT,MAAM,EACN,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,EACN,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,KAAK,CACZ,CAAC;QACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAA,gCAAgB,EAAC,gBAAgB,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,SAAS,GAAG,oBAAoB,CAAC,iBAAiB,EAAE,CAAC;IAC3D,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAA,uCAAuB,EAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAE5E,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,QAAQ,EACnB,SAAS,EACT,SAAS,EACT,MAAM,EACN,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAAyB;YACzC,GAAG,gBAAgB;YACnB,GAAG,uBAAuB;YAC1B,UAAU,EAAE,oBAAoB,CAAC,iBAAiB,EAAE;SACrD,CAAC;QACF,MAAM,IAAA,gCAAgB,EAAC,YAAY,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
{"version":3,"file":"init-action-post.js","sourceRoot":"","sources":["../src/init-action-post.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,oDAAsC;AAEtC,iDAIwB;AACxB,6CAAgD;AAChD,iDAAmD;AACnD,kEAAoD;AACpD,mDAA2C;AAC3C,gFAAkE;AAClE,uCAA6C;AAC7C,6CAAgD;AAChD,mDAOyB;AACzB,iCAA8E;AAO9E,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,IAAI,MAA0B,CAAC;IAC/B,IAAI,uBAES,CAAC;IACd,IAAI,CAAC;QACH,qCAAqC;QACrC,IAAA,4BAAa,GAAE,CAAC;QAEhB,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;QAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAEjD,MAAM,aAAa,GAAG,IAAA,6BAAgB,GAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,wBAAQ,CAC3B,aAAa,EACb,aAAa,EACb,IAAA,oCAAqB,GAAE,EACvB,MAAM,CACP,CAAC;QAEF,MAAM,GAAG,MAAM,IAAA,wBAAS,EAAC,IAAA,oCAAqB,GAAE,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,OAAO,CACZ,iGAAiG,CAClG,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,uBAAuB,GAAG,MAAM,oBAAoB,CAAC,GAAG,CACtD,cAAc,CAAC,mCAAmC,EAClD,6BAAc,EACd,MAAM,EACN,aAAa,EACb,QAAQ,EACR,MAAM,CACP,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,IAAA,gBAAS,EAAC,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE9B,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,QAAQ,EACnB,IAAA,gCAAgB,EAAC,KAAK,CAAC,EACvB,SAAS,EACT,MAAM,EACN,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,EACN,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,KAAK,CACZ,CAAC;QACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAA,gCAAgB,EAAC,gBAAgB,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,SAAS,GAAG,oBAAoB,CAAC,iBAAiB,EAAE,CAAC;IAC3D,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAA,uCAAuB,EAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAE5E,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,QAAQ,EACnB,SAAS,EACT,SAAS,EACT,MAAM,EACN,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAAyB;YACzC,GAAG,gBAAgB;YACnB,GAAG,uBAAuB;YAC1B,UAAU,EAAE,oBAAoB,CAAC,iBAAiB,EAAE;SACrD,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QACzD,MAAM,IAAA,gCAAgB,EAAC,YAAY,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}

View File

@@ -53,7 +53,12 @@ async function runWrapper() {
// Kill the running proxy
const pid = core.getState("proxy-process-pid");
if (pid) {
process.kill(Number(pid));
try {
process.kill(Number(pid));
}
catch (error) {
logger.error(`Failed to kill proxy process: ${(0, util_1.getErrorMessage)(error)}`);
}
}
const config = await configUtils.getConfig(actionsUtil.getTemporaryDirectory(), logger);
if ((config && config.debugMode) || core.isDebug()) {

View File

@@ -1 +1 @@
{"version":3,"file":"start-proxy-action-post.js","sourceRoot":"","sources":["../src/start-proxy-action-post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,oDAAsC;AAEtC,4DAA8C;AAC9C,6CAAgD;AAChD,4DAA8C;AAC9C,uDAA8D;AAC9D,uCAA6C;AAC7C,iCAAoE;AAEpE,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAElC,IAAI,CAAC;QACH,4CAA4C;QAC5C,WAAW,CAAC,aAAa,EAAE,CAAC;QAE5B,yBAAyB;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAC/C,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CACxC,WAAW,CAAC,qBAAqB,EAAE,EACnC,MAAM,CACP,CAAC;QAEF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACnD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YACpD,MAAM,CAAC,IAAI,CACT,wEAAwE,CACzE,CAAC;YACF,IAAI,MAAM,EAAE,aAAa,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7C,MAAM,CAAC,OAAO,CACZ,qFAAqF,CACtF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;YAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAEjD,MAAM,gBAAgB,GAAG,MAAM,IAAA,2CAAyB,EACtD,MAAM,EACN,aAAa,CAAC,IAAI,CACnB,CAAC;YAEF,MAAM,gBAAgB,CAAC,cAAc,CACnC,gBAAgB,EAChB,CAAC,WAAW,CAAC,EACb,WAAW,CAAC,qBAAqB,EAAE,EACnC;gBACE,wFAAwF;gBACxF,aAAa,EAAE,CAAC;aACjB,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gEAAgE;QAChE,MAAM,CAAC,OAAO,CACZ,wCAAwC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CACjE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
{"version":3,"file":"start-proxy-action-post.js","sourceRoot":"","sources":["../src/start-proxy-action-post.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;GAIG;AACH,oDAAsC;AAEtC,4DAA8C;AAC9C,6CAAgD;AAChD,4DAA8C;AAC9C,uDAA8D;AAC9D,uCAA6C;AAC7C,iCAAoE;AAEpE,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAElC,IAAI,CAAC;QACH,4CAA4C;QAC5C,WAAW,CAAC,aAAa,EAAE,CAAC;QAE5B,yBAAyB;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAC/C,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,iCAAiC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CACxC,WAAW,CAAC,qBAAqB,EAAE,EACnC,MAAM,CACP,CAAC;QAEF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACnD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;YACpD,MAAM,CAAC,IAAI,CACT,wEAAwE,CACzE,CAAC;YACF,IAAI,MAAM,EAAE,aAAa,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC7C,MAAM,CAAC,OAAO,CACZ,qFAAqF,CACtF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;YAC/C,IAAA,gCAAyB,EAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAEjD,MAAM,gBAAgB,GAAG,MAAM,IAAA,2CAAyB,EACtD,MAAM,EACN,aAAa,CAAC,IAAI,CACnB,CAAC;YAEF,MAAM,gBAAgB,CAAC,cAAc,CACnC,gBAAgB,EAChB,CAAC,WAAW,CAAC,EACb,WAAW,CAAC,qBAAqB,EAAE,EACnC;gBACE,wFAAwF;gBACxF,aAAa,EAAE,CAAC;aACjB,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gEAAgE;QAChE,MAAM,CAAC,OAAO,CACZ,wCAAwC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CACjE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}

View File

@@ -43,8 +43,8 @@ const logging_1 = require("./logging");
const start_proxy_1 = require("./start-proxy");
const util = __importStar(require("./util"));
const UPDATEJOB_PROXY = "update-job-proxy";
const UPDATEJOB_PROXY_VERSION = "v2.0.20241023203727";
const UPDATEJOB_PROXY_URL_PREFIX = "https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.18.1/";
const UPDATEJOB_PROXY_VERSION = "v2.0.20250424171100";
const UPDATEJOB_PROXY_URL_PREFIX = "https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.21.1/";
const KEY_SIZE = 2048;
const KEY_EXPIRY_YEARS = 2;
const CERT_SUBJECT = [
@@ -112,7 +112,8 @@ async function runWrapper() {
ca,
};
// Start the Proxy
const proxyBin = await getProxyBinaryPath();
const proxyBin = actionsUtil.getOptionalInput("proxy_binary") ??
(await getProxyBinaryPath());
await startProxy(proxyBin, proxyConfig, proxyLogFilePath, logger);
}
async function startProxy(binPath, config, logFilePath, logger) {

File diff suppressed because one or more lines are too long

7
lib/status-report.js generated
View File

@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
Object.defineProperty(exports, "__esModule", { value: true });
exports.JobStatus = exports.ActionName = void 0;
exports.isFirstPartyAnalysis = isFirstPartyAnalysis;
exports.isThirdPartyAnalysis = isThirdPartyAnalysis;
exports.getActionsStatus = getActionsStatus;
exports.getJobStatusDisplayName = getJobStatusDisplayName;
exports.createStatusReportBase = createStatusReportBase;
@@ -71,6 +72,12 @@ function isFirstPartyAnalysis(actionName) {
}
return process.env[environment_1.EnvVar.INIT_ACTION_HAS_RUN] === "true";
}
/**
* @returns true if the analysis is considered to be third party.
*/
function isThirdPartyAnalysis(actionName) {
return !isFirstPartyAnalysis(actionName);
}
/** Overall status of the entire job. String values match the Hydro schema. */
var JobStatus;
(function (JobStatus) {

File diff suppressed because one or more lines are too long

View File

@@ -113,7 +113,7 @@ function setupEnvironmentAndStub(tmpDir) {
t.is((0, status_report_1.getActionsStatus)(new Error("arbitrary error")), "failure", "We categorise an arbitrary error as a failure");
t.is((0, status_report_1.getActionsStatus)(new util_1.ConfigurationError("arbitrary error")), "user-error", "We categorise a ConfigurationError as a user error");
t.is((0, status_report_1.getActionsStatus)(new Error("exit code 1"), "multiple things went wrong"), "failure", "getActionsStatus should return failure if passed an arbitrary error and an additional failure cause");
t.is((0, status_report_1.getActionsStatus)(new util_1.ConfigurationError("exit code 1"), "multiple things went wrong"), "user-error", "getActionsStatus should return failure if passed a configuration error and an additional failure cause");
t.is((0, status_report_1.getActionsStatus)(new util_1.ConfigurationError("exit code 1"), "multiple things went wrong"), "user-error", "getActionsStatus should return user-error if passed a configuration error and an additional failure cause");
t.is((0, status_report_1.getActionsStatus)(), "success", "getActionsStatus should return success if no error is passed");
t.is((0, status_report_1.getActionsStatus)(new Object()), "failure", "getActionsStatus should return failure if passed an arbitrary object");
t.is((0, status_report_1.getActionsStatus)(null, "an error occurred"), "failure", "getActionsStatus should return failure if passed null and an additional failure cause");

File diff suppressed because one or more lines are too long

27
lib/upload-lib.js generated
View File

@@ -44,6 +44,8 @@ exports.validateSarifFileSchema = validateSarifFileSchema;
exports.buildPayload = buildPayload;
exports.uploadFiles = uploadFiles;
exports.waitForProcessing = waitForProcessing;
exports.shouldConsiderConfigurationError = shouldConsiderConfigurationError;
exports.shouldConsiderInvalidRequest = shouldConsiderInvalidRequest;
exports.validateUniqueCategory = validateUniqueCategory;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
@@ -58,7 +60,7 @@ const api = __importStar(require("./api-client"));
const api_client_1 = require("./api-client");
const codeql_1 = require("./codeql");
const config_utils_1 = require("./config-utils");
const diff_filtering_utils_1 = require("./diff-filtering-utils");
const diff_informed_analysis_utils_1 = require("./diff-informed-analysis-utils");
const environment_1 = require("./environment");
const fingerprints = __importStar(require("./fingerprints"));
const gitUtils = __importStar(require("./git-utils"));
@@ -408,9 +410,17 @@ async function uploadFiles(sarifPath, checkoutPath, category, features, logger)
logger.startGroup("Uploading results");
logger.info(`Processing sarif files: ${JSON.stringify(sarifFiles)}`);
const gitHubVersion = await (0, api_client_1.getGitHubVersion)();
// Validate that the files we were asked to upload are all valid SARIF files
for (const file of sarifFiles) {
validateSarifFileSchema(file, logger);
try {
// Validate that the files we were asked to upload are all valid SARIF files
for (const file of sarifFiles) {
validateSarifFileSchema(file, logger);
}
}
catch (e) {
if (e instanceof SyntaxError) {
throw new InvalidSarifUploadError(e.message);
}
throw e;
}
let sarif = await combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger);
sarif = filterAlertsByDiffRange(logger, sarif);
@@ -524,9 +534,12 @@ async function waitForProcessing(repositoryNwo, sarifID, logger, options = {
* Returns whether the provided processing errors are a configuration error.
*/
function shouldConsiderConfigurationError(processingErrors) {
const expectedConfigErrors = [
"CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled",
"rejecting delivery as the repository has too many logical alerts",
];
return (processingErrors.length === 1 &&
processingErrors[0] ===
"CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled");
expectedConfigErrors.some((msg) => processingErrors[0].includes(msg)));
}
/**
* Returns whether the provided processing errors are the result of an invalid SARIF upload request.
@@ -610,7 +623,7 @@ class InvalidSarifUploadError extends Error {
}
exports.InvalidSarifUploadError = InvalidSarifUploadError;
function filterAlertsByDiffRange(logger, sarif) {
const diffRanges = (0, diff_filtering_utils_1.readDiffRangesJsonFile)(logger);
const diffRanges = (0, diff_informed_analysis_utils_1.readDiffRangesJsonFile)(logger);
if (!diffRanges?.length) {
return sarif;
}

File diff suppressed because one or more lines are too long

35
lib/upload-lib.test.js generated
View File

@@ -244,6 +244,41 @@ ava_1.default.beforeEach(() => {
type: util_1.GitHubVariant.DOTCOM,
}));
});
(0, ava_1.default)("shouldConsiderConfigurationError correctly detects configuration errors", (t) => {
const error1 = [
"CodeQL analyses from advanced configurations cannot be processed when the default setup is enabled",
];
t.true(uploadLib.shouldConsiderConfigurationError(error1));
const error2 = [
"rejecting delivery as the repository has too many logical alerts",
];
t.true(uploadLib.shouldConsiderConfigurationError(error2));
// We fail cases where we get > 1 error messages back
const error3 = [
"rejecting delivery as the repository has too many alerts",
"extra error message",
];
t.false(uploadLib.shouldConsiderConfigurationError(error3));
});
(0, ava_1.default)("shouldConsiderInvalidRequest returns correct recognises processing errors", (t) => {
const error1 = [
"rejecting SARIF",
"an invalid URI was provided as a SARIF location",
];
t.true(uploadLib.shouldConsiderInvalidRequest(error1));
const error2 = [
"locationFromSarifResult: expected artifact location",
"an invalid URI was provided as a SARIF location",
];
t.true(uploadLib.shouldConsiderInvalidRequest(error2));
// We expect ALL errors to be of processing errors, for the outcome to be classified as
// an invalid SARIF upload error.
const error3 = [
"could not convert rules: invalid security severity value, is not a number",
"an unknown error occurred",
];
t.false(uploadLib.shouldConsiderInvalidRequest(error3));
});
function createMockSarif(id, tool) {
return {
runs: [

File diff suppressed because one or more lines are too long

View File

@@ -80,7 +80,7 @@ async function run() {
await sendSuccessStatusReport(startedAt, uploadResult.statusReport, logger);
}
catch (unwrappedError) {
const error = !(0, status_report_1.isFirstPartyAnalysis)(status_report_1.ActionName.UploadSarif) &&
const error = (0, status_report_1.isThirdPartyAnalysis)(status_report_1.ActionName.UploadSarif) &&
unwrappedError instanceof upload_lib.InvalidSarifUploadError
? new util_1.ConfigurationError(unwrappedError.message)
: (0, util_1.wrapError)(unwrappedError);

View File

@@ -1 +1 @@
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAsC;AAEtC,4DAA8C;AAC9C,iDAAyE;AACzE,6CAAgD;AAChD,mDAA2C;AAC3C,uCAAqD;AACrD,6CAAgD;AAChD,mDAOyB;AACzB,yDAA2C;AAC3C,iCAQgB;AAMhB,KAAK,UAAU,uBAAuB,CACpC,SAAe,EACf,WAA0C,EAC1C,MAAc;IAEd,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,WAAW,EACtB,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAA4B;YAC5C,GAAG,gBAAgB;YACnB,GAAG,WAAW;SACf,CAAC;QACF,MAAM,IAAA,gCAAgB,EAAC,YAAY,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,IAAA,4BAAqB,EAAC,IAAA,+BAAgB,GAAE,CAAC,CAAC;IAE1C,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;IAC/C,IAAA,yBAAkB,EAAC,IAAA,+BAAgB,GAAE,EAAE,aAAa,CAAC,CAAC;IAEtD,6CAA6C;IAC7C,WAAW,CAAC,aAAa,EAAE,CAAC;IAE5B,MAAM,aAAa,GAAG,IAAA,6BAAgB,GAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,wBAAQ,CAC3B,aAAa,EACb,aAAa,EACb,IAAA,oCAAqB,GAAE,EACvB,MAAM,CACP,CAAC;IAEF,MAAM,wBAAwB,GAAG,MAAM,IAAA,sCAAsB,EAC3D,0BAAU,CAAC,WAAW,EACtB,UAAU,EACV,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,wBAAwB,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAA,gCAAgB,EAAC,wBAAwB,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,WAAW,CAC/C,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAC1C,WAAW,CAAC,gBAAgB,CAAC,eAAe,CAAC,EAC7C,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACxC,QAAQ,EACR,MAAM,CACP,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QAEjD,qEAAqE;QACrE,IAAI,IAAA,mBAAY,GAAE,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,WAAW,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,KAAK,MAAM,EAAE,CAAC;YAC1E,MAAM,UAAU,CAAC,iBAAiB,CAChC,IAAA,6BAAgB,GAAE,EAClB,YAAY,CAAC,OAAO,EACpB,MAAM,CACP,CAAC;QACJ,CAAC;QACD,MAAM,uBAAuB,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GACT,CAAC,IAAA,oCAAoB,EAAC,0BAAU,CAAC,WAAW,CAAC;YAC7C,cAAc,YAAY,UAAU,CAAC,uBAAuB;YAC1D,CAAC,CAAC,IAAI,yBAAkB,CAAC,cAAc,CAAC,OAAO,CAAC;YAChD,CAAC,CAAC,IAAA,gBAAS,EAAC,cAAc,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,qBAAqB,GAAG,MAAM,IAAA,sCAAsB,EACxD,0BAAU,CAAC,WAAW,EACtB,IAAA,gCAAgB,EAAC,KAAK,CAAC,EACvB,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,KAAK,CAAC,KAAK,CACZ,CAAC;QACF,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,IAAA,gCAAgB,EAAC,qBAAqB,CAAC,CAAC;QAChD,CAAC;QACD,OAAO;IACT,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,sCAAsC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAC/D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}
{"version":3,"file":"upload-sarif-action.js","sourceRoot":"","sources":["../src/upload-sarif-action.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAsC;AAEtC,4DAA8C;AAC9C,iDAAyE;AACzE,6CAAgD;AAChD,mDAA2C;AAC3C,uCAAqD;AACrD,6CAAgD;AAChD,mDAOyB;AACzB,yDAA2C;AAC3C,iCAQgB;AAMhB,KAAK,UAAU,uBAAuB,CACpC,SAAe,EACf,WAA0C,EAC1C,MAAc;IAEd,MAAM,gBAAgB,GAAG,MAAM,IAAA,sCAAsB,EACnD,0BAAU,CAAC,WAAW,EACtB,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,YAAY,GAA4B;YAC5C,GAAG,gBAAgB;YACnB,GAAG,WAAW;SACf,CAAC;QACF,MAAM,IAAA,gCAAgB,EAAC,YAAY,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,IAAA,0BAAgB,GAAE,CAAC;IAClC,IAAA,4BAAqB,EAAC,IAAA,+BAAgB,GAAE,CAAC,CAAC;IAE1C,MAAM,aAAa,GAAG,MAAM,IAAA,6BAAgB,GAAE,CAAC;IAC/C,IAAA,yBAAkB,EAAC,IAAA,+BAAgB,GAAE,EAAE,aAAa,CAAC,CAAC;IAEtD,6CAA6C;IAC7C,WAAW,CAAC,aAAa,EAAE,CAAC;IAE5B,MAAM,aAAa,GAAG,IAAA,6BAAgB,GAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,wBAAQ,CAC3B,aAAa,EACb,aAAa,EACb,IAAA,oCAAqB,GAAE,EACvB,MAAM,CACP,CAAC;IAEF,MAAM,wBAAwB,GAAG,MAAM,IAAA,sCAAsB,EAC3D,0BAAU,CAAC,WAAW,EACtB,UAAU,EACV,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,CACP,CAAC;IACF,IAAI,wBAAwB,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAA,gCAAgB,EAAC,wBAAwB,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,UAAU,CAAC,WAAW,CAC/C,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAC1C,WAAW,CAAC,gBAAgB,CAAC,eAAe,CAAC,EAC7C,WAAW,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACxC,QAAQ,EACR,MAAM,CACP,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QAEjD,qEAAqE;QACrE,IAAI,IAAA,mBAAY,GAAE,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAClE,CAAC;aAAM,IAAI,WAAW,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,KAAK,MAAM,EAAE,CAAC;YAC1E,MAAM,UAAU,CAAC,iBAAiB,CAChC,IAAA,6BAAgB,GAAE,EAClB,YAAY,CAAC,OAAO,EACpB,MAAM,CACP,CAAC;QACJ,CAAC;QACD,MAAM,uBAAuB,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9E,CAAC;IAAC,OAAO,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GACT,IAAA,oCAAoB,EAAC,0BAAU,CAAC,WAAW,CAAC;YAC5C,cAAc,YAAY,UAAU,CAAC,uBAAuB;YAC1D,CAAC,CAAC,IAAI,yBAAkB,CAAC,cAAc,CAAC,OAAO,CAAC;YAChD,CAAC,CAAC,IAAA,gBAAS,EAAC,cAAc,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAExB,MAAM,qBAAqB,GAAG,MAAM,IAAA,sCAAsB,EACxD,0BAAU,CAAC,WAAW,EACtB,IAAA,gCAAgB,EAAC,KAAK,CAAC,EACvB,SAAS,EACT,SAAS,EACT,MAAM,IAAA,qBAAc,EAAC,MAAM,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,KAAK,CAAC,KAAK,CACZ,CAAC;QACF,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,IAAA,gCAAgB,EAAC,qBAAqB,CAAC,CAAC;QAChD,CAAC;QACD,OAAO;IACT,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,SAAS,CACZ,sCAAsC,IAAA,sBAAe,EAAC,KAAK,CAAC,EAAE,CAC/D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,EAAE,CAAC"}

1
node_modules/.bin/tldts generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../tldts/bin/cli.js

839
node_modules/.package-lock.json generated vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,21 @@
MIT License
Copyright (c) 2012 Another-D-Mention Software and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
MIT License
Copyright (c) 2024 asamuzaK (Kazz)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

316
node_modules/@asamuzakjp/css-color/README.md generated vendored Normal file
View File

@@ -0,0 +1,316 @@
# CSS color
[![build](https://github.com/asamuzaK/cssColor/actions/workflows/node.js.yml/badge.svg)](https://github.com/asamuzaK/cssColor/actions/workflows/node.js.yml)
[![CodeQL](https://github.com/asamuzaK/cssColor/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/asamuzaK/cssColor/actions/workflows/github-code-scanning/codeql)
[![npm (scoped)](https://img.shields.io/npm/v/@asamuzakjp/css-color)](https://www.npmjs.com/package/@asamuzakjp/css-color)
Resolve and convert CSS colors.
## Install
```console
npm i @asamuzakjp/css-color
```
## Usage
```javascript
import { convert, resolve, utils } from '@asamuzakjp/css-color';
const resolvedValue = resolve(
'color-mix(in oklab, lch(67.5345 42.5 258.2), color(srgb 0 0.5 0))'
);
// 'oklab(0.620754 -0.0931934 -0.00374881)'
const convertedValue = covert.colorToHex('lab(46.2775% -47.5621 48.5837)');
// '#008000'
const result = utils.isColor('green');
// true
```
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### resolve(color, opt)
resolves CSS color
#### Parameters
- `color` **[string][133]** color value
- system colors are not supported
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.currentColor` **[string][133]?**
- color to use for `currentcolor` keyword
- if omitted, it will be treated as a missing color,
i.e. `rgb(none none none / none)`
- `opt.customProperty` **[object][135]?**
- custom properties
- pair of `--` prefixed property name as a key and it's value,
e.g.
```javascript
const opt = {
customProperty: {
'--some-color': '#008000',
'--some-length': '16px'
}
};
```
- and/or `callback` function to get the value of the custom property,
e.g.
```javascript
const node = document.getElementById('foo');
const opt = {
customProperty: {
callback: node.style.getPropertyValue
}
};
```
- `opt.dimension` **[object][135]?**
- dimension, e.g. for converting relative length to pixels
- pair of unit as a key and number in pixels as it's value,
e.g. suppose `1em === 12px`, `1rem === 16px` and `100vw === 1024px`, then
```javascript
const opt = {
dimension: {
em: 12,
rem: 16,
vw: 10.24
}
};
```
- and/or `callback` function to get the value as a number in pixels,
e.g.
```javascript
const opt = {
dimension: {
callback: unit => {
switch (unit) {
case 'em':
return 12;
case 'rem':
return 16;
case 'vw':
return 10.24;
default:
return;
}
}
}
};
```
- `opt.format` **[string][133]?**
- output format, one of below
- `computedValue` (default), [computed value][139] of the color
- `specifiedValue`, [specified value][140] of the color
- `hex`, hex color notation, i.e. `#rrggbb`
- `hexAlpha`, hex color notation with alpha channel, i.e. `#rrggbbaa`
Returns **[string][133]?** one of `rgba?()`, `#rrggbb(aa)?`, `color-name`, `color(color-space r g b / alpha)`, `color(color-space x y z / alpha)`, `(ok)?lab(l a b / alpha)`, `(ok)?lch(l c h / alpha)`, `'(empty-string)'`, `null`
- in `computedValue`, values are numbers, however `rgb()` values are integers
- in `specifiedValue`, returns `empty string` for unknown and/or invalid color
- in `hex`, returns `null` for `transparent`, and also returns `null` if any of `r`, `g`, `b`, `alpha` is not a number
- in `hexAlpha`, returns `#00000000` for `transparent`, however returns `null` if any of `r`, `g`, `b`, `alpha` is not a number
### convert
Contains various color conversion functions.
### convert.numberToHex(value)
convert number to hex string
#### Parameters
- `value` **[number][134]** color value
Returns **[string][133]** hex string: 00..ff
### convert.colorToHex(value, opt)
convert color to hex
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.alpha` **[boolean][136]?** return in #rrggbbaa notation
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[string][133]** #rrggbb(aa)?
### convert.colorToHsl(value, opt)
convert color to hsl
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[h, s, l, alpha]
### convert.colorToHwb(value, opt)
convert color to hwb
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[h, w, b, alpha]
### convert.colorToLab(value, opt)
convert color to lab
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[l, a, b, alpha]
### convert.colorToLch(value, opt)
convert color to lch
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[l, c, h, alpha]
### convert.colorToOklab(value, opt)
convert color to oklab
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[l, a, b, alpha]
### convert.colorToOklch(value, opt)
convert color to oklch
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[l, c, h, alpha]
### convert.colorToRgb(value, opt)
convert color to rgb
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[r, g, b, alpha]
### convert.colorToXyz(value, opt)
convert color to xyz
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
- `opt.d50` **[boolean][136]?** xyz in d50 white point
Returns **[Array][137]<[number][134]>** \[x, y, z, alpha]
### convert.colorToXyzD50(value, opt)
convert color to xyz-d50
#### Parameters
- `value` **[string][133]** color value
- `opt` **[object][135]?** options (optional, default `{}`)
- `opt.customProperty` **[object][135]?**
- custom properties, see `resolve()` function above
- `opt.dimension` **[object][135]?**
- dimension, see `resolve()` function above
Returns **[Array][137]<[number][134]>** \[x, y, z, alpha]
### utils
Contains utility functions.
### utils.isColor(color)
is valid color type
#### Parameters
- `color` **[string][133]** color value
- system colors are not supported
Returns **[boolean][136]**
## Acknowledgments
The following resources have been of great help in the development of the CSS color.
- [csstools/postcss-plugins](https://github.com/csstools/postcss-plugins)
- [lru-cache](https://github.com/isaacs/node-lru-cache)
---
Copyright (c) 2024 [asamuzaK (Kazz)](https://github.com/asamuzaK/)
[133]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
[134]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[135]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[136]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[137]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
[138]: https://w3c.github.io/csswg-drafts/css-color-4/#color-conversion-code
[139]: https://developer.mozilla.org/en-US/docs/Web/CSS/computed_value
[140]: https://developer.mozilla.org/en-US/docs/Web/CSS/specified_value
[141]: https://www.npmjs.com/package/@csstools/css-calc

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5443
node_modules/@asamuzakjp/css-color/dist/cjs/index.cjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

108
node_modules/@asamuzakjp/css-color/dist/cjs/index.d.cts generated vendored Normal file
View File

@@ -0,0 +1,108 @@
/**
* typedef
*/
/**
* @typedef Options - options
* @property [alpha] - enable alpha
* @property [colorSpace] - color space
* @property [currentColor] - color for currentcolor
* @property [customPropeerty] - custom properties
* @property [d50] - white point in d50
* @property [dimension] - dimension
* @property [format] - output format
* @property [key] - key
*/
interface Options {
alpha?: boolean;
colorSpace?: string;
currentColor?: string;
customProperty?: Record<string, string | ((K: string) => string)>;
d50?: boolean;
delimiter?: string | string[];
dimension?: Record<string, number | ((K: string) => number)>;
format?: string;
nullable?: boolean;
}
/**
* @type ColorChannels - color channels
*/
type ColorChannels = [x: number, y: number, z: number, alpha: number];
/**
* convert
*/
declare const convert: {
colorToHex: (value: string, opt?: Options) => string | null;
colorToHsl: (value: string, opt?: Options) => ColorChannels;
colorToHwb: (value: string, opt?: Options) => ColorChannels;
colorToLab: (value: string, opt?: Options) => ColorChannels;
colorToLch: (value: string, opt?: Options) => ColorChannels;
colorToOklab: (value: string, opt?: Options) => ColorChannels;
colorToOklch: (value: string, opt?: Options) => ColorChannels;
colorToRgb: (value: string, opt?: Options) => ColorChannels;
colorToXyz: (value: string, opt?: Options) => ColorChannels;
colorToXyzD50: (value: string, opt?: Options) => ColorChannels;
numberToHex: (value: number) => string;
};
/**
* resolve
*/
/**
* resolve CSS color
* @param value
* - CSS color value
* - system colors are not supported
* @param [opt] - options
* @param [opt.currentColor]
* - color to use for `currentcolor` keyword
* - if omitted, it will be treated as a missing color
* i.e. `rgb(none none none / none)`
* @param [opt.customProperty]
* - custom properties
* - pair of `--` prefixed property name and value,
* e.g. `customProperty: { '--some-color': '#0000ff' }`
* - and/or `callback` function to get the value of the custom property,
* e.g. `customProperty: { callback: someDeclaration.getPropertyValue }`
* @param [opt.dimension]
* - dimension, convert relative length to pixels
* - pair of unit and it's value as a number in pixels,
* e.g. `dimension: { em: 12, rem: 16, vw: 10.26 }`
* - and/or `callback` function to get the value as a number in pixels,
* e.g. `dimension: { callback: convertUnitToPixel }`
* @param [opt.format]
* - output format, one of below
* - `computedValue` (default), [computed value][139] of the color
* - `specifiedValue`, [specified value][140] of the color
* - `hex`, hex color notation, i.e. `rrggbb`
* - `hexAlpha`, hex color notation with alpha channel, i.e. `#rrggbbaa`
* @returns
* - one of rgba?(), #rrggbb(aa)?, color-name, '(empty-string)',
* color(color-space r g b / alpha), color(color-space x y z / alpha),
* lab(l a b / alpha), lch(l c h / alpha), oklab(l a b / alpha),
* oklch(l c h / alpha), null
* - in `computedValue`, values are numbers, however `rgb()` values are
* integers
* - in `specifiedValue`, returns `empty string` for unknown and/or invalid
* color
* - in `hex`, returns `null` for `transparent`, and also returns `null` if
* any of `r`, `g`, `b`, `alpha` is not a number
* - in `hexAlpha`, returns `#00000000` for `transparent`,
* however returns `null` if any of `r`, `g`, `b`, `alpha` is not a number
*/
declare const resolve: (value: string, opt?: Options) => string | null;
declare const utils: {
cssCalc: (value: string, opt?: Options) => string;
cssVar: (value: string, opt?: Options) => string;
extractDashedIdent: (value: string) => string[];
isColor: (value: unknown, opt?: Options) => boolean;
isGradient: (value: string, opt?: Options) => boolean;
splitValue: (value: string, delimiter?: string) => string[];
};
declare const isColor: (value: unknown, opt?: Options) => boolean;
declare const cssCalc: (value: string, opt?: Options) => string;
export { convert, cssCalc, isColor, resolve, utils };

18
node_modules/@asamuzakjp/css-color/dist/esm/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
/*!
* CSS color - Resolve, parse, convert CSS color.
* @license MIT
* @copyright asamuzaK (Kazz)
* @see {@link https://github.com/asamuzaK/cssColor/blob/main/LICENSE}
*/
export { convert } from './js/convert.js';
export { resolve } from './js/resolve.js';
export declare const utils: {
cssCalc: (value: string, opt?: import('./js/typedef.js').Options) => string;
cssVar: (value: string, opt?: import('./js/typedef.js').Options) => string;
extractDashedIdent: (value: string) => string[];
isColor: (value: unknown, opt?: import('./js/typedef.js').Options) => boolean;
isGradient: (value: string, opt?: import('./js/typedef.js').Options) => boolean;
splitValue: (value: string, delimiter?: string) => string[];
};
export declare const isColor: (value: unknown, opt?: import('./js/typedef.js').Options) => boolean;
export declare const cssCalc: (value: string, opt?: import('./js/typedef.js').Options) => string;

30
node_modules/@asamuzakjp/css-color/dist/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
import { cssCalc as cssCalc$1 } from "./js/css-calc.js";
import { isGradient } from "./js/css-gradient.js";
import { cssVar } from "./js/css-var.js";
import { splitValue, isColor as isColor$1, extractDashedIdent } from "./js/util.js";
import { convert } from "./js/convert.js";
import { resolve } from "./js/resolve.js";
/*!
* CSS color - Resolve, parse, convert CSS color.
* @license MIT
* @copyright asamuzaK (Kazz)
* @see {@link https://github.com/asamuzaK/cssColor/blob/main/LICENSE}
*/
const utils = {
cssCalc: cssCalc$1,
cssVar,
extractDashedIdent,
isColor: isColor$1,
isGradient,
splitValue
};
const isColor = utils.isColor;
const cssCalc = utils.cssCalc;
export {
convert,
cssCalc,
isColor,
resolve,
utils
};
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["/*!\n * CSS color - Resolve, parse, convert CSS color.\n * @license MIT\n * @copyright asamuzaK (Kazz)\n * @see {@link https://github.com/asamuzaK/cssColor/blob/main/LICENSE}\n */\n\nimport { cssCalc as csscalc } from './js/css-calc';\nimport { isGradient } from './js/css-gradient';\nimport { cssVar } from './js/css-var';\nimport { extractDashedIdent, isColor as iscolor, splitValue } from './js/util';\n\nexport { convert } from './js/convert';\nexport { resolve } from './js/resolve';\n/* utils */\nexport const utils = {\n cssCalc: csscalc,\n cssVar,\n extractDashedIdent,\n isColor: iscolor,\n isGradient,\n splitValue\n};\n/* TODO: remove later */\n/* alias */\nexport const isColor = utils.isColor;\nexport const cssCalc = utils.cssCalc;\n"],"names":["csscalc","iscolor"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeO,MAAM,QAAQ;AAAA,EACnB,SAASA;AAAAA,EACT;AAAA,EACA;AAAA,EACA,SAASC;AAAAA,EACT;AAAA,EACA;AACF;AAGO,MAAM,UAAU,MAAM;AACtB,MAAM,UAAU,MAAM;"}

View File

@@ -0,0 +1,44 @@
import { LRUCache } from 'lru-cache';
import { Options } from './typedef.js';
/**
* CacheItem
*/
export declare class CacheItem {
#private;
/**
* constructor
*/
constructor(item: unknown, isNull?: boolean);
get item(): unknown;
get isNull(): boolean;
}
/**
* NullObject
*/
export declare class NullObject extends CacheItem {
/**
* constructor
*/
constructor();
}
export declare const lruCache: LRUCache<{}, {}, unknown>;
/**
* set cache
* @param key - cache key
* @param value - value to cache
* @returns void
*/
export declare const setCache: (key: string, value: unknown) => void;
/**
* get cache
* @param key - cache key
* @returns cached item or false otherwise
*/
export declare const getCache: (key: string) => CacheItem | boolean;
/**
* create cache key
* @param keyData - key data
* @param [opt] - options
* @returns cache key
*/
export declare const createCacheKey: (keyData: Record<string, string>, opt?: Options) => string;

View File

@@ -0,0 +1,82 @@
var __typeError = (msg) => {
throw TypeError(msg);
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var _isNull, _item;
import { LRUCache } from "lru-cache";
import { valueToJsonString } from "./util.js";
const MAX_CACHE = 4096;
class CacheItem {
/**
* constructor
*/
constructor(item, isNull = false) {
/* private */
__privateAdd(this, _isNull);
__privateAdd(this, _item);
__privateSet(this, _item, item);
__privateSet(this, _isNull, !!isNull);
}
get item() {
return __privateGet(this, _item);
}
get isNull() {
return __privateGet(this, _isNull);
}
}
_isNull = new WeakMap();
_item = new WeakMap();
class NullObject extends CacheItem {
/**
* constructor
*/
constructor() {
super(Symbol("null"), true);
}
}
const lruCache = new LRUCache({
max: MAX_CACHE
});
const setCache = (key, value) => {
if (key) {
if (value === null) {
lruCache.set(key, new NullObject());
} else if (value instanceof CacheItem) {
lruCache.set(key, value);
} else {
lruCache.set(key, new CacheItem(value));
}
}
};
const getCache = (key) => {
if (key && lruCache.has(key)) {
const item = lruCache.get(key);
if (item instanceof CacheItem) {
return item;
}
lruCache.delete(key);
return false;
}
return false;
};
const createCacheKey = (keyData, opt = {}) => {
const { customProperty = {}, dimension = {} } = opt;
let cacheKey = "";
if (keyData && Object.keys(keyData).length && typeof customProperty.callback !== "function" && typeof dimension.callback !== "function") {
keyData.opt = valueToJsonString(opt);
cacheKey = valueToJsonString(keyData);
}
return cacheKey;
};
export {
CacheItem,
NullObject,
createCacheKey,
getCache,
lruCache,
setCache
};
//# sourceMappingURL=cache.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"cache.js","sources":["../../../src/js/cache.ts"],"sourcesContent":["/**\n * cache\n */\n\nimport { LRUCache } from 'lru-cache';\nimport { Options } from './typedef';\nimport { valueToJsonString } from './util';\n\n/* numeric constants */\nconst MAX_CACHE = 4096;\n\n/**\n * CacheItem\n */\nexport class CacheItem {\n /* private */\n #isNull: boolean;\n #item: unknown;\n\n /**\n * constructor\n */\n constructor(item: unknown, isNull: boolean = false) {\n this.#item = item;\n this.#isNull = !!isNull;\n }\n\n get item() {\n return this.#item;\n }\n\n get isNull() {\n return this.#isNull;\n }\n}\n\n/**\n * NullObject\n */\nexport class NullObject extends CacheItem {\n /**\n * constructor\n */\n constructor() {\n super(Symbol('null'), true);\n }\n}\n\n/*\n * lru cache\n */\nexport const lruCache = new LRUCache({\n max: MAX_CACHE\n});\n\n/**\n * set cache\n * @param key - cache key\n * @param value - value to cache\n * @returns void\n */\nexport const setCache = (key: string, value: unknown): void => {\n if (key) {\n if (value === null) {\n lruCache.set(key, new NullObject());\n } else if (value instanceof CacheItem) {\n lruCache.set(key, value);\n } else {\n lruCache.set(key, new CacheItem(value));\n }\n }\n};\n\n/**\n * get cache\n * @param key - cache key\n * @returns cached item or false otherwise\n */\nexport const getCache = (key: string): CacheItem | boolean => {\n if (key && lruCache.has(key)) {\n const item = lruCache.get(key);\n if (item instanceof CacheItem) {\n return item;\n }\n // delete unexpected cached item\n lruCache.delete(key);\n return false;\n }\n return false;\n};\n\n/**\n * create cache key\n * @param keyData - key data\n * @param [opt] - options\n * @returns cache key\n */\nexport const createCacheKey = (\n keyData: Record<string, string>,\n opt: Options = {}\n): string => {\n const { customProperty = {}, dimension = {} } = opt;\n let cacheKey = '';\n if (\n keyData &&\n Object.keys(keyData).length &&\n typeof customProperty.callback !== 'function' &&\n typeof dimension.callback !== 'function'\n ) {\n keyData.opt = valueToJsonString(opt);\n cacheKey = valueToJsonString(keyData);\n }\n return cacheKey;\n};\n"],"names":[],"mappings":";;;;;;;;;;AASA,MAAM,YAAY;AAKX,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA,EAQrB,YAAY,MAAe,SAAkB,OAAO;AANpD;AAAA;AACA;AAME,uBAAK,OAAQ;AACR,uBAAA,SAAU,CAAC,CAAC;AAAA,EAAA;AAAA,EAGnB,IAAI,OAAO;AACT,WAAO,mBAAK;AAAA,EAAA;AAAA,EAGd,IAAI,SAAS;AACX,WAAO,mBAAK;AAAA,EAAA;AAEhB;AAlBE;AACA;AAsBK,MAAM,mBAAmB,UAAU;AAAA;AAAA;AAAA;AAAA,EAIxC,cAAc;AACN,UAAA,OAAO,MAAM,GAAG,IAAI;AAAA,EAAA;AAE9B;AAKa,MAAA,WAAW,IAAI,SAAS;AAAA,EACnC,KAAK;AACP,CAAC;AAQY,MAAA,WAAW,CAAC,KAAa,UAAyB;AAC7D,MAAI,KAAK;AACP,QAAI,UAAU,MAAM;AAClB,eAAS,IAAI,KAAK,IAAI,WAAA,CAAY;AAAA,IAAA,WACzB,iBAAiB,WAAW;AAC5B,eAAA,IAAI,KAAK,KAAK;AAAA,IAAA,OAClB;AACL,eAAS,IAAI,KAAK,IAAI,UAAU,KAAK,CAAC;AAAA,IAAA;AAAA,EACxC;AAEJ;AAOa,MAAA,WAAW,CAAC,QAAqC;AAC5D,MAAI,OAAO,SAAS,IAAI,GAAG,GAAG;AACtB,UAAA,OAAO,SAAS,IAAI,GAAG;AAC7B,QAAI,gBAAgB,WAAW;AACtB,aAAA;AAAA,IAAA;AAGT,aAAS,OAAO,GAAG;AACZ,WAAA;AAAA,EAAA;AAEF,SAAA;AACT;AAQO,MAAM,iBAAiB,CAC5B,SACA,MAAe,OACJ;AACX,QAAM,EAAE,iBAAiB,CAAA,GAAI,YAAY,CAAA,EAAO,IAAA;AAChD,MAAI,WAAW;AACf,MACE,WACA,OAAO,KAAK,OAAO,EAAE,UACrB,OAAO,eAAe,aAAa,cACnC,OAAO,UAAU,aAAa,YAC9B;AACQ,YAAA,MAAM,kBAAkB,GAAG;AACnC,eAAW,kBAAkB,OAAO;AAAA,EAAA;AAE/B,SAAA;AACT;"}

View File

@@ -0,0 +1,537 @@
import { NullObject } from './cache.js';
import { ColorChannels, Options, SpecifiedColorChannels } from './typedef.js';
/**
* @type TriColorChannels - color channels without alpha
*/
type TriColorChannels = [x: number, y: number, z: number];
/**
* @type ColorMatrix - color matrix
*/
type ColorMatrix = [
r1: TriColorChannels,
r2: TriColorChannels,
r3: TriColorChannels
];
/**
* named colors
*/
export declare const NAMED_COLORS: {
readonly aliceblue: [240, 248, 255];
readonly antiquewhite: [250, 235, 215];
readonly aqua: [0, 255, 255];
readonly aquamarine: [127, 255, 212];
readonly azure: [240, 255, 255];
readonly beige: [245, 245, 220];
readonly bisque: [255, 228, 196];
readonly black: [0, 0, 0];
readonly blanchedalmond: [255, 235, 205];
readonly blue: [0, 0, 255];
readonly blueviolet: [138, 43, 226];
readonly brown: [165, 42, 42];
readonly burlywood: [222, 184, 135];
readonly cadetblue: [95, 158, 160];
readonly chartreuse: [127, 255, 0];
readonly chocolate: [210, 105, 30];
readonly coral: [255, 127, 80];
readonly cornflowerblue: [100, 149, 237];
readonly cornsilk: [255, 248, 220];
readonly crimson: [220, 20, 60];
readonly cyan: [0, 255, 255];
readonly darkblue: [0, 0, 139];
readonly darkcyan: [0, 139, 139];
readonly darkgoldenrod: [184, 134, 11];
readonly darkgray: [169, 169, 169];
readonly darkgreen: [0, 100, 0];
readonly darkgrey: [169, 169, 169];
readonly darkkhaki: [189, 183, 107];
readonly darkmagenta: [139, 0, 139];
readonly darkolivegreen: [85, 107, 47];
readonly darkorange: [255, 140, 0];
readonly darkorchid: [153, 50, 204];
readonly darkred: [139, 0, 0];
readonly darksalmon: [233, 150, 122];
readonly darkseagreen: [143, 188, 143];
readonly darkslateblue: [72, 61, 139];
readonly darkslategray: [47, 79, 79];
readonly darkslategrey: [47, 79, 79];
readonly darkturquoise: [0, 206, 209];
readonly darkviolet: [148, 0, 211];
readonly deeppink: [255, 20, 147];
readonly deepskyblue: [0, 191, 255];
readonly dimgray: [105, 105, 105];
readonly dimgrey: [105, 105, 105];
readonly dodgerblue: [30, 144, 255];
readonly firebrick: [178, 34, 34];
readonly floralwhite: [255, 250, 240];
readonly forestgreen: [34, 139, 34];
readonly fuchsia: [255, 0, 255];
readonly gainsboro: [220, 220, 220];
readonly ghostwhite: [248, 248, 255];
readonly gold: [255, 215, 0];
readonly goldenrod: [218, 165, 32];
readonly gray: [128, 128, 128];
readonly green: [0, 128, 0];
readonly greenyellow: [173, 255, 47];
readonly grey: [128, 128, 128];
readonly honeydew: [240, 255, 240];
readonly hotpink: [255, 105, 180];
readonly indianred: [205, 92, 92];
readonly indigo: [75, 0, 130];
readonly ivory: [255, 255, 240];
readonly khaki: [240, 230, 140];
readonly lavender: [230, 230, 250];
readonly lavenderblush: [255, 240, 245];
readonly lawngreen: [124, 252, 0];
readonly lemonchiffon: [255, 250, 205];
readonly lightblue: [173, 216, 230];
readonly lightcoral: [240, 128, 128];
readonly lightcyan: [224, 255, 255];
readonly lightgoldenrodyellow: [250, 250, 210];
readonly lightgray: [211, 211, 211];
readonly lightgreen: [144, 238, 144];
readonly lightgrey: [211, 211, 211];
readonly lightpink: [255, 182, 193];
readonly lightsalmon: [255, 160, 122];
readonly lightseagreen: [32, 178, 170];
readonly lightskyblue: [135, 206, 250];
readonly lightslategray: [119, 136, 153];
readonly lightslategrey: [119, 136, 153];
readonly lightsteelblue: [176, 196, 222];
readonly lightyellow: [255, 255, 224];
readonly lime: [0, 255, 0];
readonly limegreen: [50, 205, 50];
readonly linen: [250, 240, 230];
readonly magenta: [255, 0, 255];
readonly maroon: [128, 0, 0];
readonly mediumaquamarine: [102, 205, 170];
readonly mediumblue: [0, 0, 205];
readonly mediumorchid: [186, 85, 211];
readonly mediumpurple: [147, 112, 219];
readonly mediumseagreen: [60, 179, 113];
readonly mediumslateblue: [123, 104, 238];
readonly mediumspringgreen: [0, 250, 154];
readonly mediumturquoise: [72, 209, 204];
readonly mediumvioletred: [199, 21, 133];
readonly midnightblue: [25, 25, 112];
readonly mintcream: [245, 255, 250];
readonly mistyrose: [255, 228, 225];
readonly moccasin: [255, 228, 181];
readonly navajowhite: [255, 222, 173];
readonly navy: [0, 0, 128];
readonly oldlace: [253, 245, 230];
readonly olive: [128, 128, 0];
readonly olivedrab: [107, 142, 35];
readonly orange: [255, 165, 0];
readonly orangered: [255, 69, 0];
readonly orchid: [218, 112, 214];
readonly palegoldenrod: [238, 232, 170];
readonly palegreen: [152, 251, 152];
readonly paleturquoise: [175, 238, 238];
readonly palevioletred: [219, 112, 147];
readonly papayawhip: [255, 239, 213];
readonly peachpuff: [255, 218, 185];
readonly peru: [205, 133, 63];
readonly pink: [255, 192, 203];
readonly plum: [221, 160, 221];
readonly powderblue: [176, 224, 230];
readonly purple: [128, 0, 128];
readonly rebeccapurple: [102, 51, 153];
readonly red: [255, 0, 0];
readonly rosybrown: [188, 143, 143];
readonly royalblue: [65, 105, 225];
readonly saddlebrown: [139, 69, 19];
readonly salmon: [250, 128, 114];
readonly sandybrown: [244, 164, 96];
readonly seagreen: [46, 139, 87];
readonly seashell: [255, 245, 238];
readonly sienna: [160, 82, 45];
readonly silver: [192, 192, 192];
readonly skyblue: [135, 206, 235];
readonly slateblue: [106, 90, 205];
readonly slategray: [112, 128, 144];
readonly slategrey: [112, 128, 144];
readonly snow: [255, 250, 250];
readonly springgreen: [0, 255, 127];
readonly steelblue: [70, 130, 180];
readonly tan: [210, 180, 140];
readonly teal: [0, 128, 128];
readonly thistle: [216, 191, 216];
readonly tomato: [255, 99, 71];
readonly turquoise: [64, 224, 208];
readonly violet: [238, 130, 238];
readonly wheat: [245, 222, 179];
readonly white: [255, 255, 255];
readonly whitesmoke: [245, 245, 245];
readonly yellow: [255, 255, 0];
readonly yellowgreen: [154, 205, 50];
};
/**
* cache invalid color value
* @param key - cache key
* @param nullable - is nullable
* @returns cached value
*/
export declare const cacheInvalidColorValue: (cacheKey: string, format: string, nullable?: boolean) => SpecifiedColorChannels | string | NullObject;
/**
* resolve invalid color value
* @param format - output format
* @param nullable - is nullable
* @returns resolved value
*/
export declare const resolveInvalidColorValue: (format: string, nullable?: boolean) => SpecifiedColorChannels | string | NullObject;
/**
* validate color components
* @param arr - color components
* @param [opt] - options
* @param [opt.alpha] - alpha channel
* @param [opt.minLength] - min length
* @param [opt.maxLength] - max length
* @param [opt.minRange] - min range
* @param [opt.maxRange] - max range
* @param [opt.validateRange] - validate range
* @returns result - validated color components
*/
export declare const validateColorComponents: (arr: ColorChannels | TriColorChannels, opt?: {
alpha?: boolean;
minLength?: number;
maxLength?: number;
minRange?: number;
maxRange?: number;
validateRange?: boolean;
}) => ColorChannels | TriColorChannels;
/**
* transform matrix
* @param mtx - 3 * 3 matrix
* @param vct - vector
* @param [skip] - skip validate
* @returns TriColorChannels - [p1, p2, p3]
*/
export declare const transformMatrix: (mtx: ColorMatrix, vct: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* normalize color components
* @param colorA - color components [v1, v2, v3, v4]
* @param colorB - color components [v1, v2, v3, v4]
* @param [skip] - skip validate
* @returns result - [colorA, colorB]
*/
export declare const normalizeColorComponents: (colorA: [number | string, number | string, number | string, number | string], colorB: [number | string, number | string, number | string, number | string], skip?: boolean) => [ColorChannels, ColorChannels];
/**
* number to hex string
* @param value - numeric value
* @returns hex string
*/
export declare const numberToHexString: (value: number) => string;
/**
* angle to deg
* @param angle
* @returns deg: 0..360
*/
export declare const angleToDeg: (angle: string) => number;
/**
* parse alpha
* @param [alpha] - alpha value
* @returns alpha: 0..1
*/
export declare const parseAlpha: (alpha?: string) => number;
/**
* parse hex alpha
* @param value - alpha value in hex string
* @returns alpha: 0..1
*/
export declare const parseHexAlpha: (value: string) => number;
/**
* transform rgb to linear rgb
* @param rgb - [r, g, b] r|g|b: 0..255
* @param [skip] - skip validate
* @returns TriColorChannels - [r, g, b] r|g|b: 0..1
*/
export declare const transformRgbToLinearRgb: (rgb: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform rgb to xyz
* @param rgb - [r, g, b] r|g|b: 0..255
* @param [skip] - skip validate
* @returns TriColorChannels - [x, y, z]
*/
export declare const transformRgbToXyz: (rgb: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform rgb to xyz-d50
* @param rgb - [r, g, b] r|g|b: 0..255 alpha: 0..1
* @returns TriColorChannels - [x, y, z]
*/
export declare const transformRgbToXyzD50: (rgb: TriColorChannels) => TriColorChannels;
/**
* transform linear rgb to rgb
* @param rgb - [r, g, b] r|g|b: 0..1
* @param [round] - round result
* @returns TriColorChannels - [r, g, b] r|g|b: 0..255
*/
export declare const transformLinearRgbToRgb: (rgb: TriColorChannels, round?: boolean) => TriColorChannels;
/**
* transform xyz to rgb
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [r, g, b] r|g|b: 0..255
*/
export declare const transformXyzToRgb: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz to xyz-d50
* @param xyz - [x, y, z]
* @returns TriColorChannels - [x, y, z]
*/
export declare const transformXyzToXyzD50: (xyz: TriColorChannels) => TriColorChannels;
/**
* transform xyz to hsl
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [h, s, l]
*/
export declare const transformXyzToHsl: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz to hwb
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [h, w, b]
*/
export declare const transformXyzToHwb: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz to oklab
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [l, a, b]
*/
export declare const transformXyzToOklab: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz to oklch
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [l, c, h]
*/
export declare const transformXyzToOklch: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz D50 to rgb
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [r, g, b] r|g|b: 0..255
*/
export declare const transformXyzD50ToRgb: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz-d50 to lab
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [l, a, b]
*/
export declare const transformXyzD50ToLab: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* transform xyz-d50 to lch
* @param xyz - [x, y, z]
* @param [skip] - skip validate
* @returns TriColorChannels - [l, c, h]
*/
export declare const transformXyzD50ToLch: (xyz: TriColorChannels, skip?: boolean) => TriColorChannels;
/**
* convert rgb to hex color
* @param rgb - [r, g, b, alpha] r|g|b: 0..255 alpha: 0..1
* @returns hex color
*/
export declare const convertRgbToHex: (rgb: ColorChannels) => string;
/**
* convert linear rgb to hex color
* @param rgb - [r, g, b, alpha] r|g|b|alpha: 0..1
* @param [skip] - skip validate
* @returns hex color
*/
export declare const convertLinearRgbToHex: (rgb: ColorChannels, skip?: boolean) => string;
/**
* convert xyz to hex color
* @param xyz - [x, y, z, alpha]
* @returns hex color
*/
export declare const convertXyzToHex: (xyz: ColorChannels) => string;
/**
* convert xyz D50 to hex color
* @param xyz - [x, y, z, alpha]
* @returns hex color
*/
export declare const convertXyzD50ToHex: (xyz: ColorChannels) => string;
/**
* convert hex color to rgb
* @param value - hex color value
* @returns ColorChannels - [r, g, b, alpha] r|g|b: 0..255 alpha: 0..1
*/
export declare const convertHexToRgb: (value: string) => ColorChannels;
/**
* convert hex color to linear rgb
* @param value - hex color value
* @returns ColorChannels - [r, g, b, alpha] r|g|b|alpha: 0..1
*/
export declare const convertHexToLinearRgb: (value: string) => ColorChannels;
/**
* convert hex color to xyz
* @param value - hex color value
* @returns ColorChannels - [x, y, z, alpha]
*/
export declare const convertHexToXyz: (value: string) => ColorChannels;
/**
* parse rgb()
* @param value - rgb color value
* @param [opt] - options
* @returns parsed color - ['rgb', r, g, b, alpha], '(empty)', NullObject
*/
export declare const parseRgb: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse hsl()
* @param value - hsl color value
* @param [opt] - options
* @returns parsed color - ['rgb', r, g, b, alpha], '(empty)', NullObject
*/
export declare const parseHsl: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse hwb()
* @param value - hwb color value
* @param [opt] - options
* @returns parsed color - ['rgb', r, g, b, alpha], '(empty)', NullObject
*/
export declare const parseHwb: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse lab()
* @param value - lab color value
* @param [opt] - options
* @returns parsed color
* - [xyz-d50, x, y, z, alpha], ['lab', l, a, b, alpha], '(empty)', NullObject
*/
export declare const parseLab: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse lch()
* @param value - lch color value
* @param [opt] - options
* @returns parsed color
* - ['xyz-d50', x, y, z, alpha], ['lch', l, c, h, alpha]
* - '(empty)', NullObject
*/
export declare const parseLch: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse oklab()
* @param value - oklab color value
* @param [opt] - options
* @returns parsed color
* - ['xyz-d65', x, y, z, alpha], ['oklab', l, a, b, alpha]
* - '(empty)', NullObject
*/
export declare const parseOklab: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse oklch()
* @param value - oklch color value
* @param [opt] - options
* @returns parsed color
* - ['xyz-d65', x, y, z, alpha], ['oklch', l, c, h, alpha]
* - '(empty)', NullObject
*/
export declare const parseOklch: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse color()
* @param value - color function value
* @param [opt] - options
* @returns parsed color
* - ['xyz-(d50|d65)', x, y, z, alpha], [cs, r, g, b, alpha]
* - '(empty)', NullObject
*/
export declare const parseColorFunc: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* parse color value
* @param value - CSS color value
* @param [opt] - options
* @returns parsed color
* - ['xyz-(d50|d65)', x, y, z, alpha], ['rgb', r, g, b, alpha]
* - value, '(empty)', NullObject
*/
export declare const parseColorValue: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* resolve color value
* @param value - CSS color value
* @param [opt] - options
* @returns resolved color
* - [cs, v1, v2, v3, alpha], value, '(empty)', NullObject
*/
export declare const resolveColorValue: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* resolve color()
* @param value - color function value
* @param [opt] - options
* @returns resolved color - [cs, v1, v2, v3, alpha], '(empty)', NullObject
*/
export declare const resolveColorFunc: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
/**
* convert color value to linear rgb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [r, g, b, alpha] r|g|b|alpha: 0..1
*/
export declare const convertColorToLinearRgb: (value: string, opt?: {
colorSpace?: string;
format?: string;
}) => ColorChannels | NullObject;
/**
* convert color value to rgb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject
* - [r, g, b, alpha] r|g|b: 0..255 alpha: 0..1
*/
export declare const convertColorToRgb: (value: string, opt?: Options) => ColorChannels | NullObject;
/**
* convert color value to xyz
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [x, y, z, alpha]
*/
export declare const convertColorToXyz: (value: string, opt?: Options) => ColorChannels | NullObject;
/**
* convert color value to hsl
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [h, s, l, alpha], hue may be powerless
*/
export declare const convertColorToHsl: (value: string, opt?: Options) => ColorChannels | [number | string, number, number, number] | NullObject;
/**
* convert color value to hwb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [h, w, b, alpha], hue may be powerless
*/
export declare const convertColorToHwb: (value: string, opt?: Options) => ColorChannels | [number | string, number, number, number] | NullObject;
/**
* convert color value to lab
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [l, a, b, alpha]
*/
export declare const convertColorToLab: (value: string, opt?: Options) => ColorChannels | NullObject;
/**
* convert color value to lch
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [l, c, h, alpha], hue may be powerless
*/
export declare const convertColorToLch: (value: string, opt?: Options) => ColorChannels | [number, number, number | string, number] | NullObject;
/**
* convert color value to oklab
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [l, a, b, alpha]
*/
export declare const convertColorToOklab: (value: string, opt?: Options) => ColorChannels | NullObject;
/**
* convert color value to oklch
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels | NullObject - [l, c, h, alpha], hue may be powerless
*/
export declare const convertColorToOklch: (value: string, opt?: Options) => ColorChannels | [number, number, number | string, number] | NullObject;
/**
* resolve color-mix()
* @param value - color-mix color value
* @param [opt] - options
* @returns resolved color - [cs, v1, v2, v3, alpha], '(empty)'
*/
export declare const resolveColorMix: (value: string, opt?: Options) => SpecifiedColorChannels | string | NullObject;
export {};

2792
node_modules/@asamuzakjp/css-color/dist/esm/js/color.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
/**
* common
*/
/**
* get type
* @param o - object to check
* @returns type of object
*/
export declare const getType: (o: unknown) => string;
/**
* is string
* @param o - object to check
* @returns result
*/
export declare const isString: (o: unknown) => o is string;
/**
* is string or number
* @param o - object to check
* @returns result
*/
export declare const isStringOrNumber: (o: unknown) => boolean;

View File

@@ -0,0 +1,7 @@
const isString = (o) => typeof o === "string" || o instanceof String;
const isStringOrNumber = (o) => isString(o) || typeof o === "number";
export {
isString,
isStringOrNumber
};
//# sourceMappingURL=common.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"common.js","sources":["../../../src/js/common.ts"],"sourcesContent":["/**\n * common\n */\n\n/* numeric constants */\nconst TYPE_FROM = 8;\nconst TYPE_TO = -1;\n\n/**\n * get type\n * @param o - object to check\n * @returns type of object\n */\nexport const getType = (o: unknown): string =>\n Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);\n\n/**\n * is string\n * @param o - object to check\n * @returns result\n */\nexport const isString = (o: unknown): o is string =>\n typeof o === 'string' || o instanceof String;\n\n/**\n * is string or number\n * @param o - object to check\n * @returns result\n */\nexport const isStringOrNumber = (o: unknown): boolean =>\n isString(o) || typeof o === 'number';\n"],"names":[],"mappings":"AAqBO,MAAM,WAAW,CAAC,MACvB,OAAO,MAAM,YAAY,aAAa;AAOjC,MAAM,mBAAmB,CAAC,MAC/B,SAAS,CAAC,KAAK,OAAO,MAAM;"}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,97 @@
const _DIGIT = "(?:0|[1-9]\\d*)";
const _COMPARE = "clamp|max|min";
const _EXPO = "exp|hypot|log|pow|sqrt";
const _SIGN = "abs|sign";
const _STEP = "mod|rem|round";
const _TRIG = "a?(?:cos|sin|tan)|atan2";
const _MATH = `${_COMPARE}|${_EXPO}|${_SIGN}|${_STEP}|${_TRIG}`;
const _CALC = `calc|${_MATH}`;
const _VAR = `var|${_CALC}`;
const ANGLE = "deg|g?rad|turn";
const LENGTH = "[cm]m|[dls]?v(?:[bhiw]|max|min)|in|p[ctx]|q|r?(?:[cl]h|cap|e[mx]|ic)";
const NUM = `[+-]?(?:${_DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${_DIGIT})?`;
const NUM_POSITIVE = `\\+?(?:${_DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${_DIGIT})?`;
const NONE = "none";
const PCT = `${NUM}%`;
const SYN_FN_CALC = `^(?:${_CALC})\\(|(?<=[*\\/\\s\\(])(?:${_CALC})\\(`;
const SYN_FN_MATH_START = `^(?:${_MATH})\\($`;
const SYN_FN_VAR = "^var\\(|(?<=[*\\/\\s\\(])var\\(";
const SYN_FN_VAR_START = `^(?:${_VAR})\\(`;
const _ALPHA = `(?:\\s*\\/\\s*(?:${NUM}|${PCT}|${NONE}))?`;
const _ALPHA_LV3 = `(?:\\s*,\\s*(?:${NUM}|${PCT}))?`;
const _COLOR_FUNC = "(?:ok)?l(?:ab|ch)|color|hsla?|hwb|rgba?";
const _COLOR_KEY = "[a-z]+|#[\\da-f]{3}|#[\\da-f]{4}|#[\\da-f]{6}|#[\\da-f]{8}";
const _CS_HUE = "(?:ok)?lch|hsl|hwb";
const _CS_HUE_ARC = "(?:de|in)creasing|longer|shorter";
const _NUM_ANGLE = `${NUM}(?:${ANGLE})?`;
const _NUM_ANGLE_NONE = `(?:${NUM}(?:${ANGLE})?|${NONE})`;
const _NUM_PCT_NONE = `(?:${NUM}|${PCT}|${NONE})`;
const CS_HUE = `(?:${_CS_HUE})(?:\\s(?:${_CS_HUE_ARC})\\shue)?`;
const CS_HUE_CAPT = `(${_CS_HUE})(?:\\s(${_CS_HUE_ARC})\\shue)?`;
const CS_LAB = "(?:ok)?lab";
const CS_LCH = "(?:ok)?lch";
const CS_SRGB = "srgb(?:-linear)?";
const CS_RGB = `(?:a98|prophoto)-rgb|display-p3|rec2020|${CS_SRGB}`;
const CS_XYZ = "xyz(?:-d(?:50|65))?";
const CS_RECT = `${CS_LAB}|${CS_RGB}|${CS_XYZ}`;
const CS_MIX = `${CS_HUE}|${CS_RECT}`;
const FN_COLOR = "color(";
const FN_MIX = "color-mix(";
const FN_REL = `(?:${_COLOR_FUNC})\\(\\s*from\\s+`;
const FN_REL_CAPT = `(${_COLOR_FUNC})\\(\\s*from\\s+`;
const FN_VAR = "var(";
const SYN_FN_COLOR = `(?:${CS_RGB}|${CS_XYZ})(?:\\s+${_NUM_PCT_NONE}){3}${_ALPHA}`;
const SYN_FN_REL = `^${FN_REL}|(?<=[\\s])${FN_REL}`;
const SYN_HSL = `${_NUM_ANGLE_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
const SYN_HSL_LV3 = `${_NUM_ANGLE}(?:\\s*,\\s*${PCT}){2}${_ALPHA_LV3}`;
const SYN_LCH = `(?:${_NUM_PCT_NONE}\\s+){2}${_NUM_ANGLE_NONE}${_ALPHA}`;
const SYN_MOD = `${_NUM_PCT_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
const SYN_RGB_LV3 = `(?:${NUM}(?:\\s*,\\s*${NUM}){2}|${PCT}(?:\\s*,\\s*${PCT}){2})${_ALPHA_LV3}`;
const SYN_COLOR_TYPE = `${_COLOR_KEY}|hsla?\\(\\s*${SYN_HSL_LV3}\\s*\\)|rgba?\\(\\s*${SYN_RGB_LV3}\\s*\\)|(?:hsla?|hwb)\\(\\s*${SYN_HSL}\\s*\\)|(?:(?:ok)?lab|rgba?)\\(\\s*${SYN_MOD}\\s*\\)|(?:ok)?lch\\(\\s*${SYN_LCH}\\s*\\)|color\\(\\s*${SYN_FN_COLOR}\\s*\\)`;
const SYN_MIX_PART = `(?:${SYN_COLOR_TYPE})(?:\\s+${PCT})?`;
const SYN_MIX = `color-mix\\(\\s*in\\s+(?:${CS_MIX})\\s*,\\s*${SYN_MIX_PART}\\s*,\\s*${SYN_MIX_PART}\\s*\\)`;
const SYN_MIX_CAPT = `color-mix\\(\\s*in\\s+(${CS_MIX})\\s*,\\s*(${SYN_MIX_PART})\\s*,\\s*(${SYN_MIX_PART})\\s*\\)`;
const VAL_COMP = "computedValue";
const VAL_MIX = "mixValue";
const VAL_SPEC = "specifiedValue";
export {
ANGLE,
CS_HUE,
CS_HUE_CAPT,
CS_LAB,
CS_LCH,
CS_MIX,
CS_RECT,
CS_RGB,
CS_SRGB,
CS_XYZ,
FN_COLOR,
FN_MIX,
FN_REL,
FN_REL_CAPT,
FN_VAR,
LENGTH,
NONE,
NUM,
NUM_POSITIVE,
PCT,
SYN_COLOR_TYPE,
SYN_FN_CALC,
SYN_FN_COLOR,
SYN_FN_MATH_START,
SYN_FN_REL,
SYN_FN_VAR,
SYN_FN_VAR_START,
SYN_HSL,
SYN_HSL_LV3,
SYN_LCH,
SYN_MIX,
SYN_MIX_CAPT,
SYN_MIX_PART,
SYN_MOD,
SYN_RGB_LV3,
VAL_COMP,
VAL_MIX,
VAL_SPEC
};
//# sourceMappingURL=constant.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,99 @@
import { NullObject } from './cache.js';
import { ColorChannels, Options } from './typedef.js';
/**
* pre process
* @param value - CSS color value
* @param [opt] - options
* @returns value
*/
export declare const preProcess: (value: string, opt?: Options) => string | NullObject;
/**
* convert number to hex string
* @param value - numeric value
* @returns hex string: 00..ff
*/
export declare const numberToHex: (value: number) => string;
/**
* convert color to hex
* @param value - CSS color value
* @param [opt] - options
* @param [opt.alpha] - enable alpha channel
* @returns #rrggbb | #rrggbbaa | null
*/
export declare const colorToHex: (value: string, opt?: Options) => string | null;
/**
* convert color to hsl
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [h, s, l, alpha]
*/
export declare const colorToHsl: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to hwb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [h, w, b, alpha]
*/
export declare const colorToHwb: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to lab
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, a, b, alpha]
*/
export declare const colorToLab: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to lch
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, c, h, alpha]
*/
export declare const colorToLch: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to oklab
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, a, b, alpha]
*/
export declare const colorToOklab: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to oklch
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, c, h, alpha]
*/
export declare const colorToOklch: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to rgb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [r, g, b, alpha]
*/
export declare const colorToRgb: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to xyz
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [x, y, z, alpha]
*/
export declare const colorToXyz: (value: string, opt?: Options) => ColorChannels;
/**
* convert color to xyz-d50
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [x, y, z, alpha]
*/
export declare const colorToXyzD50: (value: string, opt?: Options) => ColorChannels;
export declare const convert: {
colorToHex: (value: string, opt?: Options) => string | null;
colorToHsl: (value: string, opt?: Options) => ColorChannels;
colorToHwb: (value: string, opt?: Options) => ColorChannels;
colorToLab: (value: string, opt?: Options) => ColorChannels;
colorToLch: (value: string, opt?: Options) => ColorChannels;
colorToOklab: (value: string, opt?: Options) => ColorChannels;
colorToOklch: (value: string, opt?: Options) => ColorChannels;
colorToRgb: (value: string, opt?: Options) => ColorChannels;
colorToXyz: (value: string, opt?: Options) => ColorChannels;
colorToXyzD50: (value: string, opt?: Options) => ColorChannels;
numberToHex: (value: number) => string;
};

View File

@@ -0,0 +1,361 @@
import { NullObject, createCacheKey, getCache, CacheItem, setCache } from "./cache.js";
import { numberToHexString, parseColorFunc, parseColorValue, convertColorToRgb, convertColorToOklch, convertColorToOklab, convertColorToLch, convertColorToLab, convertColorToHwb, convertColorToHsl } from "./color.js";
import { isString } from "./common.js";
import { cssCalc } from "./css-calc.js";
import { resolveVar } from "./css-var.js";
import { resolveRelativeColor } from "./relative-color.js";
import { resolveColor } from "./resolve.js";
import { VAL_COMP, SYN_FN_VAR, SYN_FN_REL, SYN_FN_CALC } from "./constant.js";
const NAMESPACE = "convert";
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
const REG_FN_REL = new RegExp(SYN_FN_REL);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
const preProcess = (value, opt = {}) => {
if (isString(value)) {
value = value.trim();
if (!value) {
return new NullObject();
}
} else {
return new NullObject();
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "preProcess",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return cachedResult;
}
return cachedResult.item;
}
if (REG_FN_VAR.test(value)) {
const resolvedValue = resolveVar(value, opt);
if (isString(resolvedValue)) {
value = resolvedValue;
} else {
setCache(cacheKey, null);
return new NullObject();
}
}
if (REG_FN_REL.test(value)) {
const resolvedValue = resolveRelativeColor(value, opt);
if (isString(resolvedValue)) {
value = resolvedValue;
} else {
setCache(cacheKey, null);
return new NullObject();
}
} else if (REG_FN_CALC.test(value)) {
value = cssCalc(value, opt);
}
if (value.startsWith("color-mix")) {
const clonedOpt = structuredClone(opt);
clonedOpt.format = VAL_COMP;
clonedOpt.nullable = true;
const resolvedValue = resolveColor(value, clonedOpt);
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
setCache(cacheKey, value);
return value;
};
const numberToHex = (value) => {
const hex = numberToHexString(value);
return hex;
};
const colorToHex = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return null;
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const { alpha = false } = opt;
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToHex",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return null;
}
return cachedResult.item;
}
let hex;
opt.nullable = true;
if (alpha) {
opt.format = "hexAlpha";
hex = resolveColor(value, opt);
} else {
opt.format = "hex";
hex = resolveColor(value, opt);
}
if (isString(hex)) {
setCache(cacheKey, hex);
return hex;
}
setCache(cacheKey, null);
return null;
};
const colorToHsl = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToHsl",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
opt.format = "hsl";
const hsl = convertColorToHsl(value, opt);
setCache(cacheKey, hsl);
return hsl;
};
const colorToHwb = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToHwb",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
opt.format = "hwb";
const hwb = convertColorToHwb(value, opt);
setCache(cacheKey, hwb);
return hwb;
};
const colorToLab = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToLab",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const lab = convertColorToLab(value, opt);
setCache(cacheKey, lab);
return lab;
};
const colorToLch = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToLch",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const lch = convertColorToLch(value, opt);
setCache(cacheKey, lch);
return lch;
};
const colorToOklab = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToOklab",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const lab = convertColorToOklab(value, opt);
setCache(cacheKey, lab);
return lab;
};
const colorToOklch = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToOklch",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const lch = convertColorToOklch(value, opt);
setCache(cacheKey, lch);
return lch;
};
const colorToRgb = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToRgb",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const rgb = convertColorToRgb(value, opt);
setCache(cacheKey, rgb);
return rgb;
};
const colorToXyz = (value, opt = {}) => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "colorToXyz",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
let xyz;
if (value.startsWith("color(")) {
[, ...xyz] = parseColorFunc(value, opt);
} else {
[, ...xyz] = parseColorValue(value, opt);
}
setCache(cacheKey, xyz);
return xyz;
};
const colorToXyzD50 = (value, opt = {}) => {
opt.d50 = true;
return colorToXyz(value, opt);
};
const convert = {
colorToHex,
colorToHsl,
colorToHwb,
colorToLab,
colorToLch,
colorToOklab,
colorToOklch,
colorToRgb,
colorToXyz,
colorToXyzD50,
numberToHex
};
export {
colorToHex,
colorToHsl,
colorToHwb,
colorToLab,
colorToLch,
colorToOklab,
colorToOklch,
colorToRgb,
colorToXyz,
colorToXyzD50,
convert,
numberToHex,
preProcess
};
//# sourceMappingURL=convert.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,89 @@
import { CSSToken } from '@csstools/css-tokenizer';
import { NullObject } from './cache.js';
import { Options } from './typedef.js';
/**
* Calclator
*/
export declare class Calculator {
#private;
/**
* constructor
*/
constructor();
get hasNum(): boolean;
set hasNum(value: boolean);
get numSum(): number[];
get numMul(): number[];
get hasPct(): boolean;
set hasPct(value: boolean);
get pctSum(): number[];
get pctMul(): number[];
get hasDim(): boolean;
set hasDim(value: boolean);
get dimSum(): string[];
get dimSub(): string[];
get dimMul(): string[];
get dimDiv(): string[];
get hasEtc(): boolean;
set hasEtc(value: boolean);
get etcSum(): string[];
get etcSub(): string[];
get etcMul(): string[];
get etcDiv(): string[];
/**
* clear values
* @returns void
*/
clear(): void;
/**
* sort values
* @param values - values
* @returns sorted values
*/
sort(values?: string[]): string[];
/**
* multiply values
* @returns resolved value
*/
multiply(): string;
/**
* sum values
* @returns resolved value
*/
sum(): string;
}
/**
* sort calc values
* @param values - values to sort
* @param [finalize] - finalize values
* @returns sorted values
*/
export declare const sortCalcValues: (values?: (number | string)[], finalize?: boolean) => string;
/**
* serialize calc
* @param value - CSS value
* @param [opt] - options
* @returns serialized value
*/
export declare const serializeCalc: (value: string, opt?: Options) => string;
/**
* resolve dimension
* @param token - CSS token
* @param [opt] - options
* @returns resolved value
*/
export declare const resolveDimension: (token: CSSToken, opt?: Options) => string | NullObject;
/**
* parse tokens
* @param tokens - CSS tokens
* @param [opt] - options
* @returns parsed tokens
*/
export declare const parseTokens: (tokens: CSSToken[], opt?: Options) => string[];
/**
* CSS calc()
* @param value - CSS value including calc()
* @param [opt] - options
* @returns resolved value
*/
export declare const cssCalc: (value: string, opt?: Options) => string;

View File

@@ -0,0 +1,848 @@
var __typeError = (msg) => {
throw TypeError(msg);
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var _hasNum, _numSum, _numMul, _hasPct, _pctSum, _pctMul, _hasDim, _dimSum, _dimSub, _dimMul, _dimDiv, _hasEtc, _etcSum, _etcSub, _etcMul, _etcDiv;
import { calc } from "@csstools/css-calc";
import { TokenType, tokenize } from "@csstools/css-tokenizer";
import { createCacheKey, getCache, CacheItem, setCache, NullObject } from "./cache.js";
import { isString, isStringOrNumber } from "./common.js";
import { resolveVar } from "./css-var.js";
import { roundToPrecision } from "./util.js";
import { VAL_SPEC, SYN_FN_VAR, SYN_FN_CALC, SYN_FN_VAR_START, NUM, ANGLE, LENGTH, SYN_FN_MATH_START } from "./constant.js";
const {
CloseParen: PAREN_CLOSE,
Comment: COMMENT,
Dimension: DIM,
EOF,
Function: FUNC,
OpenParen: PAREN_OPEN,
Whitespace: W_SPACE
} = TokenType;
const NAMESPACE = "css-calc";
const TRIA = 3;
const HEX = 16;
const MAX_PCT = 100;
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
const REG_FN_MATH_START = new RegExp(SYN_FN_MATH_START);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
const REG_FN_VAR_START = new RegExp(SYN_FN_VAR_START);
const REG_OPERATOR = /\s[*+/-]\s/;
const REG_TYPE_DIM = new RegExp(`^(${NUM})(${ANGLE}|${LENGTH})$`);
const REG_TYPE_DIM_PCT = new RegExp(`^(${NUM})(${ANGLE}|${LENGTH}|%)$`);
const REG_TYPE_PCT = new RegExp(`^(${NUM})%$`);
class Calculator {
/**
* constructor
*/
constructor() {
/* private */
// number
__privateAdd(this, _hasNum);
__privateAdd(this, _numSum);
__privateAdd(this, _numMul);
// percentage
__privateAdd(this, _hasPct);
__privateAdd(this, _pctSum);
__privateAdd(this, _pctMul);
// dimension
__privateAdd(this, _hasDim);
__privateAdd(this, _dimSum);
__privateAdd(this, _dimSub);
__privateAdd(this, _dimMul);
__privateAdd(this, _dimDiv);
// et cetra
__privateAdd(this, _hasEtc);
__privateAdd(this, _etcSum);
__privateAdd(this, _etcSub);
__privateAdd(this, _etcMul);
__privateAdd(this, _etcDiv);
__privateSet(this, _hasNum, false);
__privateSet(this, _numSum, []);
__privateSet(this, _numMul, []);
__privateSet(this, _hasPct, false);
__privateSet(this, _pctSum, []);
__privateSet(this, _pctMul, []);
__privateSet(this, _hasDim, false);
__privateSet(this, _dimSum, []);
__privateSet(this, _dimSub, []);
__privateSet(this, _dimMul, []);
__privateSet(this, _dimDiv, []);
__privateSet(this, _hasEtc, false);
__privateSet(this, _etcSum, []);
__privateSet(this, _etcSub, []);
__privateSet(this, _etcMul, []);
__privateSet(this, _etcDiv, []);
}
get hasNum() {
return __privateGet(this, _hasNum);
}
set hasNum(value) {
__privateSet(this, _hasNum, !!value);
}
get numSum() {
return __privateGet(this, _numSum);
}
get numMul() {
return __privateGet(this, _numMul);
}
get hasPct() {
return __privateGet(this, _hasPct);
}
set hasPct(value) {
__privateSet(this, _hasPct, !!value);
}
get pctSum() {
return __privateGet(this, _pctSum);
}
get pctMul() {
return __privateGet(this, _pctMul);
}
get hasDim() {
return __privateGet(this, _hasDim);
}
set hasDim(value) {
__privateSet(this, _hasDim, !!value);
}
get dimSum() {
return __privateGet(this, _dimSum);
}
get dimSub() {
return __privateGet(this, _dimSub);
}
get dimMul() {
return __privateGet(this, _dimMul);
}
get dimDiv() {
return __privateGet(this, _dimDiv);
}
get hasEtc() {
return __privateGet(this, _hasEtc);
}
set hasEtc(value) {
__privateSet(this, _hasEtc, !!value);
}
get etcSum() {
return __privateGet(this, _etcSum);
}
get etcSub() {
return __privateGet(this, _etcSub);
}
get etcMul() {
return __privateGet(this, _etcMul);
}
get etcDiv() {
return __privateGet(this, _etcDiv);
}
/**
* clear values
* @returns void
*/
clear() {
__privateSet(this, _hasNum, false);
__privateSet(this, _numSum, []);
__privateSet(this, _numMul, []);
__privateSet(this, _hasPct, false);
__privateSet(this, _pctSum, []);
__privateSet(this, _pctMul, []);
__privateSet(this, _hasDim, false);
__privateSet(this, _dimSum, []);
__privateSet(this, _dimSub, []);
__privateSet(this, _dimMul, []);
__privateSet(this, _dimDiv, []);
__privateSet(this, _hasEtc, false);
__privateSet(this, _etcSum, []);
__privateSet(this, _etcSub, []);
__privateSet(this, _etcMul, []);
__privateSet(this, _etcDiv, []);
}
/**
* sort values
* @param values - values
* @returns sorted values
*/
sort(values = []) {
const arr = [...values];
if (arr.length > 1) {
arr.sort((a, b) => {
let res;
if (REG_TYPE_DIM_PCT.test(a) && REG_TYPE_DIM_PCT.test(b)) {
const [, valA, unitA] = a.match(REG_TYPE_DIM_PCT);
const [, valB, unitB] = b.match(REG_TYPE_DIM_PCT);
if (unitA === unitB) {
if (Number(valA) === Number(valB)) {
res = 0;
} else if (Number(valA) > Number(valB)) {
res = 1;
} else {
res = -1;
}
} else if (unitA > unitB) {
res = 1;
} else {
res = -1;
}
} else {
if (a === b) {
res = 0;
} else if (a > b) {
res = 1;
} else {
res = -1;
}
}
return res;
});
}
return arr;
}
/**
* multiply values
* @returns resolved value
*/
multiply() {
const value = [];
let num;
if (__privateGet(this, _hasNum)) {
num = 1;
for (const i of __privateGet(this, _numMul)) {
num *= i;
if (num === 0 || !Number.isFinite(num) || Number.isNaN(num)) {
break;
}
}
if (!__privateGet(this, _hasPct) && !__privateGet(this, _hasDim) && !this.hasEtc) {
if (Number.isFinite(num)) {
num = roundToPrecision(num, HEX);
}
value.push(num);
}
}
if (__privateGet(this, _hasPct)) {
if (typeof num !== "number") {
num = 1;
}
for (const i of __privateGet(this, _pctMul)) {
num *= i;
if (num === 0 || !Number.isFinite(num) || Number.isNaN(num)) {
break;
}
}
if (Number.isFinite(num)) {
num = `${roundToPrecision(num, HEX)}%`;
}
if (!__privateGet(this, _hasDim) && !this.hasEtc) {
value.push(num);
}
}
if (__privateGet(this, _hasDim)) {
let dim = "";
let mul = "";
let div = "";
if (__privateGet(this, _dimMul).length) {
if (__privateGet(this, _dimMul).length === 1) {
[mul] = __privateGet(this, _dimMul);
} else {
mul = `${this.sort(__privateGet(this, _dimMul)).join(" * ")}`;
}
}
if (__privateGet(this, _dimDiv).length) {
if (__privateGet(this, _dimDiv).length === 1) {
[div] = __privateGet(this, _dimDiv);
} else {
div = `${this.sort(__privateGet(this, _dimDiv)).join(" * ")}`;
}
}
if (Number.isFinite(num)) {
if (mul) {
if (div) {
if (div.includes("*")) {
dim = calc(`calc(${num} * ${mul} / (${div}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${num} * ${mul} / ${div})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(${num} * ${mul})`, {
toCanonicalUnits: true
});
}
} else if (div.includes("*")) {
dim = calc(`calc(${num} / (${div}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${num} / ${div})`, {
toCanonicalUnits: true
});
}
value.push(dim.replace(/^calc/, ""));
} else {
if (!value.length && num !== void 0) {
value.push(num);
}
if (mul) {
if (div) {
if (div.includes("*")) {
dim = calc(`calc(${mul} / (${div}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${mul} / ${div})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(${mul})`, {
toCanonicalUnits: true
});
}
if (value.length) {
value.push("*", dim.replace(/^calc/, ""));
} else {
value.push(dim.replace(/^calc/, ""));
}
} else {
dim = calc(`calc(${div})`, {
toCanonicalUnits: true
});
if (value.length) {
value.push("/", dim.replace(/^calc/, ""));
} else {
value.push("1", "/", dim.replace(/^calc/, ""));
}
}
}
}
if (__privateGet(this, _hasEtc)) {
if (__privateGet(this, _etcMul).length) {
if (!value.length && num !== void 0) {
value.push(num);
}
const mul = this.sort(__privateGet(this, _etcMul)).join(" * ");
if (value.length) {
value.push(`* ${mul}`);
} else {
value.push(`${mul}`);
}
}
if (__privateGet(this, _etcDiv).length) {
const div = this.sort(__privateGet(this, _etcDiv)).join(" * ");
if (div.includes("*")) {
if (value.length) {
value.push(`/ (${div})`);
} else {
value.push(`1 / (${div})`);
}
} else if (value.length) {
value.push(`/ ${div}`);
} else {
value.push(`1 / ${div}`);
}
}
}
if (value.length) {
return value.join(" ");
}
return "";
}
/**
* sum values
* @returns resolved value
*/
sum() {
const value = [];
if (__privateGet(this, _hasNum)) {
let num = 0;
for (const i of __privateGet(this, _numSum)) {
num += i;
if (!Number.isFinite(num) || Number.isNaN(num)) {
break;
}
}
value.push(num);
}
if (__privateGet(this, _hasPct)) {
let num = 0;
for (const i of __privateGet(this, _pctSum)) {
num += i;
if (!Number.isFinite(num)) {
break;
}
}
if (Number.isFinite(num)) {
num = `${num}%`;
}
if (value.length) {
value.push(`+ ${num}`);
} else {
value.push(num);
}
}
if (__privateGet(this, _hasDim)) {
let dim, sum, sub;
if (__privateGet(this, _dimSum).length) {
sum = __privateGet(this, _dimSum).join(" + ");
}
if (__privateGet(this, _dimSub).length) {
sub = __privateGet(this, _dimSub).join(" + ");
}
if (sum) {
if (sub) {
if (sub.includes("-")) {
dim = calc(`calc(${sum} - (${sub}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${sum} - ${sub})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(${sum})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(-1 * (${sub}))`, {
toCanonicalUnits: true
});
}
if (value.length) {
value.push("+", dim.replace(/^calc/, ""));
} else {
value.push(dim.replace(/^calc/, ""));
}
}
if (__privateGet(this, _hasEtc)) {
if (__privateGet(this, _etcSum).length) {
const sum = this.sort(__privateGet(this, _etcSum)).map((item) => {
let res;
if (REG_OPERATOR.test(item) && !item.startsWith("(") && !item.endsWith(")")) {
res = `(${item})`;
} else {
res = item;
}
return res;
}).join(" + ");
if (value.length) {
if (__privateGet(this, _etcSum).length > 1) {
value.push(`+ (${sum})`);
} else {
value.push(`+ ${sum}`);
}
} else {
value.push(`${sum}`);
}
}
if (__privateGet(this, _etcSub).length) {
const sub = this.sort(__privateGet(this, _etcSub)).map((item) => {
let res;
if (REG_OPERATOR.test(item) && !item.startsWith("(") && !item.endsWith(")")) {
res = `(${item})`;
} else {
res = item;
}
return res;
}).join(" + ");
if (value.length) {
if (__privateGet(this, _etcSub).length > 1) {
value.push(`- (${sub})`);
} else {
value.push(`- ${sub}`);
}
} else if (__privateGet(this, _etcSub).length > 1) {
value.push(`-1 * (${sub})`);
} else {
value.push(`-1 * ${sub}`);
}
}
}
if (value.length) {
return value.join(" ");
}
return "";
}
}
_hasNum = new WeakMap();
_numSum = new WeakMap();
_numMul = new WeakMap();
_hasPct = new WeakMap();
_pctSum = new WeakMap();
_pctMul = new WeakMap();
_hasDim = new WeakMap();
_dimSum = new WeakMap();
_dimSub = new WeakMap();
_dimMul = new WeakMap();
_dimDiv = new WeakMap();
_hasEtc = new WeakMap();
_etcSum = new WeakMap();
_etcSub = new WeakMap();
_etcMul = new WeakMap();
_etcDiv = new WeakMap();
const sortCalcValues = (values = [], finalize = false) => {
if (values.length < TRIA) {
throw new Error(`Unexpected array length ${values.length}.`);
}
const start = values.shift();
if (!isString(start) || !start.endsWith("(")) {
throw new Error(`Unexpected token ${start}.`);
}
const end = values.pop();
if (end !== ")") {
throw new Error(`Unexpected token ${end}.`);
}
if (values.length === 1) {
const [value] = values;
if (!isStringOrNumber(value)) {
throw new Error(`Unexpected token ${value}.`);
}
return `${start}${value}${end}`;
}
const sortedValues = [];
const cal = new Calculator();
let operator = "";
const l = values.length;
for (let i = 0; i < l; i++) {
const value = values[i];
if (!isStringOrNumber(value)) {
throw new Error(`Unexpected token ${value}.`);
}
if (value === "*" || value === "/") {
operator = value;
} else if (value === "+" || value === "-") {
const sortedValue = cal.multiply();
if (sortedValue) {
sortedValues.push(sortedValue, value);
}
cal.clear();
operator = "";
} else {
const numValue = Number(value);
const strValue = `${value}`;
switch (operator) {
case "/": {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numMul.push(1 / numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT);
cal.hasPct = true;
cal.pctMul.push(MAX_PCT * MAX_PCT / Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimDiv.push(strValue);
} else {
cal.hasEtc = true;
cal.etcDiv.push(strValue);
}
break;
}
case "*":
default: {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numMul.push(numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT);
cal.hasPct = true;
cal.pctMul.push(Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimMul.push(strValue);
} else {
cal.hasEtc = true;
cal.etcMul.push(strValue);
}
}
}
}
if (i === l - 1) {
const sortedValue = cal.multiply();
if (sortedValue) {
sortedValues.push(sortedValue);
}
cal.clear();
operator = "";
}
}
let resolvedValue = "";
if (finalize && (sortedValues.includes("+") || sortedValues.includes("-"))) {
const finalizedValues = [];
cal.clear();
operator = "";
const l2 = sortedValues.length;
for (let i = 0; i < l2; i++) {
const value = sortedValues[i];
if (isStringOrNumber(value)) {
if (value === "+" || value === "-") {
operator = value;
} else {
const numValue = Number(value);
const strValue = `${value}`;
switch (operator) {
case "-": {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numSum.push(-1 * numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT);
cal.hasPct = true;
cal.pctSum.push(-1 * Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimSub.push(strValue);
} else {
cal.hasEtc = true;
cal.etcSub.push(strValue);
}
break;
}
case "+":
default: {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numSum.push(numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT);
cal.hasPct = true;
cal.pctSum.push(Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimSum.push(strValue);
} else {
cal.hasEtc = true;
cal.etcSum.push(strValue);
}
}
}
}
}
if (i === l2 - 1) {
const sortedValue = cal.sum();
if (sortedValue) {
finalizedValues.push(sortedValue);
}
cal.clear();
operator = "";
}
}
resolvedValue = finalizedValues.join(" ");
} else {
resolvedValue = sortedValues.join(" ");
}
return `${start}${resolvedValue}${end}`;
};
const serializeCalc = (value, opt = {}) => {
const { format = "" } = opt;
if (isString(value)) {
if (!REG_FN_VAR_START.test(value) || format !== VAL_SPEC) {
return value;
}
value = value.toLowerCase().trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "serializeCalc",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const items = tokenize({ css: value }).map((token) => {
const [type, value2] = token;
let res = "";
if (type !== W_SPACE && type !== COMMENT) {
res = value2;
}
return res;
}).filter((v) => v);
let startIndex = items.findLastIndex((item) => /\($/.test(item));
while (startIndex) {
const endIndex = items.findIndex((item, index) => {
return item === ")" && index > startIndex;
});
const slicedValues = items.slice(startIndex, endIndex + 1);
let serializedValue = sortCalcValues(slicedValues);
if (REG_FN_VAR_START.test(serializedValue)) {
serializedValue = calc(serializedValue, {
toCanonicalUnits: true
});
}
items.splice(startIndex, endIndex - startIndex + 1, serializedValue);
startIndex = items.findLastIndex((item) => /\($/.test(item));
}
const serializedCalc = sortCalcValues(items, true);
setCache(cacheKey, serializedCalc);
return serializedCalc;
};
const resolveDimension = (token, opt = {}) => {
if (!Array.isArray(token)) {
throw new TypeError(`${token} is not an array.`);
}
const [, , , , detail = {}] = token;
const { unit, value } = detail;
const { dimension = {} } = opt;
if (unit === "px") {
return `${value}${unit}`;
}
const relativeValue = Number(value);
if (unit && Number.isFinite(relativeValue)) {
let pixelValue;
if (Object.hasOwnProperty.call(dimension, unit)) {
pixelValue = dimension[unit];
} else if (typeof dimension.callback === "function") {
pixelValue = dimension.callback(unit);
}
pixelValue = Number(pixelValue);
if (Number.isFinite(pixelValue)) {
return `${relativeValue * pixelValue}px`;
}
}
return new NullObject();
};
const parseTokens = (tokens, opt = {}) => {
if (!Array.isArray(tokens)) {
throw new TypeError(`${tokens} is not an array.`);
}
const { format = "" } = opt;
const mathFunc = /* @__PURE__ */ new Set();
let nest = 0;
const res = [];
while (tokens.length) {
const token = tokens.shift();
if (!Array.isArray(token)) {
throw new TypeError(`${token} is not an array.`);
}
const [type = "", value = ""] = token;
switch (type) {
case DIM: {
if (format === VAL_SPEC && !mathFunc.has(nest)) {
res.push(value);
} else {
const resolvedValue = resolveDimension(token, opt);
if (isString(resolvedValue)) {
res.push(resolvedValue);
} else {
res.push(value);
}
}
break;
}
case FUNC:
case PAREN_OPEN: {
res.push(value);
nest++;
if (REG_FN_MATH_START.test(value)) {
mathFunc.add(nest);
}
break;
}
case PAREN_CLOSE: {
if (res.length) {
const lastValue = res[res.length - 1];
if (lastValue === " ") {
res.splice(-1, 1, value);
} else {
res.push(value);
}
} else {
res.push(value);
}
if (mathFunc.has(nest)) {
mathFunc.delete(nest);
}
nest--;
break;
}
case W_SPACE: {
if (res.length) {
const lastValue = res[res.length - 1];
if (isString(lastValue) && !lastValue.endsWith("(") && lastValue !== " ") {
res.push(value);
}
}
break;
}
default: {
if (type !== COMMENT && type !== EOF) {
res.push(value);
}
}
}
}
return res;
};
const cssCalc = (value, opt = {}) => {
const { format = "" } = opt;
if (isString(value)) {
if (REG_FN_VAR.test(value)) {
if (format === VAL_SPEC) {
return value;
} else {
const resolvedValue2 = resolveVar(value, opt);
if (isString(resolvedValue2)) {
return resolvedValue2;
} else {
return "";
}
}
} else if (!REG_FN_CALC.test(value)) {
return value;
}
value = value.toLowerCase().trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "cssCalc",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const tokens = tokenize({ css: value });
const values = parseTokens(tokens, opt);
let resolvedValue = calc(values.join(""), {
toCanonicalUnits: true
});
if (REG_FN_VAR_START.test(value)) {
if (REG_TYPE_DIM_PCT.test(resolvedValue)) {
const [, val, unit] = resolvedValue.match(
REG_TYPE_DIM_PCT
);
resolvedValue = `${roundToPrecision(Number(val), HEX)}${unit}`;
}
if (resolvedValue && !REG_FN_VAR_START.test(resolvedValue) && format === VAL_SPEC) {
resolvedValue = `calc(${resolvedValue})`;
}
}
setCache(cacheKey, resolvedValue);
return resolvedValue;
};
export {
Calculator,
cssCalc,
parseTokens,
resolveDimension,
serializeCalc,
sortCalcValues
};
//# sourceMappingURL=css-calc.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,54 @@
import { Options } from './typedef.js';
/**
* @type ColorStopList - list of color stops
*/
type ColorStopList = [string, string, ...string[]];
/**
* @typedef Gradient - parsed CSS gradient
* @property value - input value
* @property type - gradient type
* @property [gradientLine] - gradient line
* @property colorStopList - list of color stops
*/
interface Gradient {
value: string;
type: string;
gradientLine?: string;
colorStopList: ColorStopList;
}
/**
* get gradient type
* @param value - gradient value
* @returns gradient type
*/
export declare const getGradientType: (value: string) => string;
/**
* validate gradient line
* @param value - gradient line value
* @param type - gradient type
* @returns result
*/
export declare const validateGradientLine: (value: string, type: string) => boolean;
/**
* validate color stop list
* @param list
* @param type
* @param [opt]
* @returns result
*/
export declare const validateColorStopList: (list: string[], type: string, opt?: Options) => boolean;
/**
* parse CSS gradient
* @param value - gradient value
* @param [opt] - options
* @returns parsed result
*/
export declare const parseGradient: (value: string, opt?: Options) => Gradient | null;
/**
* is CSS gradient
* @param value - CSS value
* @param [opt] - options
* @returns result
*/
export declare const isGradient: (value: string, opt?: Options) => boolean;
export {};

View File

@@ -0,0 +1,193 @@
import { createCacheKey, getCache, CacheItem, setCache } from "./cache.js";
import { isString } from "./common.js";
import { splitValue, isColor } from "./util.js";
import { NUM, ANGLE, PCT, LENGTH, CS_RECT, CS_HUE, NUM_POSITIVE } from "./constant.js";
const NAMESPACE = "css-gradient";
const DIM_ANGLE = `${NUM}(?:${ANGLE})`;
const DIM_ANGLE_PCT = `${DIM_ANGLE}|${PCT}`;
const DIM_LEN = `${NUM}(?:${LENGTH})|0`;
const DIM_LEN_PCT = `${DIM_LEN}|${PCT}`;
const DIM_LEN_PCT_POSI = `${NUM_POSITIVE}(?:${LENGTH}|%)|0`;
const DIM_LEN_POSI = `${NUM_POSITIVE}(?:${LENGTH})|0`;
const CTR = "center";
const L_R = "left|right";
const T_B = "top|bottom";
const S_E = "start|end";
const AXIS_X = `${L_R}|x-(?:${S_E})`;
const AXIS_Y = `${T_B}|y-(?:${S_E})`;
const BLOCK = `block-(?:${S_E})`;
const INLINE = `inline-(?:${S_E})`;
const POS_1 = `${CTR}|${AXIS_X}|${AXIS_Y}|${BLOCK}|${INLINE}|${DIM_LEN_PCT}`;
const POS_2 = [
`(?:${CTR}|${AXIS_X})\\s+(?:${CTR}|${AXIS_Y})`,
`(?:${CTR}|${AXIS_Y})\\s+(?:${CTR}|${AXIS_X})`,
`(?:${CTR}|${AXIS_X}|${DIM_LEN_PCT})\\s+(?:${CTR}|${AXIS_Y}|${DIM_LEN_PCT})`,
`(?:${CTR}|${BLOCK})\\s+(?:${CTR}|${INLINE})`,
`(?:${CTR}|${INLINE})\\s+(?:${CTR}|${BLOCK})`,
`(?:${CTR}|${S_E})\\s+(?:${CTR}|${S_E})`
].join("|");
const POS_4 = [
`(?:${AXIS_X})\\s+(?:${DIM_LEN_PCT})\\s+(?:${AXIS_Y})\\s+(?:${DIM_LEN_PCT})`,
`(?:${AXIS_Y})\\s+(?:${DIM_LEN_PCT})\\s+(?:${AXIS_X})\\s+(?:${DIM_LEN_PCT})`,
`(?:${BLOCK})\\s+(?:${DIM_LEN_PCT})\\s+(?:${INLINE})\\s+(?:${DIM_LEN_PCT})`,
`(?:${INLINE})\\s+(?:${DIM_LEN_PCT})\\s+(?:${BLOCK})\\s+(?:${DIM_LEN_PCT})`,
`(?:${S_E})\\s+(?:${DIM_LEN_PCT})\\s+(?:${S_E})\\s+(?:${DIM_LEN_PCT})`
].join("|");
const RAD_EXTENT = "(?:clos|farth)est-(?:corner|side)";
const RAD_SIZE = [
`${RAD_EXTENT}(?:\\s+${RAD_EXTENT})?`,
`${DIM_LEN_POSI}`,
`(?:${DIM_LEN_PCT_POSI})\\s+(?:${DIM_LEN_PCT_POSI})`
].join("|");
const RAD_SHAPE = "circle|ellipse";
const FROM_ANGLE = `from\\s+${DIM_ANGLE}`;
const AT_POSITION = `at\\s+(?:${POS_1}|${POS_2}|${POS_4})`;
const TO_SIDE_CORNER = `to\\s+(?:(?:${L_R})(?:\\s(?:${T_B}))?|(?:${T_B})(?:\\s(?:${L_R}))?)`;
const IN_COLOR_SPACE = `in\\s+(?:${CS_RECT}|${CS_HUE})`;
const REG_GRAD = /^(?:repeating-)?(?:conic|linear|radial)-gradient\(/;
const REG_GRAD_CAPT = /^((?:repeating-)?(?:conic|linear|radial)-gradient)\(/;
const getGradientType = (value) => {
if (isString(value)) {
value = value.trim();
if (REG_GRAD.test(value)) {
const [, type] = value.match(REG_GRAD_CAPT);
return type;
}
}
return "";
};
const validateGradientLine = (value, type) => {
if (isString(value) && isString(type)) {
value = value.trim();
type = type.trim();
let lineSyntax = "";
if (/^(?:repeating-)?linear-gradient$/.test(type)) {
lineSyntax = [
`(?:${DIM_ANGLE}|${TO_SIDE_CORNER})(?:\\s+${IN_COLOR_SPACE})?`,
`${IN_COLOR_SPACE}(?:\\s+(?:${DIM_ANGLE}|${TO_SIDE_CORNER}))?`
].join("|");
} else if (/^(?:repeating-)?radial-gradient$/.test(type)) {
lineSyntax = [
`(?:${RAD_SHAPE})(?:\\s+(?:${RAD_SIZE}))?(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
`(?:${RAD_SIZE})(?:\\s+(?:${RAD_SHAPE}))?(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
`${AT_POSITION}(?:\\s+${IN_COLOR_SPACE})?`,
`${IN_COLOR_SPACE}(?:\\s+${RAD_SHAPE})(?:\\s+(?:${RAD_SIZE}))?(?:\\s+${AT_POSITION})?`,
`${IN_COLOR_SPACE}(?:\\s+${RAD_SIZE})(?:\\s+(?:${RAD_SHAPE}))?(?:\\s+${AT_POSITION})?`,
`${IN_COLOR_SPACE}(?:\\s+${AT_POSITION})?`
].join("|");
} else if (/^(?:repeating-)?conic-gradient$/.test(type)) {
lineSyntax = [
`${FROM_ANGLE}(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
`${AT_POSITION}(?:\\s+${IN_COLOR_SPACE})?`,
`${IN_COLOR_SPACE}(?:\\s+${FROM_ANGLE})?(?:\\s+${AT_POSITION})?`
].join("|");
}
if (lineSyntax) {
const reg = new RegExp(`^(?:${lineSyntax})$`);
return reg.test(value);
}
}
return false;
};
const validateColorStopList = (list, type, opt = {}) => {
if (Array.isArray(list) && list.length > 1) {
const dimension = /^(?:repeating-)?conic-gradient$/.test(type) ? DIM_ANGLE_PCT : DIM_LEN_PCT;
const regColorHint = new RegExp(`^(?:${dimension})$`);
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
const arr = [];
for (const item of list) {
if (isString(item)) {
if (regColorHint.test(item)) {
arr.push("hint");
} else {
const color = item.replace(regDimension, "");
if (isColor(color, opt)) {
arr.push("color");
} else {
return false;
}
}
}
}
const value = arr.join(",");
return /^color(?:,(?:hint,)?color)+$/.test(value);
}
return false;
};
const parseGradient = (value, opt = {}) => {
if (isString(value)) {
value = value.trim();
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "parseGradient",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return null;
}
return cachedResult.item;
}
const type = getGradientType(value);
const gradValue = value.replace(REG_GRAD, "").replace(/\)$/, "");
if (type && gradValue) {
const [lineOrColorStop = "", ...colorStops] = splitValue(gradValue, ",");
const dimension = /^(?:repeating-)?conic-gradient$/.test(type) ? DIM_ANGLE_PCT : DIM_LEN_PCT;
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
let isColorStop = false;
if (regDimension.test(lineOrColorStop)) {
const colorStop = lineOrColorStop.replace(regDimension, "");
if (isColor(colorStop, opt)) {
isColorStop = true;
}
} else if (isColor(lineOrColorStop, opt)) {
isColorStop = true;
}
if (isColorStop) {
colorStops.unshift(lineOrColorStop);
const valid = validateColorStopList(colorStops, type, opt);
if (valid) {
const res = {
value,
type,
colorStopList: colorStops
};
setCache(cacheKey, res);
return res;
}
} else if (colorStops.length > 1) {
const gradientLine = lineOrColorStop;
const valid = validateGradientLine(gradientLine, type) && validateColorStopList(colorStops, type, opt);
if (valid) {
const res = {
value,
type,
gradientLine,
colorStopList: colorStops
};
setCache(cacheKey, res);
return res;
}
}
}
setCache(cacheKey, null);
return null;
}
return null;
};
const isGradient = (value, opt = {}) => {
const gradient = parseGradient(value, opt);
return gradient !== null;
};
export {
getGradientType,
isGradient,
parseGradient,
validateColorStopList,
validateGradientLine
};
//# sourceMappingURL=css-gradient.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,31 @@
import { CSSToken } from '@csstools/css-tokenizer';
import { NullObject } from './cache.js';
import { Options } from './typedef.js';
/**
* resolve custom property
* @param tokens - CSS tokens
* @param [opt] - options
* @returns result - [tokens, resolvedValue]
*/
export declare function resolveCustomProperty(tokens: CSSToken[], opt?: Options): [CSSToken[], string];
/**
* parse tokens
* @param tokens - CSS tokens
* @param [opt] - options
* @returns parsed tokens
*/
export declare function parseTokens(tokens: CSSToken[], opt?: Options): string[] | NullObject;
/**
* resolve CSS var()
* @param value - CSS value including var()
* @param [opt] - options
* @returns resolved value
*/
export declare function resolveVar(value: string, opt?: Options): string | NullObject;
/**
* CSS var()
* @param value - CSS value including var()
* @param [opt] - options
* @returns resolved value
*/
export declare const cssVar: (value: string, opt?: Options) => string;

View File

@@ -0,0 +1,195 @@
import { TokenType, tokenize } from "@csstools/css-tokenizer";
import { createCacheKey, getCache, CacheItem, setCache, NullObject } from "./cache.js";
import { isString } from "./common.js";
import { cssCalc } from "./css-calc.js";
import { isColor } from "./util.js";
import { VAL_SPEC, SYN_FN_VAR, FN_VAR, SYN_FN_CALC } from "./constant.js";
const {
CloseParen: PAREN_CLOSE,
Comment: COMMENT,
EOF,
Ident: IDENT,
Whitespace: W_SPACE
} = TokenType;
const NAMESPACE = "css-var";
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
function resolveCustomProperty(tokens, opt = {}) {
if (!Array.isArray(tokens)) {
throw new TypeError(`${tokens} is not an array.`);
}
const { customProperty = {} } = opt;
const items = [];
while (tokens.length) {
const token = tokens.shift();
if (!Array.isArray(token)) {
throw new TypeError(`${token} is not an array.`);
}
const [type, value] = token;
if (type === PAREN_CLOSE) {
break;
}
if (value === FN_VAR) {
const [restTokens, item] = resolveCustomProperty(tokens, opt);
tokens = restTokens;
if (item) {
items.push(item);
}
} else if (type === IDENT) {
if (value.startsWith("--")) {
let item;
if (Object.hasOwnProperty.call(customProperty, value)) {
item = customProperty[value];
} else if (typeof customProperty.callback === "function") {
item = customProperty.callback(value);
}
if (item) {
items.push(item);
}
} else if (value) {
items.push(value);
}
}
}
let resolveAsColor = false;
if (items.length > 1) {
const lastValue = items[items.length - 1];
resolveAsColor = isColor(lastValue);
}
let resolvedValue = "";
for (let item of items) {
item = item.trim();
if (REG_FN_VAR.test(item)) {
const resolvedItem = resolveVar(item, opt);
if (isString(resolvedItem)) {
if (resolveAsColor) {
if (isColor(resolvedItem)) {
resolvedValue = resolvedItem;
}
} else {
resolvedValue = resolvedItem;
}
}
} else if (REG_FN_CALC.test(item)) {
item = cssCalc(item, opt);
if (resolveAsColor) {
if (isColor(item)) {
resolvedValue = item;
}
} else {
resolvedValue = item;
}
} else if (item && !/^(?:inherit|initial|revert(?:-layer)?|unset)$/.test(item)) {
if (resolveAsColor) {
if (isColor(item)) {
resolvedValue = item;
}
} else {
resolvedValue = item;
}
}
if (resolvedValue) {
break;
}
}
return [tokens, resolvedValue];
}
function parseTokens(tokens, opt = {}) {
const res = [];
while (tokens.length) {
const token = tokens.shift();
const [type = "", value = ""] = token;
if (value === FN_VAR) {
const [restTokens, resolvedValue] = resolveCustomProperty(tokens, opt);
if (!resolvedValue) {
return new NullObject();
}
tokens = restTokens;
res.push(resolvedValue);
} else {
switch (type) {
case PAREN_CLOSE: {
if (res.length) {
const lastValue = res[res.length - 1];
if (lastValue === " ") {
res.splice(-1, 1, value);
} else {
res.push(value);
}
} else {
res.push(value);
}
break;
}
case W_SPACE: {
if (res.length) {
const lastValue = res[res.length - 1];
if (isString(lastValue) && !lastValue.endsWith("(") && lastValue !== " ") {
res.push(value);
}
}
break;
}
default: {
if (type !== COMMENT && type !== EOF) {
res.push(value);
}
}
}
}
}
return res;
}
function resolveVar(value, opt = {}) {
const { format = "" } = opt;
if (isString(value)) {
if (!REG_FN_VAR.test(value) || format === VAL_SPEC) {
return value;
}
value = value.trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "resolveVar",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return cachedResult;
}
return cachedResult.item;
}
const tokens = tokenize({ css: value });
const values = parseTokens(tokens, opt);
if (Array.isArray(values)) {
let color = values.join("");
if (REG_FN_CALC.test(color)) {
color = cssCalc(color, opt);
}
setCache(cacheKey, color);
return color;
} else {
setCache(cacheKey, null);
return new NullObject();
}
}
const cssVar = (value, opt = {}) => {
const resolvedValue = resolveVar(value, opt);
if (isString(resolvedValue)) {
return resolvedValue;
}
return "";
};
export {
cssVar,
parseTokens,
resolveCustomProperty,
resolveVar
};
//# sourceMappingURL=css-var.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,29 @@
import { CSSToken } from '@csstools/css-tokenizer';
import { NullObject } from './cache.js';
import { ColorChannels, Options, StringColorChannels } from './typedef.js';
/**
* @type NumberOrStringColorChannels - color channel
*/
type NumberOrStringColorChannels = ColorChannels & StringColorChannels;
/**
* resolve relative color channels
* @param tokens - CSS tokens
* @param [opt] - options
* @returns resolved color channels
*/
export declare function resolveColorChannels(tokens: CSSToken[], opt?: Options): NumberOrStringColorChannels | NullObject;
/**
* extract origin color
* @param value - CSS color value
* @param [opt] - options
* @returns origin color value
*/
export declare function extractOriginColor(value: string, opt?: Options): string | NullObject;
/**
* resolve relative color
* @param value - CSS relative color value
* @param [opt] - options
* @returns resolved value
*/
export declare function resolveRelativeColor(value: string, opt?: Options): string | NullObject;
export {};

View File

@@ -0,0 +1,487 @@
import { SyntaxFlag, color } from "@csstools/css-color-parser";
import { parseComponentValue } from "@csstools/css-parser-algorithms";
import { TokenType, tokenize } from "@csstools/css-tokenizer";
import { createCacheKey, getCache, CacheItem, NullObject, setCache } from "./cache.js";
import { convertColorToRgb, NAMED_COLORS } from "./color.js";
import { isString, isStringOrNumber } from "./common.js";
import { resolveDimension, serializeCalc } from "./css-calc.js";
import { resolveColor } from "./resolve.js";
import { roundToPrecision } from "./util.js";
import { VAL_SPEC, FN_VAR, NONE, SYN_FN_VAR, FN_REL, CS_LAB, CS_LCH, FN_REL_CAPT, SYN_COLOR_TYPE, SYN_MIX, SYN_FN_MATH_START } from "./constant.js";
const {
CloseParen: PAREN_CLOSE,
Comment: COMMENT,
Dimension: DIM,
EOF,
Function: FUNC,
Ident: IDENT,
Number: NUM,
OpenParen: PAREN_OPEN,
Percentage: PCT,
Whitespace: W_SPACE
} = TokenType;
const { HasNoneKeywords: KEY_NONE } = SyntaxFlag;
const NAMESPACE = "relative-color";
const OCT = 8;
const DEC = 10;
const HEX = 16;
const MAX_PCT = 100;
const MAX_RGB = 255;
const REG_COLOR_CAPT = new RegExp(
`^${FN_REL}(${SYN_COLOR_TYPE}|${SYN_MIX})\\s+`
);
const REG_CS_HSL = /(?:hsla?|hwb)$/;
const REG_CS_CIE = new RegExp(`^(?:${CS_LAB}|${CS_LCH})$`);
const REG_FN_MATH_START = new RegExp(SYN_FN_MATH_START);
const REG_FN_REL = new RegExp(FN_REL);
const REG_FN_REL_CAPT = new RegExp(`^${FN_REL_CAPT}`);
const REG_FN_REL_START = new RegExp(`^${FN_REL}`);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
function resolveColorChannels(tokens, opt = {}) {
if (!Array.isArray(tokens)) {
throw new TypeError(`${tokens} is not an array.`);
}
const { colorSpace = "", format = "" } = opt;
const colorChannels = /* @__PURE__ */ new Map([
["color", ["r", "g", "b", "alpha"]],
["hsl", ["h", "s", "l", "alpha"]],
["hsla", ["h", "s", "l", "alpha"]],
["hwb", ["h", "w", "b", "alpha"]],
["lab", ["l", "a", "b", "alpha"]],
["lch", ["l", "c", "h", "alpha"]],
["oklab", ["l", "a", "b", "alpha"]],
["oklch", ["l", "c", "h", "alpha"]],
["rgb", ["r", "g", "b", "alpha"]],
["rgba", ["r", "g", "b", "alpha"]]
]);
const colorChannel = colorChannels.get(colorSpace);
if (!colorChannel) {
return new NullObject();
}
const mathFunc = /* @__PURE__ */ new Set();
const channels = [[], [], [], []];
let i = 0;
let nest = 0;
let func = false;
while (tokens.length) {
const token = tokens.shift();
if (!Array.isArray(token)) {
throw new TypeError(`${token} is not an array.`);
}
const [type, value, , , detail] = token;
const channel = channels[i];
if (Array.isArray(channel)) {
switch (type) {
case DIM: {
const resolvedValue = resolveDimension(token, opt);
if (isString(resolvedValue)) {
channel.push(resolvedValue);
} else {
channel.push(value);
}
break;
}
case FUNC: {
channel.push(value);
func = true;
nest++;
if (REG_FN_MATH_START.test(value)) {
mathFunc.add(nest);
}
break;
}
case IDENT: {
if (!colorChannel.includes(value)) {
return new NullObject();
}
channel.push(value);
if (!func) {
i++;
}
break;
}
case NUM: {
channel.push(Number(detail == null ? void 0 : detail.value));
if (!func) {
i++;
}
break;
}
case PAREN_OPEN: {
channel.push(value);
nest++;
break;
}
case PAREN_CLOSE: {
if (func) {
const lastValue = channel[channel.length - 1];
if (lastValue === " ") {
channel.splice(-1, 1, value);
} else {
channel.push(value);
}
if (mathFunc.has(nest)) {
mathFunc.delete(nest);
}
nest--;
if (nest === 0) {
func = false;
i++;
}
}
break;
}
case PCT: {
channel.push(Number(detail == null ? void 0 : detail.value) / MAX_PCT);
if (!func) {
i++;
}
break;
}
case W_SPACE: {
if (channel.length && func) {
const lastValue = channel[channel.length - 1];
if (typeof lastValue === "number") {
channel.push(value);
} else if (isString(lastValue) && !lastValue.endsWith("(") && lastValue !== " ") {
channel.push(value);
}
}
break;
}
default: {
if (type !== COMMENT && type !== EOF && func) {
channel.push(value);
}
}
}
}
}
const channelValues = [];
for (const channel of channels) {
if (channel.length === 1) {
const [resolvedValue] = channel;
if (isStringOrNumber(resolvedValue)) {
channelValues.push(resolvedValue);
}
} else if (channel.length) {
const resolvedValue = serializeCalc(channel.join(""), {
format
});
channelValues.push(resolvedValue);
}
}
return channelValues;
}
function extractOriginColor(value, opt = {}) {
const { currentColor = "", format = "" } = opt;
if (isString(value)) {
value = value.toLowerCase().trim();
if (!value) {
return new NullObject();
}
if (!REG_FN_REL_START.test(value)) {
return value;
}
} else {
return new NullObject();
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "extractOriginColor",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return cachedResult;
}
return cachedResult.item;
}
if (/currentcolor/.test(value)) {
if (currentColor) {
value = value.replace(/currentcolor/g, currentColor);
} else {
setCache(cacheKey, null);
return new NullObject();
}
}
let colorSpace = "";
if (REG_FN_REL_CAPT.test(value)) {
[, colorSpace] = value.match(REG_FN_REL_CAPT);
}
opt.colorSpace = colorSpace;
if (REG_COLOR_CAPT.test(value)) {
const [, originColor] = value.match(REG_COLOR_CAPT);
const [, restValue] = value.split(originColor);
if (/^[a-z]+$/.test(originColor)) {
if (!/^transparent$/.test(originColor) && !Object.prototype.hasOwnProperty.call(NAMED_COLORS, originColor)) {
setCache(cacheKey, null);
return new NullObject();
}
} else if (format === VAL_SPEC) {
const resolvedOriginColor = resolveColor(originColor, opt);
if (isString(resolvedOriginColor)) {
value = value.replace(originColor, resolvedOriginColor);
}
}
if (format === VAL_SPEC) {
const tokens = tokenize({ css: restValue });
const channelValues = resolveColorChannels(tokens, opt);
if (channelValues instanceof NullObject) {
setCache(cacheKey, null);
return channelValues;
}
const [v1, v2, v3, v4] = channelValues;
let channelValue = "";
if (isStringOrNumber(v4)) {
channelValue = ` ${v1} ${v2} ${v3} / ${v4})`;
} else {
channelValue = ` ${channelValues.join(" ")})`;
}
if (restValue !== channelValue) {
value = value.replace(restValue, channelValue);
}
}
} else {
const [, restValue] = value.split(REG_FN_REL_START);
const tokens = tokenize({ css: restValue });
const originColor = [];
let nest = 0;
while (tokens.length) {
const [type, tokenValue] = tokens.shift();
switch (type) {
case FUNC:
case PAREN_OPEN: {
originColor.push(tokenValue);
nest++;
break;
}
case PAREN_CLOSE: {
const lastValue = originColor[originColor.length - 1];
if (lastValue === " ") {
originColor.splice(-1, 1, tokenValue);
} else if (isString(lastValue)) {
originColor.push(tokenValue);
}
nest--;
break;
}
case W_SPACE: {
const lastValue = originColor[originColor.length - 1];
if (isString(lastValue) && !lastValue.endsWith("(") && lastValue !== " ") {
originColor.push(tokenValue);
}
break;
}
default: {
if (type !== COMMENT && type !== EOF) {
originColor.push(tokenValue);
}
}
}
if (nest === 0) {
break;
}
}
const resolvedOriginColor = resolveRelativeColor(
originColor.join("").trim(),
opt
);
if (resolvedOriginColor instanceof NullObject) {
setCache(cacheKey, null);
return resolvedOriginColor;
}
const channelValues = resolveColorChannels(tokens, opt);
if (channelValues instanceof NullObject) {
setCache(cacheKey, null);
return channelValues;
}
const [v1, v2, v3, v4] = channelValues;
let channelValue = "";
if (isStringOrNumber(v4)) {
channelValue = ` ${v1} ${v2} ${v3} / ${v4})`;
} else {
channelValue = ` ${channelValues.join(" ")})`;
}
value = value.replace(restValue, `${resolvedOriginColor}${channelValue}`);
}
setCache(cacheKey, value);
return value;
}
function resolveRelativeColor(value, opt = {}) {
const { format = "" } = opt;
if (isString(value)) {
if (REG_FN_VAR.test(value)) {
if (format === VAL_SPEC) {
return value;
} else {
throw new SyntaxError(`Unexpected token ${FN_VAR} found.`);
}
} else if (!REG_FN_REL.test(value)) {
return value;
}
value = value.toLowerCase().trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "resolveRelativeColor",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return cachedResult;
}
return cachedResult.item;
}
const originColor = extractOriginColor(value, opt);
if (originColor instanceof NullObject) {
setCache(cacheKey, null);
return originColor;
}
value = originColor;
if (format === VAL_SPEC) {
if (value.startsWith("rgba(")) {
value = value.replace(/^rgba\(/, "rgb(");
} else if (value.startsWith("hsla(")) {
value = value.replace(/^hsla\(/, "hsl(");
}
return value;
}
const tokens = tokenize({ css: value });
const components = parseComponentValue(tokens);
const parsedComponents = color(components);
if (!parsedComponents) {
setCache(cacheKey, null);
return new NullObject();
}
const {
alpha: alphaComponent,
channels: channelsComponent,
colorNotation,
syntaxFlags
} = parsedComponents;
let alpha;
if (Number.isNaN(Number(alphaComponent))) {
if (syntaxFlags instanceof Set && syntaxFlags.has(KEY_NONE)) {
alpha = NONE;
} else {
alpha = 0;
}
} else {
alpha = roundToPrecision(Number(alphaComponent), OCT);
}
let v1;
let v2;
let v3;
[v1, v2, v3] = channelsComponent;
let resolvedValue;
if (REG_CS_CIE.test(colorNotation)) {
const hasNone = syntaxFlags instanceof Set && syntaxFlags.has(KEY_NONE);
if (Number.isNaN(v1)) {
if (hasNone) {
v1 = NONE;
} else {
v1 = 0;
}
} else {
v1 = roundToPrecision(v1, HEX);
}
if (Number.isNaN(v2)) {
if (hasNone) {
v2 = NONE;
} else {
v2 = 0;
}
} else {
v2 = roundToPrecision(v2, HEX);
}
if (Number.isNaN(v3)) {
if (hasNone) {
v3 = NONE;
} else {
v3 = 0;
}
} else {
v3 = roundToPrecision(v3, HEX);
}
if (alpha === 1) {
resolvedValue = `${colorNotation}(${v1} ${v2} ${v3})`;
} else {
resolvedValue = `${colorNotation}(${v1} ${v2} ${v3} / ${alpha})`;
}
} else if (REG_CS_HSL.test(colorNotation)) {
if (Number.isNaN(v1)) {
v1 = 0;
}
if (Number.isNaN(v2)) {
v2 = 0;
}
if (Number.isNaN(v3)) {
v3 = 0;
}
let [r, g, b] = convertColorToRgb(
`${colorNotation}(${v1} ${v2} ${v3} / ${alpha})`
);
r = roundToPrecision(r / MAX_RGB, DEC);
g = roundToPrecision(g / MAX_RGB, DEC);
b = roundToPrecision(b / MAX_RGB, DEC);
if (alpha === 1) {
resolvedValue = `color(srgb ${r} ${g} ${b})`;
} else {
resolvedValue = `color(srgb ${r} ${g} ${b} / ${alpha})`;
}
} else {
const cs = colorNotation === "rgb" ? "srgb" : colorNotation;
const hasNone = syntaxFlags instanceof Set && syntaxFlags.has(KEY_NONE);
if (Number.isNaN(v1)) {
if (hasNone) {
v1 = NONE;
} else {
v1 = 0;
}
} else {
v1 = roundToPrecision(v1, DEC);
}
if (Number.isNaN(v2)) {
if (hasNone) {
v2 = NONE;
} else {
v2 = 0;
}
} else {
v2 = roundToPrecision(v2, DEC);
}
if (Number.isNaN(v3)) {
if (hasNone) {
v3 = NONE;
} else {
v3 = 0;
}
} else {
v3 = roundToPrecision(v3, DEC);
}
if (alpha === 1) {
resolvedValue = `color(${cs} ${v1} ${v2} ${v3})`;
} else {
resolvedValue = `color(${cs} ${v1} ${v2} ${v3} / ${alpha})`;
}
}
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
export {
extractOriginColor,
resolveColorChannels,
resolveRelativeColor
};
//# sourceMappingURL=relative-color.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,52 @@
import { NullObject } from './cache.js';
import { Options } from './typedef.js';
/**
* resolve color
* @param value - CSS color value
* @param [opt] - options
* @returns resolved color
*/
export declare const resolveColor: (value: string, opt?: Options) => string | NullObject;
/**
* resolve CSS color
* @param value
* - CSS color value
* - system colors are not supported
* @param [opt] - options
* @param [opt.currentColor]
* - color to use for `currentcolor` keyword
* - if omitted, it will be treated as a missing color
* i.e. `rgb(none none none / none)`
* @param [opt.customProperty]
* - custom properties
* - pair of `--` prefixed property name and value,
* e.g. `customProperty: { '--some-color': '#0000ff' }`
* - and/or `callback` function to get the value of the custom property,
* e.g. `customProperty: { callback: someDeclaration.getPropertyValue }`
* @param [opt.dimension]
* - dimension, convert relative length to pixels
* - pair of unit and it's value as a number in pixels,
* e.g. `dimension: { em: 12, rem: 16, vw: 10.26 }`
* - and/or `callback` function to get the value as a number in pixels,
* e.g. `dimension: { callback: convertUnitToPixel }`
* @param [opt.format]
* - output format, one of below
* - `computedValue` (default), [computed value][139] of the color
* - `specifiedValue`, [specified value][140] of the color
* - `hex`, hex color notation, i.e. `rrggbb`
* - `hexAlpha`, hex color notation with alpha channel, i.e. `#rrggbbaa`
* @returns
* - one of rgba?(), #rrggbb(aa)?, color-name, '(empty-string)',
* color(color-space r g b / alpha), color(color-space x y z / alpha),
* lab(l a b / alpha), lch(l c h / alpha), oklab(l a b / alpha),
* oklch(l c h / alpha), null
* - in `computedValue`, values are numbers, however `rgb()` values are
* integers
* - in `specifiedValue`, returns `empty string` for unknown and/or invalid
* color
* - in `hex`, returns `null` for `transparent`, and also returns `null` if
* any of `r`, `g`, `b`, `alpha` is not a number
* - in `hexAlpha`, returns `#00000000` for `transparent`,
* however returns `null` if any of `r`, `g`, `b`, `alpha` is not a number
*/
export declare const resolve: (value: string, opt?: Options) => string | null;

View File

@@ -0,0 +1,288 @@
import { NullObject, createCacheKey, getCache, CacheItem, setCache } from "./cache.js";
import { resolveColorMix, resolveColorFunc, resolveColorValue, convertRgbToHex } from "./color.js";
import { isString } from "./common.js";
import { cssCalc } from "./css-calc.js";
import { resolveVar } from "./css-var.js";
import { resolveRelativeColor } from "./relative-color.js";
import { VAL_COMP, VAL_SPEC, FN_MIX, FN_COLOR, SYN_FN_VAR, SYN_FN_REL, SYN_FN_CALC } from "./constant.js";
const NAMESPACE = "resolve";
const RGB_TRANSPARENT = "rgba(0, 0, 0, 0)";
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
const REG_FN_REL = new RegExp(SYN_FN_REL);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
const resolveColor = (value, opt = {}) => {
if (isString(value)) {
value = value.trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const { currentColor = "", format = VAL_COMP, nullable = false } = opt;
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "resolve",
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return cachedResult;
}
return cachedResult.item;
}
if (REG_FN_VAR.test(value)) {
if (format === VAL_SPEC) {
setCache(cacheKey, value);
return value;
}
const resolvedValue = resolveVar(value, opt);
if (resolvedValue instanceof NullObject) {
switch (format) {
case "hex":
case "hexAlpha": {
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
default: {
if (nullable) {
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
const res2 = RGB_TRANSPARENT;
setCache(cacheKey, res2);
return res2;
}
}
} else {
value = resolvedValue;
}
}
if (opt.format !== format) {
opt.format = format;
}
value = value.toLowerCase();
if (REG_FN_REL.test(value)) {
const resolvedValue = resolveRelativeColor(value, opt);
if (format === VAL_COMP) {
let res2;
if (resolvedValue instanceof NullObject) {
if (nullable) {
res2 = resolvedValue;
} else {
res2 = RGB_TRANSPARENT;
}
} else {
res2 = resolvedValue;
}
setCache(cacheKey, res2);
return res2;
}
if (format === VAL_SPEC) {
let res2 = "";
if (resolvedValue instanceof NullObject) {
res2 = "";
} else {
res2 = resolvedValue;
}
setCache(cacheKey, res2);
return res2;
}
if (resolvedValue instanceof NullObject) {
value = "";
} else {
value = resolvedValue;
}
}
if (REG_FN_CALC.test(value)) {
value = cssCalc(value, opt);
}
let cs = "";
let r = NaN;
let g = NaN;
let b = NaN;
let alpha = NaN;
if (value === "transparent") {
switch (format) {
case VAL_SPEC: {
setCache(cacheKey, value);
return value;
}
case "hex": {
setCache(cacheKey, null);
return new NullObject();
}
case "hexAlpha": {
const res2 = "#00000000";
setCache(cacheKey, res2);
return res2;
}
case VAL_COMP:
default: {
const res2 = RGB_TRANSPARENT;
setCache(cacheKey, res2);
return res2;
}
}
} else if (value === "currentcolor") {
if (format === VAL_SPEC) {
setCache(cacheKey, value);
return value;
}
if (currentColor) {
let resolvedValue;
if (currentColor.startsWith(FN_MIX)) {
resolvedValue = resolveColorMix(currentColor, opt);
} else if (currentColor.startsWith(FN_COLOR)) {
resolvedValue = resolveColorFunc(currentColor, opt);
} else {
resolvedValue = resolveColorValue(currentColor, opt);
}
if (resolvedValue instanceof NullObject) {
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
[cs, r, g, b, alpha] = resolvedValue;
} else if (format === VAL_COMP) {
const res2 = RGB_TRANSPARENT;
setCache(cacheKey, res2);
return res2;
}
} else if (format === VAL_SPEC) {
if (value.startsWith(FN_MIX)) {
const res2 = resolveColorMix(value, opt);
setCache(cacheKey, res2);
return res2;
} else if (value.startsWith(FN_COLOR)) {
const [scs, rr, gg, bb, aa] = resolveColorFunc(
value,
opt
);
let res2 = "";
if (aa === 1) {
res2 = `color(${scs} ${rr} ${gg} ${bb})`;
} else {
res2 = `color(${scs} ${rr} ${gg} ${bb} / ${aa})`;
}
setCache(cacheKey, res2);
return res2;
} else {
const rgb = resolveColorValue(value, opt);
if (isString(rgb)) {
setCache(cacheKey, rgb);
return rgb;
}
const [scs, rr, gg, bb, aa] = rgb;
let res2 = "";
if (scs === "rgb") {
if (aa === 1) {
res2 = `${scs}(${rr}, ${gg}, ${bb})`;
} else {
res2 = `${scs}a(${rr}, ${gg}, ${bb}, ${aa})`;
}
} else if (aa === 1) {
res2 = `${scs}(${rr} ${gg} ${bb})`;
} else {
res2 = `${scs}(${rr} ${gg} ${bb} / ${aa})`;
}
setCache(cacheKey, res2);
return res2;
}
} else if (value.startsWith(FN_MIX)) {
if (/currentcolor/.test(value)) {
if (currentColor) {
value = value.replace(/currentcolor/g, currentColor);
}
}
if (/transparent/.test(value)) {
value = value.replace(/transparent/g, RGB_TRANSPARENT);
}
const resolvedValue = resolveColorMix(value, opt);
if (resolvedValue instanceof NullObject) {
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
[cs, r, g, b, alpha] = resolvedValue;
} else if (value.startsWith(FN_COLOR)) {
const resolvedValue = resolveColorFunc(value, opt);
if (resolvedValue instanceof NullObject) {
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
[cs, r, g, b, alpha] = resolvedValue;
} else if (value) {
const resolvedValue = resolveColorValue(value, opt);
if (resolvedValue instanceof NullObject) {
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
[cs, r, g, b, alpha] = resolvedValue;
}
let res = "";
switch (format) {
case "hex": {
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b) || Number.isNaN(alpha) || alpha === 0) {
setCache(cacheKey, null);
return new NullObject();
}
res = convertRgbToHex([r, g, b, 1]);
break;
}
case "hexAlpha": {
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b) || Number.isNaN(alpha)) {
setCache(cacheKey, null);
return new NullObject();
}
res = convertRgbToHex([r, g, b, alpha]);
break;
}
case VAL_COMP:
default: {
switch (cs) {
case "rgb": {
if (alpha === 1) {
res = `${cs}(${r}, ${g}, ${b})`;
} else {
res = `${cs}a(${r}, ${g}, ${b}, ${alpha})`;
}
break;
}
case "lab":
case "lch":
case "oklab":
case "oklch": {
if (alpha === 1) {
res = `${cs}(${r} ${g} ${b})`;
} else {
res = `${cs}(${r} ${g} ${b} / ${alpha})`;
}
break;
}
// color()
default: {
if (alpha === 1) {
res = `color(${cs} ${r} ${g} ${b})`;
} else {
res = `color(${cs} ${r} ${g} ${b} / ${alpha})`;
}
}
}
}
}
setCache(cacheKey, res);
return res;
};
const resolve = (value, opt = {}) => {
opt.nullable = false;
const resolvedValue = resolveColor(value, opt);
if (resolvedValue instanceof NullObject) {
return null;
}
return resolvedValue;
};
export {
resolve,
resolveColor
};
//# sourceMappingURL=resolve.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,78 @@
/**
* typedef
*/
/**
* @typedef Options - options
* @property [alpha] - enable alpha
* @property [colorSpace] - color space
* @property [currentColor] - color for currentcolor
* @property [customPropeerty] - custom properties
* @property [d50] - white point in d50
* @property [dimension] - dimension
* @property [format] - output format
* @property [key] - key
*/
export interface Options {
alpha?: boolean;
colorSpace?: string;
currentColor?: string;
customProperty?: Record<string, string | ((K: string) => string)>;
d50?: boolean;
delimiter?: string | string[];
dimension?: Record<string, number | ((K: string) => number)>;
format?: string;
nullable?: boolean;
}
/**
* @type ColorChannels - color channels
*/
export type ColorChannels = [x: number, y: number, z: number, alpha: number];
/**
* @type StringColorChannels - color channels
*/
export type StringColorChannels = [
x: string,
y: string,
z: string,
alpha: string | undefined
];
/**
* @type StringColorSpacedChannels - specified value
*/
export type StringColorSpacedChannels = [
cs: string,
x: string,
y: string,
z: string,
alpha: string | undefined
];
/**
* @type ComputedColorChannels - computed value
*/
export type ComputedColorChannels = [
cs: string,
x: number,
y: number,
z: number,
alpha: number
];
/**
* @type SpecifiedColorChannels - specified value
*/
export type SpecifiedColorChannels = [
cs: string,
x: number | string,
y: number | string,
z: number | string,
alpha: number | string
];
/**
* @type MatchedRegExp - matched regexp array
*/
export type MatchedRegExp = [
match: string,
gr1: string,
gr2: string,
gr3: string,
gr4: string
];

View File

@@ -0,0 +1,43 @@
import { Options } from './typedef.js';
/**
* split value
* @param value - CSS value
* @param [delimiter] - comma or space
* @returns array of values, NOTE: comments are stripped
*/
export declare const splitValue: (value: string, delimiter?: string) => string[];
/**
* extract dashed-ident tokens
* @param value - CSS value
* @returns array of dashed-ident tokens
*/
export declare const extractDashedIdent: (value: string) => string[];
/**
* is color
* @param value - CSS value
* @param [opt] - options
* @returns result
*/
export declare const isColor: (value: unknown, opt?: Options) => boolean;
/**
* value to JSON string
* @param value - CSS value
* @param [func] - stringify function
* @returns stringified value in JSON notation
*/
export declare const valueToJsonString: (value: unknown, func?: boolean) => string;
/**
* round to specified precision
* @param value - numeric value
* @param bit - minimum bits
* @returns rounded value
*/
export declare const roundToPrecision: (value: number, bit?: number) => number;
/**
* interpolate hue
* @param hueA - hue value
* @param hueB - hue value
* @param arc - shorter | longer | increasing | decreasing
* @returns result - [hueA, hueB]
*/
export declare const interpolateHue: (hueA: number, hueB: number, arc?: string) => [number, number];

252
node_modules/@asamuzakjp/css-color/dist/esm/js/util.js generated vendored Normal file
View File

@@ -0,0 +1,252 @@
import { TokenType, tokenize } from "@csstools/css-tokenizer";
import { createCacheKey, getCache, CacheItem, setCache } from "./cache.js";
import { isString } from "./common.js";
import { resolveColor } from "./resolve.js";
import { NAMED_COLORS } from "./color.js";
import { VAL_SPEC, SYN_COLOR_TYPE, SYN_MIX } from "./constant.js";
const {
CloseParen: PAREN_CLOSE,
Comma: COMMA,
Comment: COMMENT,
EOF,
Function: FUNC,
Ident: IDENT,
OpenParen: PAREN_OPEN,
Whitespace: W_SPACE
} = TokenType;
const NAMESPACE = "util";
const DEC = 10;
const HEX = 16;
const DEG = 360;
const DEG_HALF = 180;
const REG_COLOR = new RegExp(`^(?:${SYN_COLOR_TYPE})$`);
const REG_MIX = new RegExp(SYN_MIX);
const splitValue = (value, delimiter = "") => {
if (isString(value)) {
value = value.trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey(
{
namespace: NAMESPACE,
name: "splitValue",
value
},
{
delimiter
}
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const regDelimiter = delimiter === "," ? /^,$/ : /^\s+$/;
const tokens = tokenize({ css: value });
let nest = 0;
let str = "";
const res = [];
while (tokens.length) {
const [type, value2] = tokens.shift();
switch (type) {
case COMMA: {
if (regDelimiter.test(value2)) {
if (nest === 0) {
res.push(str.trim());
str = "";
} else {
str += value2;
}
} else {
str += value2;
}
break;
}
case COMMENT: {
break;
}
case FUNC:
case PAREN_OPEN: {
str += value2;
nest++;
break;
}
case PAREN_CLOSE: {
str += value2;
nest--;
break;
}
case W_SPACE: {
if (regDelimiter.test(value2)) {
if (nest === 0) {
if (str) {
res.push(str.trim());
str = "";
}
} else {
str += " ";
}
} else if (!str.endsWith(" ")) {
str += " ";
}
break;
}
default: {
if (type === EOF) {
res.push(str.trim());
str = "";
} else {
str += value2;
}
}
}
}
setCache(cacheKey, res);
return res;
};
const extractDashedIdent = (value) => {
if (isString(value)) {
value = value.trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey = createCacheKey({
namespace: NAMESPACE,
name: "extractDashedIdent",
value
});
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item;
}
const tokens = tokenize({ css: value });
const items = /* @__PURE__ */ new Set();
while (tokens.length) {
const [type, value2] = tokens.shift();
if (type === IDENT && value2.startsWith("--")) {
items.add(value2);
}
}
const res = [...items];
setCache(cacheKey, res);
return res;
};
const isColor = (value, opt = {}) => {
if (isString(value)) {
value = value.toLowerCase().trim();
if (value && isString(value)) {
if (/^[a-z]+$/.test(value)) {
if (/^(?:currentcolor|transparent)$/.test(value) || Object.prototype.hasOwnProperty.call(NAMED_COLORS, value)) {
return true;
}
} else if (REG_COLOR.test(value) || REG_MIX.test(value)) {
return true;
} else {
opt.nullable = true;
if (!opt.format) {
opt.format = VAL_SPEC;
}
const resolvedValue = resolveColor(value, opt);
if (resolvedValue) {
return true;
}
}
}
}
return false;
};
const valueToJsonString = (value, func = false) => {
if (typeof value === "undefined") {
return "";
}
const res = JSON.stringify(value, (_key, val) => {
let replacedValue;
if (typeof val === "undefined") {
replacedValue = null;
} else if (typeof val === "function") {
if (func) {
replacedValue = val.toString().replace(/\s/g, "").substring(0, HEX);
} else {
replacedValue = val.name;
}
} else if (val instanceof Map || val instanceof Set) {
replacedValue = [...val];
} else if (typeof val === "bigint") {
replacedValue = val.toString();
} else {
replacedValue = val;
}
return replacedValue;
});
return res;
};
const roundToPrecision = (value, bit = 0) => {
if (!Number.isFinite(value)) {
throw new TypeError(`${value} is not a finite number.`);
}
if (!Number.isFinite(bit)) {
throw new TypeError(`${bit} is not a finite number.`);
} else if (bit < 0 || bit > HEX) {
throw new RangeError(`${bit} is not between 0 and ${HEX}.`);
}
if (bit === 0) {
return Math.round(value);
}
let val;
if (bit === HEX) {
val = value.toPrecision(6);
} else if (bit < DEC) {
val = value.toPrecision(4);
} else {
val = value.toPrecision(5);
}
return parseFloat(val);
};
const interpolateHue = (hueA, hueB, arc = "shorter") => {
if (!Number.isFinite(hueA)) {
throw new TypeError(`${hueA} is not a finite number.`);
}
if (!Number.isFinite(hueB)) {
throw new TypeError(`${hueB} is not a finite number.`);
}
switch (arc) {
case "decreasing": {
if (hueB > hueA) {
hueA += DEG;
}
break;
}
case "increasing": {
if (hueB < hueA) {
hueB += DEG;
}
break;
}
case "longer": {
if (hueB > hueA && hueB < hueA + DEG_HALF) {
hueA += DEG;
} else if (hueB > hueA + DEG_HALF * -1 && hueB <= hueA) {
hueB += DEG;
}
break;
}
case "shorter":
default: {
if (hueB > hueA + DEG_HALF) {
hueA += DEG;
} else if (hueB < hueA + DEG_HALF * -1) {
hueB += DEG;
}
}
}
return [hueA, hueB];
};
export {
extractDashedIdent,
interpolateHue,
isColor,
roundToPrecision,
splitValue,
valueToJsonString
};
//# sourceMappingURL=util.js.map

File diff suppressed because one or more lines are too long

76
node_modules/@asamuzakjp/css-color/package.json generated vendored Normal file
View File

@@ -0,0 +1,76 @@
{
"name": "@asamuzakjp/css-color",
"description": "CSS color - Resolve and convert CSS colors.",
"author": "asamuzaK",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/asamuzaK/cssColor.git"
},
"homepage": "https://github.com/asamuzaK/cssColor#readme",
"bugs": {
"url": "https://github.com/asamuzaK/cssColor/issues"
},
"files": [
"dist",
"src"
],
"type": "module",
"types": "dist/esm/index.d.ts",
"module": "dist/esm/index.js",
"main": "dist/cjs/index.cjs",
"exports": {
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/cjs/index.d.cts",
"default": "./dist/cjs/index.cjs"
}
},
"./package.json": "./package.json"
},
"packageManager": "pnpm@10.6.1",
"dependencies": {
"@csstools/css-calc": "^2.1.2",
"@csstools/css-color-parser": "^3.0.8",
"@csstools/css-parser-algorithms": "^3.0.4",
"@csstools/css-tokenizer": "^3.0.3",
"lru-cache": "^10.4.3"
},
"devDependencies": {
"@tanstack/vite-config": "^0.1.0",
"@vitest/coverage-istanbul": "^3.0.8",
"esbuild": "^0.25.0",
"eslint": "^9.22.0",
"eslint-plugin-import-x": "^4.6.1",
"eslint-plugin-regexp": "^2.7.0",
"globals": "^16.0.0",
"knip": "^5.45.0",
"neostandard": "^0.12.1",
"prettier": "^3.5.3",
"publint": "^0.3.8",
"rimraf": "^6.0.1",
"tsup": "^8.4.0",
"typescript": "^5.8.2",
"vite": "^6.2.1",
"vitest": "^3.0.8"
},
"scripts": {
"build": "pnpm run clean && pnpm run test && pnpm run knip && pnpm run build:prod && pnpm run build:cjs && pnpm run build:browser && pnpm run publint",
"build:browser": "vite build -c ./vite.browser.config.ts",
"build:prod": "vite build",
"build:cjs": "tsup ./src/index.ts --format=cjs --platform=node --outDir=./dist/cjs/ --sourcemap --dts",
"clean": "rimraf ./coverage ./dist",
"knip": "knip",
"prettier": "prettier . --ignore-unknown --write",
"publint": "publint --strict",
"test": "pnpm run prettier && pnpm run --stream \"/^test:.*/\"",
"test:eslint": "eslint ./src ./test --fix",
"test:types": "tsc",
"test:unit": "vitest"
},
"version": "3.1.1"
}

27
node_modules/@asamuzakjp/css-color/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,27 @@
/*!
* CSS color - Resolve, parse, convert CSS color.
* @license MIT
* @copyright asamuzaK (Kazz)
* @see {@link https://github.com/asamuzaK/cssColor/blob/main/LICENSE}
*/
import { cssCalc as csscalc } from './js/css-calc';
import { isGradient } from './js/css-gradient';
import { cssVar } from './js/css-var';
import { extractDashedIdent, isColor as iscolor, splitValue } from './js/util';
export { convert } from './js/convert';
export { resolve } from './js/resolve';
/* utils */
export const utils = {
cssCalc: csscalc,
cssVar,
extractDashedIdent,
isColor: iscolor,
isGradient,
splitValue
};
/* TODO: remove later */
/* alias */
export const isColor = utils.isColor;
export const cssCalc = utils.cssCalc;

114
node_modules/@asamuzakjp/css-color/src/js/cache.ts generated vendored Normal file
View File

@@ -0,0 +1,114 @@
/**
* cache
*/
import { LRUCache } from 'lru-cache';
import { Options } from './typedef';
import { valueToJsonString } from './util';
/* numeric constants */
const MAX_CACHE = 4096;
/**
* CacheItem
*/
export class CacheItem {
/* private */
#isNull: boolean;
#item: unknown;
/**
* constructor
*/
constructor(item: unknown, isNull: boolean = false) {
this.#item = item;
this.#isNull = !!isNull;
}
get item() {
return this.#item;
}
get isNull() {
return this.#isNull;
}
}
/**
* NullObject
*/
export class NullObject extends CacheItem {
/**
* constructor
*/
constructor() {
super(Symbol('null'), true);
}
}
/*
* lru cache
*/
export const lruCache = new LRUCache({
max: MAX_CACHE
});
/**
* set cache
* @param key - cache key
* @param value - value to cache
* @returns void
*/
export const setCache = (key: string, value: unknown): void => {
if (key) {
if (value === null) {
lruCache.set(key, new NullObject());
} else if (value instanceof CacheItem) {
lruCache.set(key, value);
} else {
lruCache.set(key, new CacheItem(value));
}
}
};
/**
* get cache
* @param key - cache key
* @returns cached item or false otherwise
*/
export const getCache = (key: string): CacheItem | boolean => {
if (key && lruCache.has(key)) {
const item = lruCache.get(key);
if (item instanceof CacheItem) {
return item;
}
// delete unexpected cached item
lruCache.delete(key);
return false;
}
return false;
};
/**
* create cache key
* @param keyData - key data
* @param [opt] - options
* @returns cache key
*/
export const createCacheKey = (
keyData: Record<string, string>,
opt: Options = {}
): string => {
const { customProperty = {}, dimension = {} } = opt;
let cacheKey = '';
if (
keyData &&
Object.keys(keyData).length &&
typeof customProperty.callback !== 'function' &&
typeof dimension.callback !== 'function'
) {
keyData.opt = valueToJsonString(opt);
cacheKey = valueToJsonString(keyData);
}
return cacheKey;
};

3459
node_modules/@asamuzakjp/css-color/src/js/color.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

31
node_modules/@asamuzakjp/css-color/src/js/common.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
/**
* common
*/
/* numeric constants */
const TYPE_FROM = 8;
const TYPE_TO = -1;
/**
* get type
* @param o - object to check
* @returns type of object
*/
export const getType = (o: unknown): string =>
Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);
/**
* is string
* @param o - object to check
* @returns result
*/
export const isString = (o: unknown): o is string =>
typeof o === 'string' || o instanceof String;
/**
* is string or number
* @param o - object to check
* @returns result
*/
export const isStringOrNumber = (o: unknown): boolean =>
isString(o) || typeof o === 'number';

66
node_modules/@asamuzakjp/css-color/src/js/constant.ts generated vendored Normal file
View File

@@ -0,0 +1,66 @@
/**
* constant
*/
/* values and units */
const _DIGIT = '(?:0|[1-9]\\d*)';
const _COMPARE = 'clamp|max|min';
const _EXPO = 'exp|hypot|log|pow|sqrt';
const _SIGN = 'abs|sign';
const _STEP = 'mod|rem|round';
const _TRIG = 'a?(?:cos|sin|tan)|atan2';
const _MATH = `${_COMPARE}|${_EXPO}|${_SIGN}|${_STEP}|${_TRIG}`;
const _CALC = `calc|${_MATH}`;
const _VAR = `var|${_CALC}`;
export const ANGLE = 'deg|g?rad|turn';
export const LENGTH =
'[cm]m|[dls]?v(?:[bhiw]|max|min)|in|p[ctx]|q|r?(?:[cl]h|cap|e[mx]|ic)';
export const NUM = `[+-]?(?:${_DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${_DIGIT})?`;
export const NUM_POSITIVE = `\\+?(?:${_DIGIT}(?:\\.\\d*)?|\\.\\d+)(?:e-?${_DIGIT})?`;
export const NONE = 'none';
export const PCT = `${NUM}%`;
export const SYN_FN_CALC = `^(?:${_CALC})\\(|(?<=[*\\/\\s\\(])(?:${_CALC})\\(`;
export const SYN_FN_MATH_START = `^(?:${_MATH})\\($`;
export const SYN_FN_VAR = '^var\\(|(?<=[*\\/\\s\\(])var\\(';
export const SYN_FN_VAR_START = `^(?:${_VAR})\\(`;
/* colors */
const _ALPHA = `(?:\\s*\\/\\s*(?:${NUM}|${PCT}|${NONE}))?`;
const _ALPHA_LV3 = `(?:\\s*,\\s*(?:${NUM}|${PCT}))?`;
const _COLOR_FUNC = '(?:ok)?l(?:ab|ch)|color|hsla?|hwb|rgba?';
const _COLOR_KEY = '[a-z]+|#[\\da-f]{3}|#[\\da-f]{4}|#[\\da-f]{6}|#[\\da-f]{8}';
const _CS_HUE = '(?:ok)?lch|hsl|hwb';
const _CS_HUE_ARC = '(?:de|in)creasing|longer|shorter';
const _NUM_ANGLE = `${NUM}(?:${ANGLE})?`;
const _NUM_ANGLE_NONE = `(?:${NUM}(?:${ANGLE})?|${NONE})`;
const _NUM_PCT_NONE = `(?:${NUM}|${PCT}|${NONE})`;
export const CS_HUE = `(?:${_CS_HUE})(?:\\s(?:${_CS_HUE_ARC})\\shue)?`;
export const CS_HUE_CAPT = `(${_CS_HUE})(?:\\s(${_CS_HUE_ARC})\\shue)?`;
export const CS_LAB = '(?:ok)?lab';
export const CS_LCH = '(?:ok)?lch';
export const CS_SRGB = 'srgb(?:-linear)?';
export const CS_RGB = `(?:a98|prophoto)-rgb|display-p3|rec2020|${CS_SRGB}`;
export const CS_XYZ = 'xyz(?:-d(?:50|65))?';
export const CS_RECT = `${CS_LAB}|${CS_RGB}|${CS_XYZ}`;
export const CS_MIX = `${CS_HUE}|${CS_RECT}`;
export const FN_COLOR = 'color(';
export const FN_MIX = 'color-mix(';
export const FN_REL = `(?:${_COLOR_FUNC})\\(\\s*from\\s+`;
export const FN_REL_CAPT = `(${_COLOR_FUNC})\\(\\s*from\\s+`;
export const FN_VAR = 'var(';
export const SYN_FN_COLOR = `(?:${CS_RGB}|${CS_XYZ})(?:\\s+${_NUM_PCT_NONE}){3}${_ALPHA}`;
export const SYN_FN_REL = `^${FN_REL}|(?<=[\\s])${FN_REL}`;
export const SYN_HSL = `${_NUM_ANGLE_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
export const SYN_HSL_LV3 = `${_NUM_ANGLE}(?:\\s*,\\s*${PCT}){2}${_ALPHA_LV3}`;
export const SYN_LCH = `(?:${_NUM_PCT_NONE}\\s+){2}${_NUM_ANGLE_NONE}${_ALPHA}`;
export const SYN_MOD = `${_NUM_PCT_NONE}(?:\\s+${_NUM_PCT_NONE}){2}${_ALPHA}`;
export const SYN_RGB_LV3 = `(?:${NUM}(?:\\s*,\\s*${NUM}){2}|${PCT}(?:\\s*,\\s*${PCT}){2})${_ALPHA_LV3}`;
export const SYN_COLOR_TYPE = `${_COLOR_KEY}|hsla?\\(\\s*${SYN_HSL_LV3}\\s*\\)|rgba?\\(\\s*${SYN_RGB_LV3}\\s*\\)|(?:hsla?|hwb)\\(\\s*${SYN_HSL}\\s*\\)|(?:(?:ok)?lab|rgba?)\\(\\s*${SYN_MOD}\\s*\\)|(?:ok)?lch\\(\\s*${SYN_LCH}\\s*\\)|color\\(\\s*${SYN_FN_COLOR}\\s*\\)`;
export const SYN_MIX_PART = `(?:${SYN_COLOR_TYPE})(?:\\s+${PCT})?`;
export const SYN_MIX = `color-mix\\(\\s*in\\s+(?:${CS_MIX})\\s*,\\s*${SYN_MIX_PART}\\s*,\\s*${SYN_MIX_PART}\\s*\\)`;
export const SYN_MIX_CAPT = `color-mix\\(\\s*in\\s+(${CS_MIX})\\s*,\\s*(${SYN_MIX_PART})\\s*,\\s*(${SYN_MIX_PART})\\s*\\)`;
/* formats */
export const VAL_COMP = 'computedValue';
export const VAL_MIX = 'mixValue';
export const VAL_SPEC = 'specifiedValue';

469
node_modules/@asamuzakjp/css-color/src/js/convert.ts generated vendored Normal file
View File

@@ -0,0 +1,469 @@
/**
* convert
*/
import {
CacheItem,
NullObject,
createCacheKey,
getCache,
setCache
} from './cache';
import {
convertColorToHsl,
convertColorToHwb,
convertColorToLab,
convertColorToLch,
convertColorToOklab,
convertColorToOklch,
convertColorToRgb,
numberToHexString,
parseColorFunc,
parseColorValue
} from './color';
import { isString } from './common';
import { cssCalc } from './css-calc';
import { resolveVar } from './css-var';
import { resolveRelativeColor } from './relative-color';
import { resolveColor } from './resolve';
import { ColorChannels, ComputedColorChannels, Options } from './typedef';
/* constants */
import { SYN_FN_CALC, SYN_FN_REL, SYN_FN_VAR, VAL_COMP } from './constant';
const NAMESPACE = 'convert';
/* regexp */
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
const REG_FN_REL = new RegExp(SYN_FN_REL);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
/**
* pre process
* @param value - CSS color value
* @param [opt] - options
* @returns value
*/
export const preProcess = (
value: string,
opt: Options = {}
): string | NullObject => {
if (isString(value)) {
value = value.trim();
if (!value) {
return new NullObject();
}
} else {
return new NullObject();
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'preProcess',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return cachedResult as NullObject;
}
return cachedResult.item as string;
}
if (REG_FN_VAR.test(value)) {
const resolvedValue = resolveVar(value, opt);
if (isString(resolvedValue)) {
value = resolvedValue;
} else {
setCache(cacheKey, null);
return new NullObject();
}
}
if (REG_FN_REL.test(value)) {
const resolvedValue = resolveRelativeColor(value, opt);
if (isString(resolvedValue)) {
value = resolvedValue;
} else {
setCache(cacheKey, null);
return new NullObject();
}
} else if (REG_FN_CALC.test(value)) {
value = cssCalc(value, opt);
}
if (value.startsWith('color-mix')) {
const clonedOpt = structuredClone(opt);
clonedOpt.format = VAL_COMP;
clonedOpt.nullable = true;
const resolvedValue = resolveColor(value, clonedOpt);
setCache(cacheKey, resolvedValue);
return resolvedValue;
}
setCache(cacheKey, value);
return value;
};
/**
* convert number to hex string
* @param value - numeric value
* @returns hex string: 00..ff
*/
export const numberToHex = (value: number): string => {
const hex = numberToHexString(value);
return hex;
};
/**
* convert color to hex
* @param value - CSS color value
* @param [opt] - options
* @param [opt.alpha] - enable alpha channel
* @returns #rrggbb | #rrggbbaa | null
*/
export const colorToHex = (value: string, opt: Options = {}): string | null => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return null;
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const { alpha = false } = opt;
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToHex',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return null;
}
return cachedResult.item as string;
}
let hex;
opt.nullable = true;
if (alpha) {
opt.format = 'hexAlpha';
hex = resolveColor(value, opt);
} else {
opt.format = 'hex';
hex = resolveColor(value, opt);
}
if (isString(hex)) {
setCache(cacheKey, hex);
return hex;
}
setCache(cacheKey, null);
return null;
};
/**
* convert color to hsl
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [h, s, l, alpha]
*/
export const colorToHsl = (value: string, opt: Options = {}): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToHsl',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
opt.format = 'hsl';
const hsl = convertColorToHsl(value, opt) as ColorChannels;
setCache(cacheKey, hsl);
return hsl;
};
/**
* convert color to hwb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [h, w, b, alpha]
*/
export const colorToHwb = (value: string, opt: Options = {}): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToHwb',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
opt.format = 'hwb';
const hwb = convertColorToHwb(value, opt) as ColorChannels;
setCache(cacheKey, hwb);
return hwb;
};
/**
* convert color to lab
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, a, b, alpha]
*/
export const colorToLab = (value: string, opt: Options = {}): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToLab',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
const lab = convertColorToLab(value, opt) as ColorChannels;
setCache(cacheKey, lab);
return lab;
};
/**
* convert color to lch
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, c, h, alpha]
*/
export const colorToLch = (value: string, opt: Options = {}): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToLch',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
const lch = convertColorToLch(value, opt) as ColorChannels;
setCache(cacheKey, lch);
return lch;
};
/**
* convert color to oklab
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, a, b, alpha]
*/
export const colorToOklab = (
value: string,
opt: Options = {}
): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToOklab',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
const lab = convertColorToOklab(value, opt) as ColorChannels;
setCache(cacheKey, lab);
return lab;
};
/**
* convert color to oklch
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [l, c, h, alpha]
*/
export const colorToOklch = (
value: string,
opt: Options = {}
): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToOklch',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
const lch = convertColorToOklch(value, opt) as ColorChannels;
setCache(cacheKey, lch);
return lch;
};
/**
* convert color to rgb
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [r, g, b, alpha]
*/
export const colorToRgb = (value: string, opt: Options = {}): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToRgb',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
const rgb = convertColorToRgb(value, opt) as ColorChannels;
setCache(cacheKey, rgb);
return rgb;
};
/**
* convert color to xyz
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [x, y, z, alpha]
*/
export const colorToXyz = (value: string, opt: Options = {}): ColorChannels => {
if (isString(value)) {
const resolvedValue = preProcess(value, opt);
if (resolvedValue instanceof NullObject) {
return [0, 0, 0, 0];
}
value = resolvedValue.toLowerCase();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'colorToXyz',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as ColorChannels;
}
let xyz;
if (value.startsWith('color(')) {
[, ...xyz] = parseColorFunc(value, opt) as ComputedColorChannels;
} else {
[, ...xyz] = parseColorValue(value, opt) as ComputedColorChannels;
}
setCache(cacheKey, xyz);
return xyz as ColorChannels;
};
/**
* convert color to xyz-d50
* @param value - CSS color value
* @param [opt] - options
* @returns ColorChannels - [x, y, z, alpha]
*/
export const colorToXyzD50 = (
value: string,
opt: Options = {}
): ColorChannels => {
opt.d50 = true;
return colorToXyz(value, opt);
};
/* convert */
export const convert = {
colorToHex,
colorToHsl,
colorToHwb,
colorToLab,
colorToLch,
colorToOklab,
colorToOklch,
colorToRgb,
colorToXyz,
colorToXyzD50,
numberToHex
};

948
node_modules/@asamuzakjp/css-color/src/js/css-calc.ts generated vendored Normal file
View File

@@ -0,0 +1,948 @@
/**
* css-calc
*/
import { calc } from '@csstools/css-calc';
import { CSSToken, TokenType, tokenize } from '@csstools/css-tokenizer';
import {
CacheItem,
NullObject,
createCacheKey,
getCache,
setCache
} from './cache';
import { isString, isStringOrNumber } from './common';
import { resolveVar } from './css-var';
import { roundToPrecision } from './util';
import { MatchedRegExp, Options } from './typedef';
/* constants */
import {
ANGLE,
LENGTH,
NUM,
SYN_FN_CALC,
SYN_FN_MATH_START,
SYN_FN_VAR,
SYN_FN_VAR_START,
VAL_SPEC
} from './constant';
const {
CloseParen: PAREN_CLOSE,
Comment: COMMENT,
Dimension: DIM,
EOF,
Function: FUNC,
OpenParen: PAREN_OPEN,
Whitespace: W_SPACE
} = TokenType;
const NAMESPACE = 'css-calc';
/* numeric constants */
const TRIA = 3;
const HEX = 16;
const MAX_PCT = 100;
/* regexp */
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
const REG_FN_MATH_START = new RegExp(SYN_FN_MATH_START);
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
const REG_FN_VAR_START = new RegExp(SYN_FN_VAR_START);
const REG_OPERATOR = /\s[*+/-]\s/;
const REG_TYPE_DIM = new RegExp(`^(${NUM})(${ANGLE}|${LENGTH})$`);
const REG_TYPE_DIM_PCT = new RegExp(`^(${NUM})(${ANGLE}|${LENGTH}|%)$`);
const REG_TYPE_PCT = new RegExp(`^(${NUM})%$`);
/**
* Calclator
*/
export class Calculator {
/* private */
// number
#hasNum: boolean;
#numSum: number[];
#numMul: number[];
// percentage
#hasPct: boolean;
#pctSum: number[];
#pctMul: number[];
// dimension
#hasDim: boolean;
#dimSum: string[];
#dimSub: string[];
#dimMul: string[];
#dimDiv: string[];
// et cetra
#hasEtc: boolean;
#etcSum: string[];
#etcSub: string[];
#etcMul: string[];
#etcDiv: string[];
/**
* constructor
*/
constructor() {
// number
this.#hasNum = false;
this.#numSum = [];
this.#numMul = [];
// percentage
this.#hasPct = false;
this.#pctSum = [];
this.#pctMul = [];
// dimension
this.#hasDim = false;
this.#dimSum = [];
this.#dimSub = [];
this.#dimMul = [];
this.#dimDiv = [];
// et cetra
this.#hasEtc = false;
this.#etcSum = [];
this.#etcSub = [];
this.#etcMul = [];
this.#etcDiv = [];
}
get hasNum() {
return this.#hasNum;
}
set hasNum(value: boolean) {
this.#hasNum = !!value;
}
get numSum() {
return this.#numSum;
}
get numMul() {
return this.#numMul;
}
get hasPct() {
return this.#hasPct;
}
set hasPct(value: boolean) {
this.#hasPct = !!value;
}
get pctSum() {
return this.#pctSum;
}
get pctMul() {
return this.#pctMul;
}
get hasDim() {
return this.#hasDim;
}
set hasDim(value: boolean) {
this.#hasDim = !!value;
}
get dimSum() {
return this.#dimSum;
}
get dimSub() {
return this.#dimSub;
}
get dimMul() {
return this.#dimMul;
}
get dimDiv() {
return this.#dimDiv;
}
get hasEtc() {
return this.#hasEtc;
}
set hasEtc(value: boolean) {
this.#hasEtc = !!value;
}
get etcSum() {
return this.#etcSum;
}
get etcSub() {
return this.#etcSub;
}
get etcMul() {
return this.#etcMul;
}
get etcDiv() {
return this.#etcDiv;
}
/**
* clear values
* @returns void
*/
clear() {
// number
this.#hasNum = false;
this.#numSum = [];
this.#numMul = [];
// percentage
this.#hasPct = false;
this.#pctSum = [];
this.#pctMul = [];
// dimension
this.#hasDim = false;
this.#dimSum = [];
this.#dimSub = [];
this.#dimMul = [];
this.#dimDiv = [];
// et cetra
this.#hasEtc = false;
this.#etcSum = [];
this.#etcSub = [];
this.#etcMul = [];
this.#etcDiv = [];
}
/**
* sort values
* @param values - values
* @returns sorted values
*/
sort(values: string[] = []): string[] {
const arr = [...values];
if (arr.length > 1) {
arr.sort((a, b) => {
let res;
if (REG_TYPE_DIM_PCT.test(a) && REG_TYPE_DIM_PCT.test(b)) {
const [, valA, unitA] = a.match(REG_TYPE_DIM_PCT) as MatchedRegExp;
const [, valB, unitB] = b.match(REG_TYPE_DIM_PCT) as MatchedRegExp;
if (unitA === unitB) {
if (Number(valA) === Number(valB)) {
res = 0;
} else if (Number(valA) > Number(valB)) {
res = 1;
} else {
res = -1;
}
} else if (unitA > unitB) {
res = 1;
} else {
res = -1;
}
} else {
if (a === b) {
res = 0;
} else if (a > b) {
res = 1;
} else {
res = -1;
}
}
return res;
});
}
return arr;
}
/**
* multiply values
* @returns resolved value
*/
multiply(): string {
const value = [];
let num;
if (this.#hasNum) {
num = 1;
for (const i of this.#numMul) {
num *= i;
if (num === 0 || !Number.isFinite(num) || Number.isNaN(num)) {
break;
}
}
if (!this.#hasPct && !this.#hasDim && !this.hasEtc) {
if (Number.isFinite(num)) {
num = roundToPrecision(num, HEX);
}
value.push(num);
}
}
if (this.#hasPct) {
if (typeof num !== 'number') {
num = 1;
}
for (const i of this.#pctMul) {
num *= i;
if (num === 0 || !Number.isFinite(num) || Number.isNaN(num)) {
break;
}
}
if (Number.isFinite(num)) {
num = `${roundToPrecision(num, HEX)}%`;
}
if (!this.#hasDim && !this.hasEtc) {
value.push(num);
}
}
if (this.#hasDim) {
let dim = '';
let mul = '';
let div = '';
if (this.#dimMul.length) {
if (this.#dimMul.length === 1) {
[mul] = this.#dimMul as [string];
} else {
mul = `${this.sort(this.#dimMul).join(' * ')}`;
}
}
if (this.#dimDiv.length) {
if (this.#dimDiv.length === 1) {
[div] = this.#dimDiv as [string];
} else {
div = `${this.sort(this.#dimDiv).join(' * ')}`;
}
}
if (Number.isFinite(num)) {
if (mul) {
if (div) {
if (div.includes('*')) {
dim = calc(`calc(${num} * ${mul} / (${div}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${num} * ${mul} / ${div})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(${num} * ${mul})`, {
toCanonicalUnits: true
});
}
} else if (div.includes('*')) {
dim = calc(`calc(${num} / (${div}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${num} / ${div})`, {
toCanonicalUnits: true
});
}
value.push(dim.replace(/^calc/, ''));
} else {
if (!value.length && num !== undefined) {
value.push(num);
}
if (mul) {
if (div) {
if (div.includes('*')) {
dim = calc(`calc(${mul} / (${div}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${mul} / ${div})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(${mul})`, {
toCanonicalUnits: true
});
}
if (value.length) {
value.push('*', dim.replace(/^calc/, ''));
} else {
value.push(dim.replace(/^calc/, ''));
}
} else {
dim = calc(`calc(${div})`, {
toCanonicalUnits: true
});
if (value.length) {
value.push('/', dim.replace(/^calc/, ''));
} else {
value.push('1', '/', dim.replace(/^calc/, ''));
}
}
}
}
if (this.#hasEtc) {
if (this.#etcMul.length) {
if (!value.length && num !== undefined) {
value.push(num);
}
const mul = this.sort(this.#etcMul).join(' * ');
if (value.length) {
value.push(`* ${mul}`);
} else {
value.push(`${mul}`);
}
}
if (this.#etcDiv.length) {
const div = this.sort(this.#etcDiv).join(' * ');
if (div.includes('*')) {
if (value.length) {
value.push(`/ (${div})`);
} else {
value.push(`1 / (${div})`);
}
} else if (value.length) {
value.push(`/ ${div}`);
} else {
value.push(`1 / ${div}`);
}
}
}
if (value.length) {
return value.join(' ');
}
return '';
}
/**
* sum values
* @returns resolved value
*/
sum(): string {
const value = [];
if (this.#hasNum) {
let num = 0;
for (const i of this.#numSum) {
num += i;
if (!Number.isFinite(num) || Number.isNaN(num)) {
break;
}
}
value.push(num);
}
if (this.#hasPct) {
let num: number | string = 0;
for (const i of this.#pctSum) {
num += i;
if (!Number.isFinite(num)) {
break;
}
}
if (Number.isFinite(num)) {
num = `${num}%`;
}
if (value.length) {
value.push(`+ ${num}`);
} else {
value.push(num);
}
}
if (this.#hasDim) {
let dim, sum, sub;
if (this.#dimSum.length) {
sum = this.#dimSum.join(' + ');
}
if (this.#dimSub.length) {
sub = this.#dimSub.join(' + ');
}
if (sum) {
if (sub) {
if (sub.includes('-')) {
dim = calc(`calc(${sum} - (${sub}))`, {
toCanonicalUnits: true
});
} else {
dim = calc(`calc(${sum} - ${sub})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(${sum})`, {
toCanonicalUnits: true
});
}
} else {
dim = calc(`calc(-1 * (${sub}))`, {
toCanonicalUnits: true
});
}
if (value.length) {
value.push('+', dim.replace(/^calc/, ''));
} else {
value.push(dim.replace(/^calc/, ''));
}
}
if (this.#hasEtc) {
if (this.#etcSum.length) {
const sum = this.sort(this.#etcSum)
.map(item => {
let res;
if (
REG_OPERATOR.test(item) &&
!item.startsWith('(') &&
!item.endsWith(')')
) {
res = `(${item})`;
} else {
res = item;
}
return res;
})
.join(' + ');
if (value.length) {
if (this.#etcSum.length > 1) {
value.push(`+ (${sum})`);
} else {
value.push(`+ ${sum}`);
}
} else {
value.push(`${sum}`);
}
}
if (this.#etcSub.length) {
const sub = this.sort(this.#etcSub)
.map(item => {
let res;
if (
REG_OPERATOR.test(item) &&
!item.startsWith('(') &&
!item.endsWith(')')
) {
res = `(${item})`;
} else {
res = item;
}
return res;
})
.join(' + ');
if (value.length) {
if (this.#etcSub.length > 1) {
value.push(`- (${sub})`);
} else {
value.push(`- ${sub}`);
}
} else if (this.#etcSub.length > 1) {
value.push(`-1 * (${sub})`);
} else {
value.push(`-1 * ${sub}`);
}
}
}
if (value.length) {
return value.join(' ');
}
return '';
}
}
/**
* sort calc values
* @param values - values to sort
* @param [finalize] - finalize values
* @returns sorted values
*/
export const sortCalcValues = (
values: (number | string)[] = [],
finalize: boolean = false
): string => {
if (values.length < TRIA) {
throw new Error(`Unexpected array length ${values.length}.`);
}
const start = values.shift();
if (!isString(start) || !start.endsWith('(')) {
throw new Error(`Unexpected token ${start}.`);
}
const end = values.pop();
if (end !== ')') {
throw new Error(`Unexpected token ${end}.`);
}
if (values.length === 1) {
const [value] = values;
if (!isStringOrNumber(value)) {
throw new Error(`Unexpected token ${value}.`);
}
return `${start}${value}${end}`;
}
const sortedValues = [];
const cal = new Calculator();
let operator: string = '';
const l = values.length;
for (let i = 0; i < l; i++) {
const value = values[i];
if (!isStringOrNumber(value)) {
throw new Error(`Unexpected token ${value}.`);
}
if (value === '*' || value === '/') {
operator = value;
} else if (value === '+' || value === '-') {
const sortedValue = cal.multiply();
if (sortedValue) {
sortedValues.push(sortedValue, value);
}
cal.clear();
operator = '';
} else {
const numValue = Number(value);
const strValue = `${value}`;
switch (operator) {
case '/': {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numMul.push(1 / numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT) as MatchedRegExp;
cal.hasPct = true;
cal.pctMul.push((MAX_PCT * MAX_PCT) / Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimDiv.push(strValue);
} else {
cal.hasEtc = true;
cal.etcDiv.push(strValue);
}
break;
}
case '*':
default: {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numMul.push(numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT) as MatchedRegExp;
cal.hasPct = true;
cal.pctMul.push(Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimMul.push(strValue);
} else {
cal.hasEtc = true;
cal.etcMul.push(strValue);
}
}
}
}
if (i === l - 1) {
const sortedValue = cal.multiply();
if (sortedValue) {
sortedValues.push(sortedValue);
}
cal.clear();
operator = '';
}
}
let resolvedValue = '';
if (finalize && (sortedValues.includes('+') || sortedValues.includes('-'))) {
const finalizedValues = [];
cal.clear();
operator = '';
const l = sortedValues.length;
for (let i = 0; i < l; i++) {
const value = sortedValues[i];
if (isStringOrNumber(value)) {
if (value === '+' || value === '-') {
operator = value;
} else {
const numValue = Number(value);
const strValue = `${value}`;
switch (operator) {
case '-': {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numSum.push(-1 * numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT) as MatchedRegExp;
cal.hasPct = true;
cal.pctSum.push(-1 * Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimSub.push(strValue);
} else {
cal.hasEtc = true;
cal.etcSub.push(strValue);
}
break;
}
case '+':
default: {
if (Number.isFinite(numValue)) {
cal.hasNum = true;
cal.numSum.push(numValue);
} else if (REG_TYPE_PCT.test(strValue)) {
const [, val] = strValue.match(REG_TYPE_PCT) as MatchedRegExp;
cal.hasPct = true;
cal.pctSum.push(Number(val));
} else if (REG_TYPE_DIM.test(strValue)) {
cal.hasDim = true;
cal.dimSum.push(strValue);
} else {
cal.hasEtc = true;
cal.etcSum.push(strValue);
}
}
}
}
}
if (i === l - 1) {
const sortedValue = cal.sum();
if (sortedValue) {
finalizedValues.push(sortedValue);
}
cal.clear();
operator = '';
}
}
resolvedValue = finalizedValues.join(' ');
} else {
resolvedValue = sortedValues.join(' ');
}
return `${start}${resolvedValue}${end}`;
};
/**
* serialize calc
* @param value - CSS value
* @param [opt] - options
* @returns serialized value
*/
export const serializeCalc = (value: string, opt: Options = {}): string => {
const { format = '' } = opt;
if (isString(value)) {
if (!REG_FN_VAR_START.test(value) || format !== VAL_SPEC) {
return value;
}
value = value.toLowerCase().trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'serializeCalc',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as string;
}
const items: string[] = tokenize({ css: value })
.map((token: CSSToken): string => {
const [type, value] = token as [TokenType, string];
let res = '';
if (type !== W_SPACE && type !== COMMENT) {
res = value;
}
return res;
})
.filter(v => v);
let startIndex = items.findLastIndex((item: string) => /\($/.test(item));
while (startIndex) {
const endIndex = items.findIndex((item: unknown, index: number) => {
return item === ')' && index > startIndex;
});
const slicedValues: string[] = items.slice(startIndex, endIndex + 1);
let serializedValue: string = sortCalcValues(slicedValues);
if (REG_FN_VAR_START.test(serializedValue)) {
serializedValue = calc(serializedValue, {
toCanonicalUnits: true
});
}
items.splice(startIndex, endIndex - startIndex + 1, serializedValue);
startIndex = items.findLastIndex((item: string) => /\($/.test(item));
}
const serializedCalc = sortCalcValues(items, true);
setCache(cacheKey, serializedCalc);
return serializedCalc;
};
/**
* resolve dimension
* @param token - CSS token
* @param [opt] - options
* @returns resolved value
*/
export const resolveDimension = (
token: CSSToken,
opt: Options = {}
): string | NullObject => {
if (!Array.isArray(token)) {
throw new TypeError(`${token} is not an array.`);
}
const [, , , , detail = {}] = token;
const { unit, value } = detail as {
unit: string;
value: number;
};
const { dimension = {} } = opt;
if (unit === 'px') {
return `${value}${unit}`;
}
const relativeValue = Number(value);
if (unit && Number.isFinite(relativeValue)) {
let pixelValue;
if (Object.hasOwnProperty.call(dimension, unit)) {
pixelValue = dimension[unit];
} else if (typeof dimension.callback === 'function') {
pixelValue = dimension.callback(unit);
}
pixelValue = Number(pixelValue);
if (Number.isFinite(pixelValue)) {
return `${relativeValue * pixelValue}px`;
}
}
return new NullObject();
};
/**
* parse tokens
* @param tokens - CSS tokens
* @param [opt] - options
* @returns parsed tokens
*/
export const parseTokens = (
tokens: CSSToken[],
opt: Options = {}
): string[] => {
if (!Array.isArray(tokens)) {
throw new TypeError(`${tokens} is not an array.`);
}
const { format = '' } = opt;
const mathFunc = new Set();
let nest = 0;
const res: string[] = [];
while (tokens.length) {
const token = tokens.shift();
if (!Array.isArray(token)) {
throw new TypeError(`${token} is not an array.`);
}
const [type = '', value = ''] = token as [TokenType, string];
switch (type) {
case DIM: {
if (format === VAL_SPEC && !mathFunc.has(nest)) {
res.push(value);
} else {
const resolvedValue = resolveDimension(token, opt);
if (isString(resolvedValue)) {
res.push(resolvedValue);
} else {
res.push(value);
}
}
break;
}
case FUNC:
case PAREN_OPEN: {
res.push(value);
nest++;
if (REG_FN_MATH_START.test(value)) {
mathFunc.add(nest);
}
break;
}
case PAREN_CLOSE: {
if (res.length) {
const lastValue = res[res.length - 1];
if (lastValue === ' ') {
res.splice(-1, 1, value);
} else {
res.push(value);
}
} else {
res.push(value);
}
if (mathFunc.has(nest)) {
mathFunc.delete(nest);
}
nest--;
break;
}
case W_SPACE: {
if (res.length) {
const lastValue = res[res.length - 1];
if (
isString(lastValue) &&
!lastValue.endsWith('(') &&
lastValue !== ' '
) {
res.push(value);
}
}
break;
}
default: {
if (type !== COMMENT && type !== EOF) {
res.push(value);
}
}
}
}
return res;
};
/**
* CSS calc()
* @param value - CSS value including calc()
* @param [opt] - options
* @returns resolved value
*/
export const cssCalc = (value: string, opt: Options = {}): string => {
const { format = '' } = opt;
if (isString(value)) {
if (REG_FN_VAR.test(value)) {
if (format === VAL_SPEC) {
return value;
} else {
const resolvedValue = resolveVar(value, opt);
if (isString(resolvedValue)) {
return resolvedValue;
} else {
return '';
}
}
} else if (!REG_FN_CALC.test(value)) {
return value;
}
value = value.toLowerCase().trim();
} else {
throw new TypeError(`${value} is not a string.`);
}
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'cssCalc',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
return cachedResult.item as string;
}
const tokens = tokenize({ css: value });
const values = parseTokens(tokens, opt);
let resolvedValue: string = calc(values.join(''), {
toCanonicalUnits: true
});
if (REG_FN_VAR_START.test(value)) {
if (REG_TYPE_DIM_PCT.test(resolvedValue)) {
const [, val, unit] = resolvedValue.match(
REG_TYPE_DIM_PCT
) as MatchedRegExp;
resolvedValue = `${roundToPrecision(Number(val), HEX)}${unit}`;
}
// wrap with `calc()`
if (
resolvedValue &&
!REG_FN_VAR_START.test(resolvedValue) &&
format === VAL_SPEC
) {
resolvedValue = `calc(${resolvedValue})`;
}
}
setCache(cacheKey, resolvedValue);
return resolvedValue;
};

View File

@@ -0,0 +1,287 @@
/**
* css-gradient
*/
import { CacheItem, createCacheKey, getCache, setCache } from './cache';
import { isString } from './common';
import { MatchedRegExp, Options } from './typedef';
import { isColor, splitValue } from './util';
/* constants */
import {
ANGLE,
CS_HUE,
CS_RECT,
LENGTH,
NUM,
NUM_POSITIVE,
PCT
} from './constant';
const NAMESPACE = 'css-gradient';
const DIM_ANGLE = `${NUM}(?:${ANGLE})`;
const DIM_ANGLE_PCT = `${DIM_ANGLE}|${PCT}`;
const DIM_LEN = `${NUM}(?:${LENGTH})|0`;
const DIM_LEN_PCT = `${DIM_LEN}|${PCT}`;
const DIM_LEN_PCT_POSI = `${NUM_POSITIVE}(?:${LENGTH}|%)|0`;
const DIM_LEN_POSI = `${NUM_POSITIVE}(?:${LENGTH})|0`;
const CTR = 'center';
const L_R = 'left|right';
const T_B = 'top|bottom';
const S_E = 'start|end';
const AXIS_X = `${L_R}|x-(?:${S_E})`;
const AXIS_Y = `${T_B}|y-(?:${S_E})`;
const BLOCK = `block-(?:${S_E})`;
const INLINE = `inline-(?:${S_E})`;
const POS_1 = `${CTR}|${AXIS_X}|${AXIS_Y}|${BLOCK}|${INLINE}|${DIM_LEN_PCT}`;
const POS_2 = [
`(?:${CTR}|${AXIS_X})\\s+(?:${CTR}|${AXIS_Y})`,
`(?:${CTR}|${AXIS_Y})\\s+(?:${CTR}|${AXIS_X})`,
`(?:${CTR}|${AXIS_X}|${DIM_LEN_PCT})\\s+(?:${CTR}|${AXIS_Y}|${DIM_LEN_PCT})`,
`(?:${CTR}|${BLOCK})\\s+(?:${CTR}|${INLINE})`,
`(?:${CTR}|${INLINE})\\s+(?:${CTR}|${BLOCK})`,
`(?:${CTR}|${S_E})\\s+(?:${CTR}|${S_E})`
].join('|');
const POS_4 = [
`(?:${AXIS_X})\\s+(?:${DIM_LEN_PCT})\\s+(?:${AXIS_Y})\\s+(?:${DIM_LEN_PCT})`,
`(?:${AXIS_Y})\\s+(?:${DIM_LEN_PCT})\\s+(?:${AXIS_X})\\s+(?:${DIM_LEN_PCT})`,
`(?:${BLOCK})\\s+(?:${DIM_LEN_PCT})\\s+(?:${INLINE})\\s+(?:${DIM_LEN_PCT})`,
`(?:${INLINE})\\s+(?:${DIM_LEN_PCT})\\s+(?:${BLOCK})\\s+(?:${DIM_LEN_PCT})`,
`(?:${S_E})\\s+(?:${DIM_LEN_PCT})\\s+(?:${S_E})\\s+(?:${DIM_LEN_PCT})`
].join('|');
const RAD_EXTENT = '(?:clos|farth)est-(?:corner|side)';
const RAD_SIZE = [
`${RAD_EXTENT}(?:\\s+${RAD_EXTENT})?`,
`${DIM_LEN_POSI}`,
`(?:${DIM_LEN_PCT_POSI})\\s+(?:${DIM_LEN_PCT_POSI})`
].join('|');
const RAD_SHAPE = 'circle|ellipse';
const FROM_ANGLE = `from\\s+${DIM_ANGLE}`;
const AT_POSITION = `at\\s+(?:${POS_1}|${POS_2}|${POS_4})`;
const TO_SIDE_CORNER = `to\\s+(?:(?:${L_R})(?:\\s(?:${T_B}))?|(?:${T_B})(?:\\s(?:${L_R}))?)`;
const IN_COLOR_SPACE = `in\\s+(?:${CS_RECT}|${CS_HUE})`;
/* type definitions */
/**
* @type ColorStopList - list of color stops
*/
type ColorStopList = [string, string, ...string[]];
/**
* @typedef Gradient - parsed CSS gradient
* @property value - input value
* @property type - gradient type
* @property [gradientLine] - gradient line
* @property colorStopList - list of color stops
*/
interface Gradient {
value: string;
type: string;
gradientLine?: string;
colorStopList: ColorStopList;
}
/* regexp */
const REG_GRAD = /^(?:repeating-)?(?:conic|linear|radial)-gradient\(/;
const REG_GRAD_CAPT = /^((?:repeating-)?(?:conic|linear|radial)-gradient)\(/;
/**
* get gradient type
* @param value - gradient value
* @returns gradient type
*/
export const getGradientType = (value: string): string => {
if (isString(value)) {
value = value.trim();
if (REG_GRAD.test(value)) {
const [, type] = value.match(REG_GRAD_CAPT) as MatchedRegExp;
return type;
}
}
return '';
};
/**
* validate gradient line
* @param value - gradient line value
* @param type - gradient type
* @returns result
*/
export const validateGradientLine = (value: string, type: string): boolean => {
if (isString(value) && isString(type)) {
value = value.trim();
type = type.trim();
let lineSyntax = '';
if (/^(?:repeating-)?linear-gradient$/.test(type)) {
/*
* <linear-gradient-line> = [
* [ <angle> | to <side-or-corner> ] ||
* <color-interpolation-method>
* ]
*/
lineSyntax = [
`(?:${DIM_ANGLE}|${TO_SIDE_CORNER})(?:\\s+${IN_COLOR_SPACE})?`,
`${IN_COLOR_SPACE}(?:\\s+(?:${DIM_ANGLE}|${TO_SIDE_CORNER}))?`
].join('|');
} else if (/^(?:repeating-)?radial-gradient$/.test(type)) {
/*
* <radial-gradient-line> = [
* [ [ <radial-shape> || <radial-size> ]? [ at <position> ]? ] ||
* <color-interpolation-method>]?
*/
lineSyntax = [
`(?:${RAD_SHAPE})(?:\\s+(?:${RAD_SIZE}))?(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
`(?:${RAD_SIZE})(?:\\s+(?:${RAD_SHAPE}))?(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
`${AT_POSITION}(?:\\s+${IN_COLOR_SPACE})?`,
`${IN_COLOR_SPACE}(?:\\s+${RAD_SHAPE})(?:\\s+(?:${RAD_SIZE}))?(?:\\s+${AT_POSITION})?`,
`${IN_COLOR_SPACE}(?:\\s+${RAD_SIZE})(?:\\s+(?:${RAD_SHAPE}))?(?:\\s+${AT_POSITION})?`,
`${IN_COLOR_SPACE}(?:\\s+${AT_POSITION})?`
].join('|');
} else if (/^(?:repeating-)?conic-gradient$/.test(type)) {
/*
* <conic-gradient-line> = [
* [ [ from <angle> ]? [ at <position> ]? ] ||
* <color-interpolation-method>
* ]
*/
lineSyntax = [
`${FROM_ANGLE}(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
`${AT_POSITION}(?:\\s+${IN_COLOR_SPACE})?`,
`${IN_COLOR_SPACE}(?:\\s+${FROM_ANGLE})?(?:\\s+${AT_POSITION})?`
].join('|');
}
if (lineSyntax) {
const reg = new RegExp(`^(?:${lineSyntax})$`);
return reg.test(value);
}
}
return false;
};
/**
* validate color stop list
* @param list
* @param type
* @param [opt]
* @returns result
*/
export const validateColorStopList = (
list: string[],
type: string,
opt: Options = {}
): boolean => {
if (Array.isArray(list) && list.length > 1) {
const dimension = /^(?:repeating-)?conic-gradient$/.test(type)
? DIM_ANGLE_PCT
: DIM_LEN_PCT;
const regColorHint = new RegExp(`^(?:${dimension})$`);
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
const arr = [];
for (const item of list) {
if (isString(item)) {
if (regColorHint.test(item)) {
arr.push('hint');
} else {
const color = item.replace(regDimension, '');
if (isColor(color, opt)) {
arr.push('color');
} else {
return false;
}
}
}
}
const value = arr.join(',');
return /^color(?:,(?:hint,)?color)+$/.test(value);
}
return false;
};
/**
* parse CSS gradient
* @param value - gradient value
* @param [opt] - options
* @returns parsed result
*/
export const parseGradient = (
value: string,
opt: Options = {}
): Gradient | null => {
if (isString(value)) {
value = value.trim();
const cacheKey: string = createCacheKey(
{
namespace: NAMESPACE,
name: 'parseGradient',
value
},
opt
);
const cachedResult = getCache(cacheKey);
if (cachedResult instanceof CacheItem) {
if (cachedResult.isNull) {
return null;
}
return cachedResult.item as Gradient;
}
const type = getGradientType(value);
const gradValue = value.replace(REG_GRAD, '').replace(/\)$/, '');
if (type && gradValue) {
const [lineOrColorStop = '', ...colorStops] = splitValue(gradValue, ',');
const dimension = /^(?:repeating-)?conic-gradient$/.test(type)
? DIM_ANGLE_PCT
: DIM_LEN_PCT;
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
let isColorStop = false;
if (regDimension.test(lineOrColorStop)) {
const colorStop = lineOrColorStop.replace(regDimension, '');
if (isColor(colorStop, opt)) {
isColorStop = true;
}
} else if (isColor(lineOrColorStop, opt)) {
isColorStop = true;
}
if (isColorStop) {
colorStops.unshift(lineOrColorStop);
const valid = validateColorStopList(colorStops, type, opt);
if (valid) {
const res: Gradient = {
value,
type,
colorStopList: colorStops as ColorStopList
};
setCache(cacheKey, res);
return res;
}
} else if (colorStops.length > 1) {
const gradientLine = lineOrColorStop;
const valid =
validateGradientLine(gradientLine, type) &&
validateColorStopList(colorStops, type, opt);
if (valid) {
const res: Gradient = {
value,
type,
gradientLine,
colorStopList: colorStops as ColorStopList
};
setCache(cacheKey, res);
return res;
}
}
}
setCache(cacheKey, null);
return null;
}
return null;
};
/**
* is CSS gradient
* @param value - CSS value
* @param [opt] - options
* @returns result
*/
export const isGradient = (value: string, opt: Options = {}): boolean => {
const gradient = parseGradient(value, opt);
return gradient !== null;
};

Some files were not shown because too many files have changed in this diff Show More