feat(snipe): Vue 3 frontend scaffold + Docker web service
- web/: Vue 3 + Vite + UnoCSS + Pinia, dark tactical theme (amber/#0d1117) - AppNav, ListingCard, SearchView with filters/sort, composables (useSnipeMode, useKonamiCode, useMotion), Pinia search store - Steal shimmer, auction countdown, Snipe Mode easter egg all native in Vue - docker/web/: nginx + multi-stage Dockerfile (node build → nginx serve) - compose.yml: api (8510) + web (8509) services - Dockerfile CMD updated to uvicorn for upcoming FastAPI layer - Clean build: 0 TS errors, 380 modules
This commit is contained in:
parent
07794ee163
commit
7a704441a6
9684 changed files with 1179566 additions and 5 deletions
|
|
@ -11,5 +11,5 @@ COPY snipe/ ./snipe/
|
||||||
WORKDIR /app/snipe
|
WORKDIR /app/snipe
|
||||||
RUN pip install --no-cache-dir -e .
|
RUN pip install --no-cache-dir -e .
|
||||||
|
|
||||||
EXPOSE 8509
|
EXPOSE 8510
|
||||||
CMD ["streamlit", "run", "streamlit_app.py", "--server.port=8509", "--server.address=0.0.0.0"]
|
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8510"]
|
||||||
|
|
|
||||||
14
compose.yml
14
compose.yml
|
|
@ -1,10 +1,20 @@
|
||||||
services:
|
services:
|
||||||
snipe:
|
api:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: snipe/Dockerfile
|
dockerfile: snipe/Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- "8506:8506"
|
- "8510:8510"
|
||||||
env_file: .env
|
env_file: .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/snipe/data
|
- ./data:/app/snipe/data
|
||||||
|
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: docker/web/Dockerfile
|
||||||
|
ports:
|
||||||
|
- "8509:80"
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
|
|
||||||
15
docker/web/Dockerfile
Normal file
15
docker/web/Dockerfile
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Stage 1: build
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
COPY web/package*.json ./
|
||||||
|
RUN npm ci --prefer-offline
|
||||||
|
COPY web/ ./
|
||||||
|
ARG VITE_BASE_URL=/snipe/
|
||||||
|
ENV VITE_BASE_URL=${VITE_BASE_URL}
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Stage 2: serve
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY docker/web/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
25
docker/web/nginx.conf
Normal file
25
docker/web/nginx.conf
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# index.html — never cache; ensures clients always get the latest entry point
|
||||||
|
# after a deployment (chunks are content-hashed so they can be cached forever)
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
try_files $uri /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# SPA fallback for all other routes
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cache static assets aggressively — content hash in filename guarantees freshness
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SERVICE=snipe
|
SERVICE=snipe
|
||||||
PORT=8506
|
PORT=8509 # Vue web UI (nginx)
|
||||||
COMPOSE_FILE="compose.yml"
|
COMPOSE_FILE="compose.yml"
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
|
|
|
||||||
20
web/index.html
Normal file
20
web/index.html
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<!-- Emoji favicon: target reticle — inline SVG to avoid a separate file -->
|
||||||
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🎯</text></svg>" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Snipe</title>
|
||||||
|
<!-- Inline background prevents blank flash before CSS bundle loads -->
|
||||||
|
<!-- Matches --color-surface dark tactical theme from theme.css -->
|
||||||
|
<style>
|
||||||
|
html, body { margin: 0; background: #0d1117; min-height: 100vh; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Mount target only — App.vue root must NOT use id="app". Gotcha #1. -->
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
web/node_modules/.bin/acorn
generated
vendored
Symbolic link
1
web/node_modules/.bin/acorn
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../acorn/bin/acorn
|
||||||
1
web/node_modules/.bin/css-beautify
generated
vendored
Symbolic link
1
web/node_modules/.bin/css-beautify
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../js-beautify/js/bin/css-beautify.js
|
||||||
1
web/node_modules/.bin/editorconfig
generated
vendored
Symbolic link
1
web/node_modules/.bin/editorconfig
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../editorconfig/bin/editorconfig
|
||||||
1
web/node_modules/.bin/esbuild
generated
vendored
Symbolic link
1
web/node_modules/.bin/esbuild
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../esbuild/bin/esbuild
|
||||||
1
web/node_modules/.bin/glob
generated
vendored
Symbolic link
1
web/node_modules/.bin/glob
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../glob/dist/esm/bin.mjs
|
||||||
1
web/node_modules/.bin/html-beautify
generated
vendored
Symbolic link
1
web/node_modules/.bin/html-beautify
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../js-beautify/js/bin/html-beautify.js
|
||||||
1
web/node_modules/.bin/jiti
generated
vendored
Symbolic link
1
web/node_modules/.bin/jiti
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../jiti/lib/jiti-cli.mjs
|
||||||
1
web/node_modules/.bin/js-beautify
generated
vendored
Symbolic link
1
web/node_modules/.bin/js-beautify
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../js-beautify/js/bin/js-beautify.js
|
||||||
1
web/node_modules/.bin/jsesc
generated
vendored
Symbolic link
1
web/node_modules/.bin/jsesc
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../jsesc/bin/jsesc
|
||||||
1
web/node_modules/.bin/json5
generated
vendored
Symbolic link
1
web/node_modules/.bin/json5
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../json5/lib/cli.js
|
||||||
1
web/node_modules/.bin/nanoid
generated
vendored
Symbolic link
1
web/node_modules/.bin/nanoid
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../nanoid/bin/nanoid.cjs
|
||||||
1
web/node_modules/.bin/node-which
generated
vendored
Symbolic link
1
web/node_modules/.bin/node-which
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../which/bin/node-which
|
||||||
1
web/node_modules/.bin/nopt
generated
vendored
Symbolic link
1
web/node_modules/.bin/nopt
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../nopt/bin/nopt.js
|
||||||
1
web/node_modules/.bin/parser
generated
vendored
Symbolic link
1
web/node_modules/.bin/parser
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../@babel/parser/bin/babel-parser.js
|
||||||
1
web/node_modules/.bin/regexp-tree
generated
vendored
Symbolic link
1
web/node_modules/.bin/regexp-tree
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../regexp-tree/bin/regexp-tree
|
||||||
1
web/node_modules/.bin/rollup
generated
vendored
Symbolic link
1
web/node_modules/.bin/rollup
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../rollup/dist/bin/rollup
|
||||||
1
web/node_modules/.bin/semver
generated
vendored
Symbolic link
1
web/node_modules/.bin/semver
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../semver/bin/semver.js
|
||||||
1
web/node_modules/.bin/specificity
generated
vendored
Symbolic link
1
web/node_modules/.bin/specificity
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../@bramus/specificity/bin/cli.js
|
||||||
1
web/node_modules/.bin/tldts
generated
vendored
Symbolic link
1
web/node_modules/.bin/tldts
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../tldts/bin/cli.js
|
||||||
1
web/node_modules/.bin/tsc
generated
vendored
Symbolic link
1
web/node_modules/.bin/tsc
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../typescript/bin/tsc
|
||||||
1
web/node_modules/.bin/tsserver
generated
vendored
Symbolic link
1
web/node_modules/.bin/tsserver
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../typescript/bin/tsserver
|
||||||
1
web/node_modules/.bin/unocss
generated
vendored
Symbolic link
1
web/node_modules/.bin/unocss
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../@unocss/cli/bin/unocss.mjs
|
||||||
1
web/node_modules/.bin/vite
generated
vendored
Symbolic link
1
web/node_modules/.bin/vite
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../vite/bin/vite.js
|
||||||
1
web/node_modules/.bin/vitest
generated
vendored
Symbolic link
1
web/node_modules/.bin/vitest
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../vitest/vitest.mjs
|
||||||
1
web/node_modules/.bin/vue-tsc
generated
vendored
Symbolic link
1
web/node_modules/.bin/vue-tsc
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../vue-tsc/bin/vue-tsc.js
|
||||||
1
web/node_modules/.bin/why-is-node-running
generated
vendored
Symbolic link
1
web/node_modules/.bin/why-is-node-running
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../why-is-node-running/cli.js
|
||||||
1
web/node_modules/.bin/yaml
generated
vendored
Symbolic link
1
web/node_modules/.bin/yaml
generated
vendored
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../yaml/bin.mjs
|
||||||
3767
web/node_modules/.package-lock.json
generated
vendored
Normal file
3767
web/node_modules/.package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
20
web/node_modules/@acemir/cssom/LICENSE.txt
generated
vendored
Normal file
20
web/node_modules/@acemir/cssom/LICENSE.txt
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (c) Nikita Vasilyev
|
||||||
|
|
||||||
|
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.
|
||||||
64
web/node_modules/@acemir/cssom/README.mdown
generated
vendored
Normal file
64
web/node_modules/@acemir/cssom/README.mdown
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# CSSOM
|
||||||
|
|
||||||
|
CSSOM.js is a CSS parser written in pure JavaScript. It is also a partial implementation of [CSS Object Model](http://dev.w3.org/csswg/cssom/).
|
||||||
|
|
||||||
|
CSSOM.parse("body {color: black}")
|
||||||
|
-> {
|
||||||
|
cssRules: [
|
||||||
|
{
|
||||||
|
selectorText: "body",
|
||||||
|
style: {
|
||||||
|
0: "color",
|
||||||
|
color: "black",
|
||||||
|
length: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
## [Parser demo](https://acemir.github.io/CSSOM/docs/parse.html)
|
||||||
|
|
||||||
|
Works well in Google Chrome 6+, Safari 5+, Firefox 3.6+, Opera 10.63+.
|
||||||
|
Doesn't work in IE < 9 because of unsupported getters/setters.
|
||||||
|
|
||||||
|
To use CSSOM.js in the browser you might want to build a one-file version that exposes a single `CSSOM` global variable:
|
||||||
|
|
||||||
|
➤ git clone https://github.com/acemir/CSSOM.git
|
||||||
|
➤ cd CSSOM
|
||||||
|
➤ node build.js
|
||||||
|
build/CSSOM.js is done
|
||||||
|
|
||||||
|
To use it with Node.js or any other CommonJS loader:
|
||||||
|
|
||||||
|
➤ npm install @acemir/cssom
|
||||||
|
|
||||||
|
## Don’t use it if...
|
||||||
|
|
||||||
|
You parse CSS to mungle, minify or reformat code like this:
|
||||||
|
|
||||||
|
```css
|
||||||
|
div {
|
||||||
|
background: gray;
|
||||||
|
background: linear-gradient(to bottom, white 0%, black 100%);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This pattern is often used to give browsers that don’t understand linear gradients a fallback solution (e.g. gray color in the example).
|
||||||
|
In CSSOM, `background: gray` [gets overwritten](http://nv.github.io/CSSOM/docs/parse.html#css=div%20%7B%0A%20%20%20%20%20%20background%3A%20gray%3B%0A%20%20%20%20background%3A%20linear-gradient(to%20bottom%2C%20white%200%25%2C%20black%20100%25)%3B%0A%7D).
|
||||||
|
It does **NOT** get preserved.
|
||||||
|
|
||||||
|
If you do CSS mungling, minification, or image inlining, considere using one of the following:
|
||||||
|
|
||||||
|
* [postcss](https://github.com/postcss/postcss)
|
||||||
|
* [reworkcss/css](https://github.com/reworkcss/css)
|
||||||
|
* [csso](https://github.com/css/csso)
|
||||||
|
* [mensch](https://github.com/brettstimmerman/mensch)
|
||||||
|
|
||||||
|
|
||||||
|
## [Tests](https://acemir.github.io/CSSOM/spec/)
|
||||||
|
|
||||||
|
To run tests locally:
|
||||||
|
|
||||||
|
➤ git submodule init
|
||||||
|
➤ git submodule update
|
||||||
6611
web/node_modules/@acemir/cssom/build/CSSOM.js
generated
vendored
Normal file
6611
web/node_modules/@acemir/cssom/build/CSSOM.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
32
web/node_modules/@acemir/cssom/lib/CSSConditionRule.js
generated
vendored
Normal file
32
web/node_modules/@acemir/cssom/lib/CSSConditionRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://www.w3.org/TR/css-conditional-3/#the-cssconditionrule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSConditionRule = function CSSConditionRule() {
|
||||||
|
CSSOM.CSSGroupingRule.call(this);
|
||||||
|
this.__conditionText = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSConditionRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
||||||
|
CSSOM.CSSConditionRule.prototype.constructor = CSSOM.CSSConditionRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSConditionRule, CSSOM.CSSGroupingRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSConditionRule.prototype, "conditionText", {
|
||||||
|
get: function () {
|
||||||
|
return this.__conditionText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSConditionRule = CSSOM.CSSConditionRule;
|
||||||
|
///CommonJS
|
||||||
70
web/node_modules/@acemir/cssom/lib/CSSContainerRule.js
generated
vendored
Normal file
70
web/node_modules/@acemir/cssom/lib/CSSContainerRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
CSSConditionRule: require("./CSSConditionRule").CSSConditionRule,
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-contain-3/
|
||||||
|
* @see https://www.w3.org/TR/css-contain-3/
|
||||||
|
*/
|
||||||
|
CSSOM.CSSContainerRule = function CSSContainerRule() {
|
||||||
|
CSSOM.CSSConditionRule.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSContainerRule.prototype = Object.create(CSSOM.CSSConditionRule.prototype);
|
||||||
|
CSSOM.CSSContainerRule.prototype.constructor = CSSOM.CSSContainerRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSContainerRule, CSSOM.CSSConditionRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSContainerRule.prototype, "type", {
|
||||||
|
value: 17,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperties(CSSOM.CSSContainerRule.prototype, {
|
||||||
|
"cssText": {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@container " + this.conditionText + values;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"containerName": {
|
||||||
|
get: function() {
|
||||||
|
var parts = this.conditionText.trim().split(/\s+/);
|
||||||
|
if (parts.length > 1 && parts[0] !== '(' && !parts[0].startsWith('(')) {
|
||||||
|
return parts[0];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"containerQuery": {
|
||||||
|
get: function() {
|
||||||
|
var parts = this.conditionText.trim().split(/\s+/);
|
||||||
|
if (parts.length > 1 && parts[0] !== '(' && !parts[0].startsWith('(')) {
|
||||||
|
return parts.slice(1).join(' ');
|
||||||
|
}
|
||||||
|
return this.conditionText;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSContainerRule = CSSOM.CSSContainerRule;
|
||||||
|
///CommonJS
|
||||||
57
web/node_modules/@acemir/cssom/lib/CSSCounterStyleRule.js
generated
vendored
Normal file
57
web/node_modules/@acemir/cssom/lib/CSSCounterStyleRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-counter-styles/#the-csscounterstylerule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSCounterStyleRule = function CSSCounterStyleRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.name = "";
|
||||||
|
this.__props = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSCounterStyleRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSCounterStyleRule.prototype.constructor = CSSOM.CSSCounterStyleRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSCounterStyleRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSCounterStyleRule.prototype, "type", {
|
||||||
|
value: 11,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSCounterStyleRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
// FIXME : Implement real cssText generation based on properties
|
||||||
|
return "@counter-style " + this.name + " { " + this.__props + " }";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NON-STANDARD
|
||||||
|
* Rule text parser.
|
||||||
|
* @param {string} cssText
|
||||||
|
*/
|
||||||
|
Object.defineProperty(CSSOM.CSSCounterStyleRule.prototype, "parse", {
|
||||||
|
value: function(cssText) {
|
||||||
|
// Extract the name from "@counter-style <name> { ... }"
|
||||||
|
var match = cssText.match(/@counter-style\s+([^\s{]+)\s*\{([^]*)\}/);
|
||||||
|
if (match) {
|
||||||
|
this.name = match[1];
|
||||||
|
// Get the text inside the brackets and clean it up
|
||||||
|
var propsText = match[2];
|
||||||
|
this.__props = propsText.trim().replace(/\n/g, " ").replace(/(['"])(?:\\.|[^\\])*?\1|(\s{2,})/g, function (match, quote) {
|
||||||
|
return quote ? match : ' ';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSCounterStyleRule = CSSOM.CSSCounterStyleRule;
|
||||||
|
///CommonJS
|
||||||
48
web/node_modules/@acemir/cssom/lib/CSSDocumentRule.js
generated
vendored
Normal file
48
web/node_modules/@acemir/cssom/lib/CSSDocumentRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
MatcherList: require("./MatcherList").MatcherList
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://developer.mozilla.org/en/CSS/@-moz-document
|
||||||
|
* @deprecated This rule is a non-standard Mozilla-specific extension and is not part of any official CSS specification.
|
||||||
|
*/
|
||||||
|
CSSOM.CSSDocumentRule = function CSSDocumentRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.matcher = new CSSOM.MatcherList();
|
||||||
|
this.cssRules = new CSSOM.CSSRuleList();
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSDocumentRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSDocumentRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "type", {
|
||||||
|
value: 10,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
//CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
||||||
|
//CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var cssTexts = [];
|
||||||
|
for (var i=0, length=this.cssRules.length; i < length; i++) {
|
||||||
|
cssTexts.push(this.cssRules[i].cssText);
|
||||||
|
}
|
||||||
|
return "@-moz-document " + this.matcher.matcherText + " {" + (cssTexts.length ? "\n " + cssTexts.join("\n ") : "") + "\n}";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSDocumentRule = CSSOM.CSSDocumentRule;
|
||||||
|
///CommonJS
|
||||||
62
web/node_modules/@acemir/cssom/lib/CSSFontFaceRule.js
generated
vendored
Normal file
62
web/node_modules/@acemir/cssom/lib/CSSFontFaceRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
|
||||||
|
CSSRule: require("./CSSRule").CSSRule
|
||||||
|
};
|
||||||
|
// Use cssstyle if available
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#css-font-face-rule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSFontFaceRule = function CSSFontFaceRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.__style = new CSSOM.CSSStyleDeclaration();
|
||||||
|
this.__style.parentRule = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSFontFaceRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSFontFaceRule.prototype.constructor = CSSOM.CSSFontFaceRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSFontFaceRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "type", {
|
||||||
|
value: 5,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
//CSSOM.CSSFontFaceRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
||||||
|
//CSSOM.CSSFontFaceRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "style", {
|
||||||
|
get: function() {
|
||||||
|
return this.__style;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__style.cssText = value;
|
||||||
|
} else {
|
||||||
|
this.__style = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSFontFaceRule.cpp
|
||||||
|
Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
return "@font-face {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSFontFaceRule = CSSOM.CSSFontFaceRule;
|
||||||
|
///CommonJS
|
||||||
165
web/node_modules/@acemir/cssom/lib/CSSGroupingRule.js
generated
vendored
Normal file
165
web/node_modules/@acemir/cssom/lib/CSSGroupingRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
parse: require('./parse').parse
|
||||||
|
};
|
||||||
|
var errorUtils = require("./errorUtils").errorUtils;
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSGroupingRule = function CSSGroupingRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.__cssRules = new CSSOM.CSSRuleList();
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSGroupingRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSGroupingRule.prototype.constructor = CSSOM.CSSGroupingRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSGroupingRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSGroupingRule.prototype, "cssRules", {
|
||||||
|
get: function() {
|
||||||
|
return this.__cssRules;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to insert a new CSS rule to a list of CSS rules.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* cssGroupingRule.cssText
|
||||||
|
* -> "body{margin:0;}"
|
||||||
|
* cssGroupingRule.insertRule("img{border:none;}", 1)
|
||||||
|
* -> 1
|
||||||
|
* cssGroupingRule.cssText
|
||||||
|
* -> "body{margin:0;}img{border:none;}"
|
||||||
|
*
|
||||||
|
* @param {string} rule
|
||||||
|
* @param {number} [index]
|
||||||
|
* @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-insertrule
|
||||||
|
* @return {number} The index within the grouping rule's collection of the newly inserted rule.
|
||||||
|
*/
|
||||||
|
CSSOM.CSSGroupingRule.prototype.insertRule = function insertRule(rule, index) {
|
||||||
|
if (rule === undefined && index === undefined) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
|
||||||
|
}
|
||||||
|
if (index === void 0) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
index = Number(index);
|
||||||
|
if (index < 0) {
|
||||||
|
index = 4294967296 + index;
|
||||||
|
}
|
||||||
|
if (index > this.cssRules.length) {
|
||||||
|
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
||||||
|
}
|
||||||
|
var ruleToParse = processedRuleToParse = String(rule);
|
||||||
|
ruleToParse = ruleToParse.trim().replace(/^\/\*[\s\S]*?\*\/\s*/, "");
|
||||||
|
var isNestedSelector = this.constructor.name === "CSSStyleRule";
|
||||||
|
if (isNestedSelector === false) {
|
||||||
|
var currentRule = this;
|
||||||
|
while (currentRule.parentRule) {
|
||||||
|
currentRule = currentRule.parentRule;
|
||||||
|
if (currentRule.constructor.name === "CSSStyleRule") {
|
||||||
|
isNestedSelector = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNestedSelector) {
|
||||||
|
processedRuleToParse = 's { n { } ' + ruleToParse + '}';
|
||||||
|
}
|
||||||
|
var isScopeRule = this.constructor.name === "CSSScopeRule";
|
||||||
|
if (isScopeRule) {
|
||||||
|
if (isNestedSelector) {
|
||||||
|
processedRuleToParse = 's { ' + '@scope {' + ruleToParse + '}}';
|
||||||
|
} else {
|
||||||
|
processedRuleToParse = '@scope {' + ruleToParse + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var parsedRules = new CSSOM.CSSRuleList();
|
||||||
|
CSSOM.parse(processedRuleToParse, {
|
||||||
|
styleSheet: this.parentStyleSheet,
|
||||||
|
cssRules: parsedRules
|
||||||
|
});
|
||||||
|
if (isScopeRule) {
|
||||||
|
if (isNestedSelector) {
|
||||||
|
parsedRules = parsedRules[0].cssRules[0].cssRules;
|
||||||
|
} else {
|
||||||
|
parsedRules = parsedRules[0].cssRules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNestedSelector) {
|
||||||
|
parsedRules = parsedRules[0].cssRules.slice(1);
|
||||||
|
}
|
||||||
|
if (parsedRules.length !== 1) {
|
||||||
|
if (isNestedSelector && parsedRules.length === 0 && ruleToParse.indexOf('@font-face') === 0) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
|
||||||
|
"Only conditional nested group rules, style rules, @scope rules, @apply rules, and nested declaration rules may be nested.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
} else {
|
||||||
|
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var cssRule = parsedRules[0];
|
||||||
|
|
||||||
|
if (cssRule.constructor.name === 'CSSNestedDeclarations' && cssRule.style.length === 0) {
|
||||||
|
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for rules that cannot be inserted inside a CSSGroupingRule
|
||||||
|
if (cssRule.constructor.name === 'CSSImportRule' || cssRule.constructor.name === 'CSSNamespaceRule') {
|
||||||
|
var ruleKeyword = cssRule.constructor.name === 'CSSImportRule' ? '@import' : '@namespace';
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': " +
|
||||||
|
"'" + ruleKeyword + "' rules cannot be inserted inside a group rule.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for CSSLayerStatementRule (@layer statement rules)
|
||||||
|
if (cssRule.constructor.name === 'CSSLayerStatementRule') {
|
||||||
|
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
||||||
|
}
|
||||||
|
|
||||||
|
cssRule.__parentRule = this;
|
||||||
|
this.cssRules.splice(index, 0, cssRule);
|
||||||
|
return index;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to delete a rule from the grouping rule.
|
||||||
|
*
|
||||||
|
* cssGroupingRule.cssText
|
||||||
|
* -> "img{border:none;}body{margin:0;}"
|
||||||
|
* cssGroupingRule.deleteRule(0)
|
||||||
|
* cssGroupingRule.cssText
|
||||||
|
* -> "body{margin:0;}"
|
||||||
|
*
|
||||||
|
* @param {number} index within the grouping rule's rule list of the rule to remove.
|
||||||
|
* @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) {
|
||||||
|
if (index === undefined) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
|
||||||
|
}
|
||||||
|
index = Number(index);
|
||||||
|
if (index < 0) {
|
||||||
|
index = 4294967296 + index;
|
||||||
|
}
|
||||||
|
if (index >= this.cssRules.length) {
|
||||||
|
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
||||||
|
}
|
||||||
|
this.cssRules[index].__parentRule = null;
|
||||||
|
this.cssRules[index].__parentStyleSheet = null;
|
||||||
|
this.cssRules.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSGroupingRule = CSSOM.CSSGroupingRule;
|
||||||
|
///CommonJS
|
||||||
54
web/node_modules/@acemir/cssom/lib/CSSHostRule.js
generated
vendored
Normal file
54
web/node_modules/@acemir/cssom/lib/CSSHostRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://www.w3.org/TR/shadow-dom/#host-at-rule
|
||||||
|
* @see http://html5index.org/Shadow%20DOM%20-%20CSSHostRule.html
|
||||||
|
* @deprecated This rule was part of early Shadow DOM drafts but was removed in favor of the more flexible :host and :host-context() pseudo-classes in modern CSS for Web Components.
|
||||||
|
*/
|
||||||
|
CSSOM.CSSHostRule = function CSSHostRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.cssRules = new CSSOM.CSSRuleList();
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSHostRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSHostRule.prototype.constructor = CSSOM.CSSHostRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSHostRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSHostRule.prototype, "type", {
|
||||||
|
value: 1001,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
//CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
||||||
|
//CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSHostRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@host" + values;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSHostRule = CSSOM.CSSHostRule;
|
||||||
|
///CommonJS
|
||||||
267
web/node_modules/@acemir/cssom/lib/CSSImportRule.js
generated
vendored
Normal file
267
web/node_modules/@acemir/cssom/lib/CSSImportRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,267 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSStyleSheet: require("./CSSStyleSheet").CSSStyleSheet,
|
||||||
|
MediaList: require("./MediaList").MediaList
|
||||||
|
};
|
||||||
|
var regexPatterns = require("./regexPatterns").regexPatterns;
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#cssimportrule
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSImportRule = function CSSImportRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.__href = "";
|
||||||
|
this.__media = new CSSOM.MediaList();
|
||||||
|
this.__layerName = null;
|
||||||
|
this.__supportsText = null;
|
||||||
|
this.__styleSheet = new CSSOM.CSSStyleSheet();
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSImportRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSImportRule.prototype.constructor = CSSOM.CSSImportRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSImportRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "type", {
|
||||||
|
value: 3,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var mediaText = this.media.mediaText;
|
||||||
|
return "@import url(\"" + this.href.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + "\")" + (this.layerName !== null ? " layer" + (this.layerName && "(" + this.layerName + ")") : "" ) + (this.supportsText ? " supports(" + this.supportsText + ")" : "" ) + (mediaText ? " " + mediaText : "") + ";";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "href", {
|
||||||
|
get: function() {
|
||||||
|
return this.__href;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "media", {
|
||||||
|
get: function() {
|
||||||
|
return this.__media;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__media.mediaText = value;
|
||||||
|
} else {
|
||||||
|
this.__media = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "layerName", {
|
||||||
|
get: function() {
|
||||||
|
return this.__layerName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "supportsText", {
|
||||||
|
get: function() {
|
||||||
|
return this.__supportsText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "styleSheet", {
|
||||||
|
get: function() {
|
||||||
|
return this.__styleSheet;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NON-STANDARD
|
||||||
|
* Rule text parser.
|
||||||
|
* @param {string} cssText
|
||||||
|
*/
|
||||||
|
Object.defineProperty(CSSOM.CSSImportRule.prototype, "parse", {
|
||||||
|
value: function(cssText) {
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @import url(partial.css) screen, handheld;
|
||||||
|
* || |
|
||||||
|
* after-import media
|
||||||
|
* |
|
||||||
|
* url
|
||||||
|
*/
|
||||||
|
var state = '';
|
||||||
|
|
||||||
|
var buffer = '';
|
||||||
|
var index;
|
||||||
|
|
||||||
|
var layerRegExp = regexPatterns.layerRegExp;
|
||||||
|
var layerRuleNameRegExp = regexPatterns.layerRuleNameRegExp;
|
||||||
|
var doubleOrMoreSpacesRegExp = regexPatterns.doubleOrMoreSpacesRegExp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the content inside supports() handling nested parentheses.
|
||||||
|
* @param {string} text - The text to parse
|
||||||
|
* @returns {object|null} - {content: string, endIndex: number} or null if not found
|
||||||
|
*/
|
||||||
|
function extractSupportsContent(text) {
|
||||||
|
var supportsIndex = text.indexOf('supports(');
|
||||||
|
if (supportsIndex !== 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var depth = 0;
|
||||||
|
var start = supportsIndex + 'supports('.length;
|
||||||
|
var i = start;
|
||||||
|
|
||||||
|
for (; i < text.length; i++) {
|
||||||
|
if (text[i] === '(') {
|
||||||
|
depth++;
|
||||||
|
} else if (text[i] === ')') {
|
||||||
|
if (depth === 0) {
|
||||||
|
// Found the closing parenthesis for supports()
|
||||||
|
return {
|
||||||
|
content: text.slice(start, i),
|
||||||
|
endIndex: i
|
||||||
|
};
|
||||||
|
}
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // Unbalanced parentheses
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var character; (character = cssText.charAt(i)); i++) {
|
||||||
|
|
||||||
|
switch (character) {
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\f':
|
||||||
|
if (state === 'after-import') {
|
||||||
|
state = 'url';
|
||||||
|
} else {
|
||||||
|
buffer += character;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '@':
|
||||||
|
if (!state && cssText.indexOf('@import', i) === i) {
|
||||||
|
state = 'after-import';
|
||||||
|
i += 'import'.length;
|
||||||
|
buffer = '';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
if (state === 'media') {
|
||||||
|
buffer += character;
|
||||||
|
}
|
||||||
|
if (state === 'url' && cssText.indexOf('url(', i) === i) {
|
||||||
|
index = cssText.indexOf(')', i + 1);
|
||||||
|
if (index === -1) {
|
||||||
|
throw i + ': ")" not found';
|
||||||
|
}
|
||||||
|
i += 'url('.length;
|
||||||
|
var url = cssText.slice(i, index);
|
||||||
|
if (url[0] === url[url.length - 1]) {
|
||||||
|
if (url[0] === '"' || url[0] === "'") {
|
||||||
|
url = url.slice(1, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.__href = url;
|
||||||
|
i = index;
|
||||||
|
state = 'media';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
if (state === 'after-import' || state === 'url') {
|
||||||
|
index = cssText.indexOf('"', i + 1);
|
||||||
|
if (!index) {
|
||||||
|
throw i + ": '\"' not found";
|
||||||
|
}
|
||||||
|
this.__href = cssText.slice(i + 1, index);
|
||||||
|
i = index;
|
||||||
|
state = 'media';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "'":
|
||||||
|
if (state === 'after-import' || state === 'url') {
|
||||||
|
index = cssText.indexOf("'", i + 1);
|
||||||
|
if (!index) {
|
||||||
|
throw i + ': "\'" not found';
|
||||||
|
}
|
||||||
|
this.__href = cssText.slice(i + 1, index);
|
||||||
|
i = index;
|
||||||
|
state = 'media';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ';':
|
||||||
|
if (state === 'media') {
|
||||||
|
if (buffer) {
|
||||||
|
var bufferTrimmed = buffer.trim();
|
||||||
|
|
||||||
|
if (bufferTrimmed.indexOf('layer') === 0) {
|
||||||
|
var layerMatch = bufferTrimmed.match(layerRegExp);
|
||||||
|
|
||||||
|
if (layerMatch) {
|
||||||
|
var layerName = layerMatch[1].trim();
|
||||||
|
|
||||||
|
if (layerName.match(layerRuleNameRegExp) !== null) {
|
||||||
|
this.__layerName = layerMatch[1].trim();
|
||||||
|
bufferTrimmed = bufferTrimmed.replace(layerRegExp, '')
|
||||||
|
.replace(doubleOrMoreSpacesRegExp, ' ') // Replace double or more spaces with single space
|
||||||
|
.trim();
|
||||||
|
} else {
|
||||||
|
// REVIEW: In the browser, an empty layer() is not processed as a unamed layer
|
||||||
|
// and treats the rest of the string as mediaText, ignoring the parse of supports()
|
||||||
|
if (bufferTrimmed) {
|
||||||
|
this.media.mediaText = bufferTrimmed;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.__layerName = "";
|
||||||
|
bufferTrimmed = bufferTrimmed.substring('layer'.length).trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var supportsResult = extractSupportsContent(bufferTrimmed);
|
||||||
|
|
||||||
|
if (supportsResult) {
|
||||||
|
// REVIEW: In the browser, an empty supports() invalidates and ignores the entire @import rule
|
||||||
|
this.__supportsText = supportsResult.content.trim();
|
||||||
|
// Remove the entire supports(...) from the buffer
|
||||||
|
bufferTrimmed = bufferTrimmed.slice(0, 0) + bufferTrimmed.slice(supportsResult.endIndex + 1);
|
||||||
|
bufferTrimmed = bufferTrimmed.replace(doubleOrMoreSpacesRegExp, ' ').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// REVIEW: In the browser, any invalid media is replaced with 'not all'
|
||||||
|
if (bufferTrimmed) {
|
||||||
|
this.media.mediaText = bufferTrimmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (state === 'media') {
|
||||||
|
buffer += character;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSImportRule = CSSOM.CSSImportRule;
|
||||||
|
///CommonJS
|
||||||
63
web/node_modules/@acemir/cssom/lib/CSSKeyframeRule.js
generated
vendored
Normal file
63
web/node_modules/@acemir/cssom/lib/CSSKeyframeRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSStyleDeclaration: require('./CSSStyleDeclaration').CSSStyleDeclaration
|
||||||
|
};
|
||||||
|
// Use cssstyle if available
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframeRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframeRule = function CSSKeyframeRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.keyText = '';
|
||||||
|
this.__style = new CSSOM.CSSStyleDeclaration();
|
||||||
|
this.__style.parentRule = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSKeyframeRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSKeyframeRule.prototype.constructor = CSSOM.CSSKeyframeRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSKeyframeRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "type", {
|
||||||
|
value: 8,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
//CSSOM.CSSKeyframeRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
||||||
|
//CSSOM.CSSKeyframeRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "style", {
|
||||||
|
get: function() {
|
||||||
|
return this.__style;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__style.cssText = value;
|
||||||
|
} else {
|
||||||
|
this.__style = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframeRule.cpp
|
||||||
|
Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
return this.keyText + " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSKeyframeRule = CSSOM.CSSKeyframeRule;
|
||||||
|
///CommonJS
|
||||||
247
web/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js
generated
vendored
Normal file
247
web/node_modules/@acemir/cssom/lib/CSSKeyframesRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
parse: require("./parse").parse
|
||||||
|
};
|
||||||
|
var errorUtils = require("./errorUtils").errorUtils;
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframesRule = function CSSKeyframesRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.name = '';
|
||||||
|
this.cssRules = new CSSOM.CSSRuleList();
|
||||||
|
|
||||||
|
// Set up initial indexed access
|
||||||
|
this._setupIndexedAccess();
|
||||||
|
|
||||||
|
// Override cssRules methods after initial setup, store references as non-enumerable properties
|
||||||
|
var self = this;
|
||||||
|
var originalPush = this.cssRules.push;
|
||||||
|
var originalSplice = this.cssRules.splice;
|
||||||
|
|
||||||
|
// Create non-enumerable method overrides
|
||||||
|
Object.defineProperty(this.cssRules, 'push', {
|
||||||
|
value: function() {
|
||||||
|
var result = originalPush.apply(this, arguments);
|
||||||
|
self._setupIndexedAccess();
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(this.cssRules, 'splice', {
|
||||||
|
value: function() {
|
||||||
|
var result = originalSplice.apply(this, arguments);
|
||||||
|
self._setupIndexedAccess();
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSKeyframesRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSKeyframesRule.prototype.constructor = CSSOM.CSSKeyframesRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSKeyframesRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "type", {
|
||||||
|
value: 7,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp
|
||||||
|
Object.defineProperty(CSSOM.CSSKeyframesRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
var cssWideKeywords = ['initial', 'inherit', 'revert', 'revert-layer', 'unset', 'none'];
|
||||||
|
var processedName = cssWideKeywords.includes(this.name) ? '"' + this.name + '"' : this.name;
|
||||||
|
return "@" + (this._vendorPrefix || '') + "keyframes " + processedName + values;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a new keyframe rule to the list of keyframes.
|
||||||
|
*
|
||||||
|
* @param {string} rule - The keyframe rule string to append (e.g., "50% { opacity: 0.5; }")
|
||||||
|
* @see https://www.w3.org/TR/css-animations-1/#dom-csskeyframesrule-appendrule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframesRule.prototype.appendRule = function appendRule(rule) {
|
||||||
|
if (arguments.length === 0) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'appendRule', 'CSSKeyframesRule');
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedRule;
|
||||||
|
try {
|
||||||
|
// Parse the rule string as a keyframe rule
|
||||||
|
var tempStyleSheet = CSSOM.parse("@keyframes temp { " + rule + " }");
|
||||||
|
if (tempStyleSheet.cssRules.length > 0 && tempStyleSheet.cssRules[0].cssRules.length > 0) {
|
||||||
|
parsedRule = tempStyleSheet.cssRules[0].cssRules[0];
|
||||||
|
} else {
|
||||||
|
throw new Error("Failed to parse keyframe rule");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
errorUtils.throwParseError(this, 'appendRule', 'CSSKeyframesRule', rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
parsedRule.__parentRule = this;
|
||||||
|
this.cssRules.push(parsedRule);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a keyframe rule that matches the specified key.
|
||||||
|
*
|
||||||
|
* @param {string} select - The keyframe selector to delete (e.g., "50%", "from", "to")
|
||||||
|
* @see https://www.w3.org/TR/css-animations-1/#dom-csskeyframesrule-deleterule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframesRule.prototype.deleteRule = function deleteRule(select) {
|
||||||
|
if (arguments.length === 0) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'deleteRule', 'CSSKeyframesRule');
|
||||||
|
}
|
||||||
|
|
||||||
|
var normalizedSelect = this._normalizeKeyText(select);
|
||||||
|
|
||||||
|
for (var i = 0; i < this.cssRules.length; i++) {
|
||||||
|
var rule = this.cssRules[i];
|
||||||
|
if (this._normalizeKeyText(rule.keyText) === normalizedSelect) {
|
||||||
|
rule.__parentRule = null;
|
||||||
|
this.cssRules.splice(i, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds and returns the keyframe rule that matches the specified key.
|
||||||
|
* When multiple rules have the same key, returns the last one.
|
||||||
|
*
|
||||||
|
* @param {string} select - The keyframe selector to find (e.g., "50%", "from", "to")
|
||||||
|
* @return {CSSKeyframeRule|null} The matching keyframe rule, or null if not found
|
||||||
|
* @see https://www.w3.org/TR/css-animations-1/#dom-csskeyframesrule-findrule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframesRule.prototype.findRule = function findRule(select) {
|
||||||
|
if (arguments.length === 0) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'findRule', 'CSSKeyframesRule');
|
||||||
|
}
|
||||||
|
|
||||||
|
var normalizedSelect = this._normalizeKeyText(select);
|
||||||
|
|
||||||
|
// Iterate backwards to find the last matching rule
|
||||||
|
for (var i = this.cssRules.length - 1; i >= 0; i--) {
|
||||||
|
var rule = this.cssRules[i];
|
||||||
|
if (this._normalizeKeyText(rule.keyText) === normalizedSelect) {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes keyframe selector text for comparison.
|
||||||
|
* Handles "from" -> "0%" and "to" -> "100%" conversions and trims whitespace.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} keyText - The keyframe selector text to normalize
|
||||||
|
* @return {string} The normalized keyframe selector text
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframesRule.prototype._normalizeKeyText = function _normalizeKeyText(keyText) {
|
||||||
|
if (!keyText) return '';
|
||||||
|
|
||||||
|
var normalized = keyText.toString().trim().toLowerCase();
|
||||||
|
|
||||||
|
// Convert keywords to percentages for comparison
|
||||||
|
if (normalized === 'from') {
|
||||||
|
return '0%';
|
||||||
|
} else if (normalized === 'to') {
|
||||||
|
return '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes CSSKeyframesRule iterable over its cssRules.
|
||||||
|
* Allows for...of loops and other iterable methods.
|
||||||
|
*/
|
||||||
|
if (typeof Symbol !== 'undefined' && Symbol.iterator) {
|
||||||
|
CSSOM.CSSKeyframesRule.prototype[Symbol.iterator] = function() {
|
||||||
|
var index = 0;
|
||||||
|
var cssRules = this.cssRules;
|
||||||
|
|
||||||
|
return {
|
||||||
|
next: function() {
|
||||||
|
if (index < cssRules.length) {
|
||||||
|
return { value: cssRules[index++], done: false };
|
||||||
|
} else {
|
||||||
|
return { done: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds indexed getters for direct access to cssRules by index.
|
||||||
|
* This enables rule[0], rule[1], etc. access patterns.
|
||||||
|
* Works in environments where Proxy is not available (like jsdom).
|
||||||
|
*/
|
||||||
|
CSSOM.CSSKeyframesRule.prototype._setupIndexedAccess = function() {
|
||||||
|
// Remove any existing indexed properties
|
||||||
|
for (var i = 0; i < 1000; i++) { // reasonable upper limit
|
||||||
|
if (this.hasOwnProperty(i)) {
|
||||||
|
delete this[i];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add indexed getters for current cssRules
|
||||||
|
for (var i = 0; i < this.cssRules.length; i++) {
|
||||||
|
(function(index) {
|
||||||
|
Object.defineProperty(this, index, {
|
||||||
|
get: function() {
|
||||||
|
return this.cssRules[index];
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
}.call(this, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update length property
|
||||||
|
Object.defineProperty(this, 'length', {
|
||||||
|
get: function() {
|
||||||
|
return this.cssRules.length;
|
||||||
|
},
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSKeyframesRule = CSSOM.CSSKeyframesRule;
|
||||||
|
///CommonJS
|
||||||
49
web/node_modules/@acemir/cssom/lib/CSSLayerBlockRule.js
generated
vendored
Normal file
49
web/node_modules/@acemir/cssom/lib/CSSLayerBlockRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-cascade-5/#csslayerblockrule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSLayerBlockRule = function CSSLayerBlockRule() {
|
||||||
|
CSSOM.CSSGroupingRule.call(this);
|
||||||
|
this.name = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSLayerBlockRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
||||||
|
CSSOM.CSSLayerBlockRule.prototype.constructor = CSSOM.CSSLayerBlockRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSLayerBlockRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSLayerBlockRule.prototype, "type", {
|
||||||
|
value: 18,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperties(CSSOM.CSSLayerBlockRule.prototype, {
|
||||||
|
cssText: {
|
||||||
|
get: function () {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@layer" + (this.name ? " " + this.name : "") + values;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSLayerBlockRule = CSSOM.CSSLayerBlockRule;
|
||||||
|
///CommonJS
|
||||||
36
web/node_modules/@acemir/cssom/lib/CSSLayerStatementRule.js
generated
vendored
Normal file
36
web/node_modules/@acemir/cssom/lib/CSSLayerStatementRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-cascade-5/#csslayerstatementrule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSLayerStatementRule = function CSSLayerStatementRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.nameList = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSLayerStatementRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSLayerStatementRule.prototype.constructor = CSSOM.CSSLayerStatementRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSLayerStatementRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSLayerStatementRule.prototype, "type", {
|
||||||
|
value: 0,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperties(CSSOM.CSSLayerStatementRule.prototype, {
|
||||||
|
cssText: {
|
||||||
|
get: function () {
|
||||||
|
return "@layer " + this.nameList.join(", ") + ";";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSLayerStatementRule = CSSOM.CSSLayerStatementRule;
|
||||||
|
///CommonJS
|
||||||
74
web/node_modules/@acemir/cssom/lib/CSSMediaRule.js
generated
vendored
Normal file
74
web/node_modules/@acemir/cssom/lib/CSSMediaRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
CSSConditionRule: require("./CSSConditionRule").CSSConditionRule,
|
||||||
|
MediaList: require("./MediaList").MediaList
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#cssmediarule
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSMediaRule = function CSSMediaRule() {
|
||||||
|
CSSOM.CSSConditionRule.call(this);
|
||||||
|
this.__media = new CSSOM.MediaList();
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSMediaRule.prototype = Object.create(CSSOM.CSSConditionRule.prototype);
|
||||||
|
CSSOM.CSSMediaRule.prototype.constructor = CSSOM.CSSMediaRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSMediaRule, CSSOM.CSSConditionRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSMediaRule.prototype, "type", {
|
||||||
|
value: 4,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// https://opensource.apple.com/source/WebCore/WebCore-7611.1.21.161.3/css/CSSMediaRule.cpp
|
||||||
|
Object.defineProperties(CSSOM.CSSMediaRule.prototype, {
|
||||||
|
"media": {
|
||||||
|
get: function() {
|
||||||
|
return this.__media;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__media.mediaText = value;
|
||||||
|
} else {
|
||||||
|
this.__media = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true
|
||||||
|
},
|
||||||
|
"conditionText": {
|
||||||
|
get: function() {
|
||||||
|
return this.media.mediaText;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cssText": {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@media " + this.media.mediaText + values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSMediaRule = CSSOM.CSSMediaRule;
|
||||||
|
///CommonJS
|
||||||
103
web/node_modules/@acemir/cssom/lib/CSSNamespaceRule.js
generated
vendored
Normal file
103
web/node_modules/@acemir/cssom/lib/CSSNamespaceRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSStyleSheet: require("./CSSStyleSheet").CSSStyleSheet
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/cssom/#the-cssnamespacerule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSNamespaceRule = function CSSNamespaceRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.__prefix = "";
|
||||||
|
this.__namespaceURI = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSNamespaceRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSNamespaceRule.prototype.constructor = CSSOM.CSSNamespaceRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSNamespaceRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "type", {
|
||||||
|
value: 10,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
return "@namespace" + (this.prefix && " " + this.prefix) + " url(\"" + this.namespaceURI + "\");";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "prefix", {
|
||||||
|
get: function() {
|
||||||
|
return this.__prefix;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "namespaceURI", {
|
||||||
|
get: function() {
|
||||||
|
return this.__namespaceURI;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NON-STANDARD
|
||||||
|
* Rule text parser.
|
||||||
|
* @param {string} cssText
|
||||||
|
*/
|
||||||
|
Object.defineProperty(CSSOM.CSSNamespaceRule.prototype, "parse", {
|
||||||
|
value: function(cssText) {
|
||||||
|
var newPrefix = "";
|
||||||
|
var newNamespaceURI = "";
|
||||||
|
|
||||||
|
// Remove @namespace and trim
|
||||||
|
var text = cssText.trim();
|
||||||
|
if (text.indexOf('@namespace') === 0) {
|
||||||
|
text = text.slice('@namespace'.length).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing semicolon if present
|
||||||
|
if (text.charAt(text.length - 1) === ';') {
|
||||||
|
text = text.slice(0, -1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex to match valid namespace syntax:
|
||||||
|
// 1. [optional prefix] url("...") or [optional prefix] url('...') or [optional prefix] url() or [optional prefix] url(unquoted)
|
||||||
|
// 2. [optional prefix] "..." or [optional prefix] '...'
|
||||||
|
// The prefix must be a valid CSS identifier (letters, digits, hyphens, underscores, starting with letter or underscore)
|
||||||
|
var re = /^(?:([a-zA-Z_][a-zA-Z0-9_-]*)\s+)?(?:url\(\s*(?:(['"])(.*?)\2\s*|([^)]*?))\s*\)|(['"])(.*?)\5)$/;
|
||||||
|
var match = text.match(re);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
// If prefix is present
|
||||||
|
if (match[1]) {
|
||||||
|
newPrefix = match[1];
|
||||||
|
}
|
||||||
|
// If url(...) form with quotes
|
||||||
|
if (typeof match[3] !== "undefined") {
|
||||||
|
newNamespaceURI = match[3];
|
||||||
|
}
|
||||||
|
// If url(...) form without quotes
|
||||||
|
else if (typeof match[4] !== "undefined") {
|
||||||
|
newNamespaceURI = match[4].trim();
|
||||||
|
}
|
||||||
|
// If quoted string form
|
||||||
|
else if (typeof match[6] !== "undefined") {
|
||||||
|
newNamespaceURI = match[6];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__prefix = newPrefix;
|
||||||
|
this.__namespaceURI = newNamespaceURI;
|
||||||
|
} else {
|
||||||
|
throw new DOMException("Invalid @namespace rule", "InvalidStateError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSNamespaceRule = CSSOM.CSSNamespaceRule;
|
||||||
|
///CommonJS
|
||||||
56
web/node_modules/@acemir/cssom/lib/CSSNestedDeclarations.js
generated
vendored
Normal file
56
web/node_modules/@acemir/cssom/lib/CSSNestedDeclarations.js
generated
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSStyleDeclaration: require('./CSSStyleDeclaration').CSSStyleDeclaration
|
||||||
|
};
|
||||||
|
// Use cssstyle if available
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-nesting-1/
|
||||||
|
*/
|
||||||
|
CSSOM.CSSNestedDeclarations = function CSSNestedDeclarations() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.__style = new CSSOM.CSSStyleDeclaration();
|
||||||
|
this.__style.parentRule = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSNestedDeclarations.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSNestedDeclarations.prototype.constructor = CSSOM.CSSNestedDeclarations;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSNestedDeclarations, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "type", {
|
||||||
|
value: 0,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "style", {
|
||||||
|
get: function() {
|
||||||
|
return this.__style;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__style.cssText = value;
|
||||||
|
} else {
|
||||||
|
this.__style = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSNestedDeclarations.prototype, "cssText", {
|
||||||
|
get: function () {
|
||||||
|
return this.style.cssText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSNestedDeclarations = CSSOM.CSSNestedDeclarations;
|
||||||
|
///CommonJS
|
||||||
58
web/node_modules/@acemir/cssom/lib/CSSOM.js
generated
vendored
Normal file
58
web/node_modules/@acemir/cssom/lib/CSSOM.js
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
var CSSOM = {
|
||||||
|
/**
|
||||||
|
* Creates and configures a new CSSOM instance with the specified options.
|
||||||
|
*
|
||||||
|
* @param {Object} opts - Configuration options for the CSSOM instance
|
||||||
|
* @param {Object} [opts.globalObject] - Optional global object to be assigned to CSSOM objects prototype
|
||||||
|
* @returns {Object} A new CSSOM instance with the applied configuration
|
||||||
|
* @description
|
||||||
|
* This method creates a new instance of CSSOM and optionally
|
||||||
|
* configures CSSStyleSheet with a global object reference. When a globalObject is provided
|
||||||
|
* and CSSStyleSheet exists on the instance, it creates a new CSSStyleSheet constructor
|
||||||
|
* using a factory function and assigns the globalObject to its prototype's __globalObject property.
|
||||||
|
*/
|
||||||
|
setup: function (opts) {
|
||||||
|
var instance = Object.create(this);
|
||||||
|
if (opts.globalObject) {
|
||||||
|
if (instance.CSSStyleSheet) {
|
||||||
|
var factoryCSSStyleSheet = createFunctionFactory(instance.CSSStyleSheet);
|
||||||
|
var CSSStyleSheet = factoryCSSStyleSheet();
|
||||||
|
CSSStyleSheet.prototype.__globalObject = opts.globalObject;
|
||||||
|
|
||||||
|
instance.CSSStyleSheet = CSSStyleSheet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function createFunctionFactory(fn) {
|
||||||
|
return function() {
|
||||||
|
// Create a new function that delegates to the original
|
||||||
|
var newFn = function() {
|
||||||
|
return fn.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy prototype chain
|
||||||
|
Object.setPrototypeOf(newFn, Object.getPrototypeOf(fn));
|
||||||
|
|
||||||
|
// Copy own properties
|
||||||
|
for (var key in fn) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(fn, key)) {
|
||||||
|
newFn[key] = fn[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone the .prototype object for constructor-like behavior
|
||||||
|
if (fn.prototype) {
|
||||||
|
newFn.prototype = Object.create(fn.prototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFn;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
module.exports = CSSOM;
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
125
web/node_modules/@acemir/cssom/lib/CSSPageRule.js
generated
vendored
Normal file
125
web/node_modules/@acemir/cssom/lib/CSSPageRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
};
|
||||||
|
var regexPatterns = require("./regexPatterns").regexPatterns;
|
||||||
|
// Use cssstyle if available
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/cssom/#the-csspagerule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSPageRule = function CSSPageRule() {
|
||||||
|
CSSOM.CSSGroupingRule.call(this);
|
||||||
|
this.__style = new CSSOM.CSSStyleDeclaration();
|
||||||
|
this.__style.parentRule = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSPageRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
||||||
|
CSSOM.CSSPageRule.prototype.constructor = CSSOM.CSSPageRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSPageRule, CSSOM.CSSGroupingRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPageRule.prototype, "type", {
|
||||||
|
value: 6,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPageRule.prototype, "selectorText", {
|
||||||
|
get: function() {
|
||||||
|
return this.__selectorText;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
var trimmedValue = value.trim();
|
||||||
|
|
||||||
|
// Empty selector is valid for @page
|
||||||
|
if (trimmedValue === '') {
|
||||||
|
this.__selectorText = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var atPageRuleSelectorRegExp = regexPatterns.atPageRuleSelectorRegExp;
|
||||||
|
var cssCustomIdentifierRegExp = regexPatterns.cssCustomIdentifierRegExp;
|
||||||
|
var match = trimmedValue.match(atPageRuleSelectorRegExp);
|
||||||
|
if (match) {
|
||||||
|
var pageName = match[1] || '';
|
||||||
|
var pseudoPages = match[2] || '';
|
||||||
|
|
||||||
|
// Validate page name if present
|
||||||
|
if (pageName) {
|
||||||
|
// Page name can be an identifier or a string
|
||||||
|
if (!cssCustomIdentifierRegExp.test(pageName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate pseudo-pages if present
|
||||||
|
if (pseudoPages) {
|
||||||
|
var pseudos = pseudoPages.split(':').filter(function(p) { return p; });
|
||||||
|
var validPseudos = ['left', 'right', 'first', 'blank'];
|
||||||
|
var allValid = true;
|
||||||
|
for (var j = 0; j < pseudos.length; j++) {
|
||||||
|
if (validPseudos.indexOf(pseudos[j].toLowerCase()) === -1) {
|
||||||
|
allValid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allValid) {
|
||||||
|
return; // Invalid pseudo-page, do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__selectorText = pageName + pseudoPages.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPageRule.prototype, "style", {
|
||||||
|
get: function() {
|
||||||
|
return this.__style;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__style.cssText = value;
|
||||||
|
} else {
|
||||||
|
this.__style = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPageRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
this.style.cssText && valuesArr.push(this.style.cssText);
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
} else {
|
||||||
|
values = " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
||||||
|
}
|
||||||
|
return "@page" + (this.selectorText ? " " + this.selectorText : "") + values;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSPageRule = CSSOM.CSSPageRule;
|
||||||
|
///CommonJS
|
||||||
122
web/node_modules/@acemir/cssom/lib/CSSPropertyRule.js
generated
vendored
Normal file
122
web/node_modules/@acemir/cssom/lib/CSSPropertyRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.css-houdini.org/css-properties-values-api/#the-css-property-rule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSPropertyRule = function CSSPropertyRule() {
|
||||||
|
CSSOM.CSSRule.call(this);
|
||||||
|
this.__name = "";
|
||||||
|
this.__syntax = "";
|
||||||
|
this.__inherits = false;
|
||||||
|
this.__initialValue = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSPropertyRule.prototype = Object.create(CSSOM.CSSRule.prototype);
|
||||||
|
CSSOM.CSSPropertyRule.prototype.constructor = CSSOM.CSSPropertyRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSPropertyRule, CSSOM.CSSRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "type", {
|
||||||
|
value: 0,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var text = "@property " + this.name + " {";
|
||||||
|
if (this.syntax !== "") {
|
||||||
|
text += " syntax: \"" + this.syntax.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + "\";";
|
||||||
|
}
|
||||||
|
text += " inherits: " + (this.inherits ? "true" : "false") + ";";
|
||||||
|
if (this.initialValue !== null) {
|
||||||
|
text += " initial-value: " + this.initialValue + ";";
|
||||||
|
}
|
||||||
|
text += " }";
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "name", {
|
||||||
|
get: function() {
|
||||||
|
return this.__name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "syntax", {
|
||||||
|
get: function() {
|
||||||
|
return this.__syntax;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "inherits", {
|
||||||
|
get: function() {
|
||||||
|
return this.__inherits;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "initialValue", {
|
||||||
|
get: function() {
|
||||||
|
return this.__initialValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NON-STANDARD
|
||||||
|
* Rule text parser.
|
||||||
|
* @param {string} cssText
|
||||||
|
* @returns {boolean} True if the rule is valid and was parsed successfully
|
||||||
|
*/
|
||||||
|
Object.defineProperty(CSSOM.CSSPropertyRule.prototype, "parse", {
|
||||||
|
value: function(cssText) {
|
||||||
|
// Extract the name from "@property <name> { ... }"
|
||||||
|
var match = cssText.match(/@property\s+(--[^\s{]+)\s*\{([^]*)\}/);
|
||||||
|
if (!match) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__name = match[1];
|
||||||
|
var bodyText = match[2];
|
||||||
|
|
||||||
|
// Parse syntax descriptor (REQUIRED)
|
||||||
|
var syntaxMatch = bodyText.match(/syntax\s*:\s*(['"])([^]*?)\1\s*;/);
|
||||||
|
if (!syntaxMatch) {
|
||||||
|
return false; // syntax is required
|
||||||
|
}
|
||||||
|
this.__syntax = syntaxMatch[2];
|
||||||
|
|
||||||
|
// Syntax cannot be empty
|
||||||
|
if (this.__syntax === "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse inherits descriptor (REQUIRED)
|
||||||
|
var inheritsMatch = bodyText.match(/inherits\s*:\s*(true|false)\s*;/);
|
||||||
|
if (!inheritsMatch) {
|
||||||
|
return false; // inherits is required
|
||||||
|
}
|
||||||
|
this.__inherits = inheritsMatch[1] === "true";
|
||||||
|
|
||||||
|
// Parse initial-value descriptor (OPTIONAL, but required if syntax is not "*")
|
||||||
|
var initialValueMatch = bodyText.match(/initial-value\s*:\s*([^;]+);/);
|
||||||
|
if (initialValueMatch) {
|
||||||
|
this.__initialValue = initialValueMatch[1].trim();
|
||||||
|
} else {
|
||||||
|
// If syntax is not "*", initial-value is required
|
||||||
|
if (this.__syntax !== "*") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Successfully parsed
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSPropertyRule = CSSOM.CSSPropertyRule;
|
||||||
|
///CommonJS
|
||||||
92
web/node_modules/@acemir/cssom/lib/CSSRule.js
generated
vendored
Normal file
92
web/node_modules/@acemir/cssom/lib/CSSRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#the-cssrule-interface
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSRule = function CSSRule() {
|
||||||
|
this.__parentRule = null;
|
||||||
|
this.__parentStyleSheet = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSRule.UNKNOWN_RULE = 0; // obsolete
|
||||||
|
CSSOM.CSSRule.STYLE_RULE = 1;
|
||||||
|
CSSOM.CSSRule.CHARSET_RULE = 2; // obsolete
|
||||||
|
CSSOM.CSSRule.IMPORT_RULE = 3;
|
||||||
|
CSSOM.CSSRule.MEDIA_RULE = 4;
|
||||||
|
CSSOM.CSSRule.FONT_FACE_RULE = 5;
|
||||||
|
CSSOM.CSSRule.PAGE_RULE = 6;
|
||||||
|
CSSOM.CSSRule.KEYFRAMES_RULE = 7;
|
||||||
|
CSSOM.CSSRule.KEYFRAME_RULE = 8;
|
||||||
|
CSSOM.CSSRule.MARGIN_RULE = 9;
|
||||||
|
CSSOM.CSSRule.NAMESPACE_RULE = 10;
|
||||||
|
CSSOM.CSSRule.COUNTER_STYLE_RULE = 11;
|
||||||
|
CSSOM.CSSRule.SUPPORTS_RULE = 12;
|
||||||
|
CSSOM.CSSRule.DOCUMENT_RULE = 13;
|
||||||
|
CSSOM.CSSRule.FONT_FEATURE_VALUES_RULE = 14;
|
||||||
|
CSSOM.CSSRule.VIEWPORT_RULE = 15;
|
||||||
|
CSSOM.CSSRule.REGION_STYLE_RULE = 16;
|
||||||
|
CSSOM.CSSRule.CONTAINER_RULE = 17;
|
||||||
|
CSSOM.CSSRule.LAYER_BLOCK_RULE = 18;
|
||||||
|
CSSOM.CSSRule.STARTING_STYLE_RULE = 1002;
|
||||||
|
|
||||||
|
Object.defineProperties(CSSOM.CSSRule.prototype, {
|
||||||
|
|
||||||
|
constructor: { value: CSSOM.CSSRule },
|
||||||
|
|
||||||
|
cssRule: {
|
||||||
|
value: "",
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true
|
||||||
|
},
|
||||||
|
|
||||||
|
cssText: {
|
||||||
|
get: function() {
|
||||||
|
// Default getter: subclasses should override this
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
set: function(cssText) {
|
||||||
|
return cssText;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
parentRule: {
|
||||||
|
get: function() {
|
||||||
|
return this.__parentRule
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
parentStyleSheet: {
|
||||||
|
get: function() {
|
||||||
|
return this.__parentStyleSheet
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
UNKNOWN_RULE: { value: 0, enumerable: true }, // obsolet
|
||||||
|
STYLE_RULE: { value: 1, enumerable: true },
|
||||||
|
CHARSET_RULE: { value: 2, enumerable: true }, // obsolet
|
||||||
|
IMPORT_RULE: { value: 3, enumerable: true },
|
||||||
|
MEDIA_RULE: { value: 4, enumerable: true },
|
||||||
|
FONT_FACE_RULE: { value: 5, enumerable: true },
|
||||||
|
PAGE_RULE: { value: 6, enumerable: true },
|
||||||
|
KEYFRAMES_RULE: { value: 7, enumerable: true },
|
||||||
|
KEYFRAME_RULE: { value: 8, enumerable: true },
|
||||||
|
MARGIN_RULE: { value: 9, enumerable: true },
|
||||||
|
NAMESPACE_RULE: { value: 10, enumerable: true },
|
||||||
|
COUNTER_STYLE_RULE: { value: 11, enumerable: true },
|
||||||
|
SUPPORTS_RULE: { value: 12, enumerable: true },
|
||||||
|
DOCUMENT_RULE: { value: 13, enumerable: true },
|
||||||
|
FONT_FEATURE_VALUES_RULE: { value: 14, enumerable: true },
|
||||||
|
VIEWPORT_RULE: { value: 15, enumerable: true },
|
||||||
|
REGION_STYLE_RULE: { value: 16, enumerable: true },
|
||||||
|
CONTAINER_RULE: { value: 17, enumerable: true },
|
||||||
|
LAYER_BLOCK_RULE: { value: 18, enumerable: true },
|
||||||
|
STARTING_STYLE_RULE: { value: 1002, enumerable: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSRule = CSSOM.CSSRule;
|
||||||
|
///CommonJS
|
||||||
26
web/node_modules/@acemir/cssom/lib/CSSRuleList.js
generated
vendored
Normal file
26
web/node_modules/@acemir/cssom/lib/CSSRuleList.js
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/cssom/#the-cssrulelist-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSRuleList = function CSSRuleList(){
|
||||||
|
var arr = new Array();
|
||||||
|
Object.setPrototypeOf(arr, CSSOM.CSSRuleList.prototype);
|
||||||
|
return arr;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSRuleList.prototype = Object.create(Array.prototype);
|
||||||
|
CSSOM.CSSRuleList.prototype.constructor = CSSOM.CSSRuleList;
|
||||||
|
|
||||||
|
CSSOM.CSSRuleList.prototype.item = function(index) {
|
||||||
|
return this[index] || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSRuleList = CSSOM.CSSRuleList;
|
||||||
|
///CommonJS
|
||||||
61
web/node_modules/@acemir/cssom/lib/CSSScopeRule.js
generated
vendored
Normal file
61
web/node_modules/@acemir/cssom/lib/CSSScopeRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-cascade-6/#cssscoperule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSScopeRule = function CSSScopeRule() {
|
||||||
|
CSSOM.CSSGroupingRule.call(this);
|
||||||
|
this.__start = null;
|
||||||
|
this.__end = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSScopeRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
||||||
|
CSSOM.CSSScopeRule.prototype.constructor = CSSOM.CSSScopeRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSScopeRule, CSSOM.CSSGroupingRule);
|
||||||
|
|
||||||
|
Object.defineProperties(CSSOM.CSSScopeRule.prototype, {
|
||||||
|
type: {
|
||||||
|
value: 0,
|
||||||
|
writable: false,
|
||||||
|
},
|
||||||
|
cssText: {
|
||||||
|
get: function () {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@scope" + (this.start ? " (" + this.start + ")" : "") + (this.end ? " to (" + this.end + ")" : "") + values;
|
||||||
|
},
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
get: function () {
|
||||||
|
return this.__start;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
get: function () {
|
||||||
|
return this.__end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSScopeRule = CSSOM.CSSScopeRule;
|
||||||
|
///CommonJS
|
||||||
52
web/node_modules/@acemir/cssom/lib/CSSStartingStyleRule.js
generated
vendored
Normal file
52
web/node_modules/@acemir/cssom/lib/CSSStartingStyleRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://www.w3.org/TR/shadow-dom/#host-at-rule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStartingStyleRule = function CSSStartingStyleRule() {
|
||||||
|
CSSOM.CSSGroupingRule.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSStartingStyleRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
||||||
|
CSSOM.CSSStartingStyleRule.prototype.constructor = CSSOM.CSSStartingStyleRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSStartingStyleRule, CSSOM.CSSGroupingRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStartingStyleRule.prototype, "type", {
|
||||||
|
value: 1002,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
//CSSOM.CSSStartingStyleRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule;
|
||||||
|
//CSSOM.CSSStartingStyleRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule;
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStartingStyleRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@starting-style" + values;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSStartingStyleRule = CSSOM.CSSStartingStyleRule;
|
||||||
|
///CommonJS
|
||||||
164
web/node_modules/@acemir/cssom/lib/CSSStyleDeclaration.js
generated
vendored
Normal file
164
web/node_modules/@acemir/cssom/lib/CSSStyleDeclaration.js
generated
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {};
|
||||||
|
var regexPatterns = require("./regexPatterns").regexPatterns;
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleDeclaration = function CSSStyleDeclaration(){
|
||||||
|
this.length = 0;
|
||||||
|
this.parentRule = null;
|
||||||
|
|
||||||
|
// NON-STANDARD
|
||||||
|
this._importants = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CSSOM.CSSStyleDeclaration.prototype = {
|
||||||
|
|
||||||
|
constructor: CSSOM.CSSStyleDeclaration,
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue
|
||||||
|
* @return {string} the value of the property if it has been explicitly set for this declaration block.
|
||||||
|
* Returns the empty string if the property has not been set.
|
||||||
|
*/
|
||||||
|
getPropertyValue: function(name) {
|
||||||
|
return this[name] || "";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @param {string} value
|
||||||
|
* @param {string} [priority=null] "important" or null
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty
|
||||||
|
*/
|
||||||
|
setProperty: function(name, value, priority, parseErrorHandler)
|
||||||
|
{
|
||||||
|
// NOTE: Check viability to add a validation for css values or use a dependency like csstree-validator
|
||||||
|
var basicStylePropertyValueValidationRegExp = regexPatterns.basicStylePropertyValueValidationRegExp
|
||||||
|
if (basicStylePropertyValueValidationRegExp.test(value)) {
|
||||||
|
parseErrorHandler && parseErrorHandler('Invalid CSSStyleDeclaration property (name = "' + name + '", value = "' + value + '")');
|
||||||
|
} else if (this[name]) {
|
||||||
|
// Property already exist. Overwrite it.
|
||||||
|
var index = Array.prototype.indexOf.call(this, name);
|
||||||
|
if (index < 0) {
|
||||||
|
this[this.length] = name;
|
||||||
|
this.length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the priority value of the incoming property is "important",
|
||||||
|
// or the value of the existing property is not "important",
|
||||||
|
// then remove the existing property and rewrite it.
|
||||||
|
if (priority || !this._importants[name]) {
|
||||||
|
this.removeProperty(name);
|
||||||
|
this[this.length] = name;
|
||||||
|
this.length++;
|
||||||
|
this[name] = value + '';
|
||||||
|
this._importants[name] = priority;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// New property.
|
||||||
|
this[this.length] = name;
|
||||||
|
this.length++;
|
||||||
|
this[name] = value + '';
|
||||||
|
this._importants[name] = priority;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty
|
||||||
|
* @return {string} the value of the property if it has been explicitly set for this declaration block.
|
||||||
|
* Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property.
|
||||||
|
*/
|
||||||
|
removeProperty: function(name) {
|
||||||
|
if (!(name in this)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
var index = Array.prototype.indexOf.call(this, name);
|
||||||
|
if (index < 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
var prevValue = this[name];
|
||||||
|
this[name] = "";
|
||||||
|
|
||||||
|
// That's what WebKit and Opera do
|
||||||
|
Array.prototype.splice.call(this, index, 1);
|
||||||
|
|
||||||
|
// That's what Firefox does
|
||||||
|
//this[index] = ""
|
||||||
|
|
||||||
|
return prevValue;
|
||||||
|
},
|
||||||
|
|
||||||
|
getPropertyCSSValue: function() {
|
||||||
|
//FIXME
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {String} name
|
||||||
|
*/
|
||||||
|
getPropertyPriority: function(name) {
|
||||||
|
return this._importants[name] || "";
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* element.style.overflow = "auto"
|
||||||
|
* element.style.getPropertyShorthand("overflow-x")
|
||||||
|
* -> "overflow"
|
||||||
|
*/
|
||||||
|
getPropertyShorthand: function() {
|
||||||
|
//FIXME
|
||||||
|
},
|
||||||
|
|
||||||
|
isPropertyImplicit: function() {
|
||||||
|
//FIXME
|
||||||
|
},
|
||||||
|
|
||||||
|
// Doesn't work in IE < 9
|
||||||
|
get cssText(){
|
||||||
|
var properties = [];
|
||||||
|
for (var i=0, length=this.length; i < length; ++i) {
|
||||||
|
var name = this[i];
|
||||||
|
var value = this.getPropertyValue(name);
|
||||||
|
var priority = this.getPropertyPriority(name);
|
||||||
|
if (priority) {
|
||||||
|
priority = " !" + priority;
|
||||||
|
}
|
||||||
|
properties[i] = name + ": " + value + priority + ";";
|
||||||
|
}
|
||||||
|
return properties.join(" ");
|
||||||
|
},
|
||||||
|
|
||||||
|
set cssText(text){
|
||||||
|
var i, name;
|
||||||
|
for (i = this.length; i--;) {
|
||||||
|
name = this[i];
|
||||||
|
this[name] = "";
|
||||||
|
}
|
||||||
|
Array.prototype.splice.call(this, 0, this.length);
|
||||||
|
this._importants = {};
|
||||||
|
|
||||||
|
var dummyRule = CSSOM.parse('#bogus{' + text + '}').cssRules[0].style;
|
||||||
|
var length = dummyRule.length;
|
||||||
|
for (i = 0; i < length; ++i) {
|
||||||
|
name = dummyRule[i];
|
||||||
|
this.setProperty(dummyRule[i], dummyRule.getPropertyValue(name), dummyRule.getPropertyPriority(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSStyleDeclaration = CSSOM.CSSStyleDeclaration;
|
||||||
|
CSSOM.parse = require('./parse').parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleDeclaration.js
|
||||||
|
///CommonJS
|
||||||
109
web/node_modules/@acemir/cssom/lib/CSSStyleRule.js
generated
vendored
Normal file
109
web/node_modules/@acemir/cssom/lib/CSSStyleRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
};
|
||||||
|
var regexPatterns = require("./regexPatterns").regexPatterns;
|
||||||
|
// Use cssstyle if available
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#cssstylerule
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleRule = function CSSStyleRule() {
|
||||||
|
CSSOM.CSSGroupingRule.call(this);
|
||||||
|
this.__selectorText = "";
|
||||||
|
this.__style = new CSSOM.CSSStyleDeclaration();
|
||||||
|
this.__style.parentRule = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSStyleRule.prototype = Object.create(CSSOM.CSSGroupingRule.prototype);
|
||||||
|
CSSOM.CSSStyleRule.prototype.constructor = CSSOM.CSSStyleRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSStyleRule, CSSOM.CSSGroupingRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleRule.prototype, "type", {
|
||||||
|
value: 1,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleRule.prototype, "selectorText", {
|
||||||
|
get: function() {
|
||||||
|
return this.__selectorText;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
// Don't trim if the value ends with a hex escape sequence followed by space
|
||||||
|
// (e.g., ".\31 " where the space is part of the escape terminator)
|
||||||
|
var endsWithHexEscapeRegExp = regexPatterns.endsWithHexEscapeRegExp;
|
||||||
|
var endsWithEscape = endsWithHexEscapeRegExp.test(value);
|
||||||
|
var trimmedValue = endsWithEscape ? value.replace(/\s+$/, ' ').trimStart() : value.trim();
|
||||||
|
|
||||||
|
if (trimmedValue === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Setting invalid selectorText should be ignored
|
||||||
|
// There are some validations already on lib/parse.js
|
||||||
|
// but the same validations should be applied here.
|
||||||
|
// Check if we can move these validation logic to a shared function.
|
||||||
|
|
||||||
|
this.__selectorText = trimmedValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleRule.prototype, "style", {
|
||||||
|
get: function() {
|
||||||
|
return this.__style;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__style.cssText = value;
|
||||||
|
} else {
|
||||||
|
this.__style = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var text;
|
||||||
|
if (this.selectorText) {
|
||||||
|
var values = "";
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
this.style.cssText && valuesArr.push(this.style.cssText);
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
} else {
|
||||||
|
values = " {" + (this.style.cssText ? " " + this.style.cssText : "") + " }";
|
||||||
|
}
|
||||||
|
text = this.selectorText + values;
|
||||||
|
} else {
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSStyleRule = CSSOM.CSSStyleRule;
|
||||||
|
///CommonJS
|
||||||
371
web/node_modules/@acemir/cssom/lib/CSSStyleSheet.js
generated
vendored
Normal file
371
web/node_modules/@acemir/cssom/lib/CSSStyleSheet.js
generated
vendored
Normal file
|
|
@ -0,0 +1,371 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
MediaList: require("./MediaList").MediaList,
|
||||||
|
StyleSheet: require("./StyleSheet").StyleSheet,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSStyleRule: require("./CSSStyleRule").CSSStyleRule,
|
||||||
|
};
|
||||||
|
var errorUtils = require("./errorUtils").errorUtils;
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {CSSStyleSheetInit} [opts] - CSSStyleSheetInit options.
|
||||||
|
* @param {string} [opts.baseURL] - The base URL of the stylesheet.
|
||||||
|
* @param {boolean} [opts.disabled] - The disabled attribute of the stylesheet.
|
||||||
|
* @param {MediaList | string} [opts.media] - The media attribute of the stylesheet.
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleSheet = function CSSStyleSheet(opts) {
|
||||||
|
CSSOM.StyleSheet.call(this);
|
||||||
|
this.__constructed = true;
|
||||||
|
this.__cssRules = new CSSOM.CSSRuleList();
|
||||||
|
this.__ownerRule = null;
|
||||||
|
|
||||||
|
if (opts && typeof opts === "object") {
|
||||||
|
if (opts.baseURL && typeof opts.baseURL === "string") {
|
||||||
|
this.__baseURL = opts.baseURL;
|
||||||
|
}
|
||||||
|
if (opts.media && typeof opts.media === "string") {
|
||||||
|
this.media.mediaText = opts.media;
|
||||||
|
}
|
||||||
|
if (typeof opts.disabled === "boolean") {
|
||||||
|
this.disabled = opts.disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CSSOM.CSSStyleSheet.prototype = Object.create(CSSOM.StyleSheet.prototype);
|
||||||
|
CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSStyleSheet, CSSOM.StyleSheet);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "cssRules", {
|
||||||
|
get: function() {
|
||||||
|
return this.__cssRules;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "rules", {
|
||||||
|
get: function() {
|
||||||
|
return this.__cssRules;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSStyleSheet.prototype, "ownerRule", {
|
||||||
|
get: function() {
|
||||||
|
return this.__ownerRule;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade.
|
||||||
|
*
|
||||||
|
* sheet = new Sheet("body {margin: 0}")
|
||||||
|
* sheet.toString()
|
||||||
|
* -> "body{margin:0;}"
|
||||||
|
* sheet.insertRule("img {border: none}", 0)
|
||||||
|
* -> 0
|
||||||
|
* sheet.toString()
|
||||||
|
* -> "img{border:none;}body{margin:0;}"
|
||||||
|
*
|
||||||
|
* @param {string} rule
|
||||||
|
* @param {number} [index=0]
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
|
||||||
|
* @return {number} The index within the style sheet's rule collection of the newly inserted rule.
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) {
|
||||||
|
if (rule === undefined && index === undefined) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'insertRule', this.constructor.name);
|
||||||
|
}
|
||||||
|
if (index === void 0) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
index = Number(index);
|
||||||
|
if (index < 0) {
|
||||||
|
index = 4294967296 + index;
|
||||||
|
}
|
||||||
|
if (index > this.cssRules.length) {
|
||||||
|
errorUtils.throwIndexError(this, 'insertRule', this.constructor.name, index, this.cssRules.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ruleToParse = String(rule);
|
||||||
|
var parseErrors = [];
|
||||||
|
var parsedSheet = CSSOM.parse(ruleToParse, undefined, function(err) {
|
||||||
|
parseErrors.push(err);
|
||||||
|
} );
|
||||||
|
if (parsedSheet.cssRules.length !== 1) {
|
||||||
|
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
||||||
|
}
|
||||||
|
var cssRule = parsedSheet.cssRules[0];
|
||||||
|
|
||||||
|
// Helper function to find the last index of a specific rule constructor
|
||||||
|
function findLastIndexOfConstructor(rules, constructorName) {
|
||||||
|
for (var i = rules.length - 1; i >= 0; i--) {
|
||||||
|
if (rules[i].constructor.name === constructorName) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to find the first index of a rule that's NOT of specified constructors
|
||||||
|
function findFirstNonConstructorIndex(rules, constructorNames) {
|
||||||
|
for (var i = 0; i < rules.length; i++) {
|
||||||
|
if (constructorNames.indexOf(rules[i].constructor.name) === -1) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rules.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate rule ordering based on CSS specification
|
||||||
|
if (cssRule.constructor.name === 'CSSImportRule') {
|
||||||
|
if (this.__constructed === true) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Can't insert @import rules into a constructed stylesheet.",
|
||||||
|
'SyntaxError');
|
||||||
|
}
|
||||||
|
// @import rules cannot be inserted after @layer rules that already exist
|
||||||
|
// They can only be inserted at the beginning or after other @import rules
|
||||||
|
var firstLayerIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
|
||||||
|
if (firstLayerIndex < this.cssRules.length && this.cssRules[firstLayerIndex].constructor.name === 'CSSLayerStatementRule' && index > firstLayerIndex) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also cannot insert after @namespace or other rules
|
||||||
|
var firstNonImportIndex = findFirstNonConstructorIndex(this.cssRules, ['CSSImportRule']);
|
||||||
|
if (index > firstNonImportIndex && firstNonImportIndex < this.cssRules.length &&
|
||||||
|
this.cssRules[firstNonImportIndex].constructor.name !== 'CSSLayerStatementRule') {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
}
|
||||||
|
} else if (cssRule.constructor.name === 'CSSNamespaceRule') {
|
||||||
|
// @namespace rules can come after @layer and @import, but before any other rules
|
||||||
|
// They cannot come before @import rules
|
||||||
|
var firstImportIndex = -1;
|
||||||
|
for (var i = 0; i < this.cssRules.length; i++) {
|
||||||
|
if (this.cssRules[i].constructor.name === 'CSSImportRule') {
|
||||||
|
firstImportIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var firstNonImportNamespaceIndex = findFirstNonConstructorIndex(this.cssRules, [
|
||||||
|
'CSSLayerStatementRule',
|
||||||
|
'CSSImportRule',
|
||||||
|
'CSSNamespaceRule'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Cannot insert before @import rules
|
||||||
|
if (firstImportIndex !== -1 && index <= firstImportIndex) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot insert if there are already non-special rules
|
||||||
|
if (firstNonImportNamespaceIndex < this.cssRules.length) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
||||||
|
'InvalidStateError');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot insert after other types of rules
|
||||||
|
if (index > firstNonImportNamespaceIndex) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if (cssRule.constructor.name === 'CSSLayerStatementRule') {
|
||||||
|
// @layer statement rules can be inserted anywhere before @import and @namespace
|
||||||
|
// No additional restrictions beyond what's already handled
|
||||||
|
} else {
|
||||||
|
// Any other rule cannot be inserted before @import and @namespace
|
||||||
|
var firstNonSpecialRuleIndex = findFirstNonConstructorIndex(this.cssRules, [
|
||||||
|
'CSSLayerStatementRule',
|
||||||
|
'CSSImportRule',
|
||||||
|
'CSSNamespaceRule'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (index < firstNonSpecialRuleIndex) {
|
||||||
|
errorUtils.throwError(this, 'DOMException',
|
||||||
|
"Failed to execute 'insertRule' on '" + this.constructor.name + "': Failed to insert the rule.",
|
||||||
|
'HierarchyRequestError');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseErrors.filter(function(error) { return !error.isNested; }).length !== 0) {
|
||||||
|
errorUtils.throwParseError(this, 'insertRule', this.constructor.name, ruleToParse, 'SyntaxError');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cssRule.__parentStyleSheet = this;
|
||||||
|
this.cssRules.splice(index, 0, cssRule);
|
||||||
|
return index;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSStyleSheet.prototype.addRule = function(selector, styleBlock, index) {
|
||||||
|
if (index === void 0) {
|
||||||
|
index = this.cssRules.length;
|
||||||
|
}
|
||||||
|
this.insertRule(selector + "{" + styleBlock + "}", index);
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to delete a rule from the style sheet.
|
||||||
|
*
|
||||||
|
* sheet = new Sheet("img{border:none} body{margin:0}")
|
||||||
|
* sheet.toString()
|
||||||
|
* -> "img{border:none;}body{margin:0;}"
|
||||||
|
* sheet.deleteRule(0)
|
||||||
|
* sheet.toString()
|
||||||
|
* -> "body{margin:0;}"
|
||||||
|
*
|
||||||
|
* @param {number} index within the style sheet's rule list of the rule to remove.
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-deleteRule
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) {
|
||||||
|
if (index === undefined) {
|
||||||
|
errorUtils.throwMissingArguments(this, 'deleteRule', this.constructor.name);
|
||||||
|
}
|
||||||
|
index = Number(index);
|
||||||
|
if (index < 0) {
|
||||||
|
index = 4294967296 + index;
|
||||||
|
}
|
||||||
|
if (index >= this.cssRules.length) {
|
||||||
|
errorUtils.throwIndexError(this, 'deleteRule', this.constructor.name, index, this.cssRules.length);
|
||||||
|
}
|
||||||
|
if (this.cssRules[index]) {
|
||||||
|
if (this.cssRules[index].constructor.name == "CSSNamespaceRule") {
|
||||||
|
var shouldContinue = this.cssRules.every(function (rule) {
|
||||||
|
return ['CSSImportRule','CSSLayerStatementRule','CSSNamespaceRule'].indexOf(rule.constructor.name) !== -1
|
||||||
|
});
|
||||||
|
if (!shouldContinue) {
|
||||||
|
errorUtils.throwError(this, 'DOMException', "Failed to execute 'deleteRule' on '" + this.constructor.name + "': Failed to delete rule.", "InvalidStateError");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.cssRules[index].constructor.name == "CSSImportRule") {
|
||||||
|
this.cssRules[index].styleSheet.__parentStyleSheet = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cssRules[index].__parentStyleSheet = null;
|
||||||
|
}
|
||||||
|
this.cssRules.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSStyleSheet.prototype.removeRule = function(index) {
|
||||||
|
if (index === void 0) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
this.deleteRule(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the rules of a {@link CSSStyleSheet}
|
||||||
|
*
|
||||||
|
* @returns a promise
|
||||||
|
* @see https://www.w3.org/TR/cssom-1/#dom-cssstylesheet-replace
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleSheet.prototype.replace = function(text) {
|
||||||
|
var _Promise;
|
||||||
|
if (this.__globalObject && this.__globalObject['Promise']) {
|
||||||
|
_Promise = this.__globalObject['Promise'];
|
||||||
|
} else {
|
||||||
|
_Promise = Promise;
|
||||||
|
}
|
||||||
|
var _setTimeout;
|
||||||
|
if (this.__globalObject && this.__globalObject['setTimeout']) {
|
||||||
|
_setTimeout = this.__globalObject['setTimeout'];
|
||||||
|
} else {
|
||||||
|
_setTimeout = setTimeout;
|
||||||
|
}
|
||||||
|
var sheet = this;
|
||||||
|
return new _Promise(function (resolve, reject) {
|
||||||
|
// If the constructed flag is not set, or the disallow modification flag is set, throw a NotAllowedError DOMException.
|
||||||
|
if (!sheet.__constructed || sheet.__disallowModification) {
|
||||||
|
reject(errorUtils.createError(sheet, 'DOMException',
|
||||||
|
"Failed to execute 'replaceSync' on '" + sheet.constructor.name + "': Not allowed.",
|
||||||
|
'NotAllowedError'));
|
||||||
|
}
|
||||||
|
// Set the disallow modification flag.
|
||||||
|
sheet.__disallowModification = true;
|
||||||
|
|
||||||
|
// In parallel, do these steps:
|
||||||
|
_setTimeout(function() {
|
||||||
|
// Let rules be the result of running parse a stylesheet's contents from text.
|
||||||
|
var rules = new CSSOM.CSSRuleList();
|
||||||
|
CSSOM.parse(text, { styleSheet: sheet, cssRules: rules });
|
||||||
|
// If rules contains one or more @import rules, remove those rules from rules.
|
||||||
|
var i = 0;
|
||||||
|
while (i < rules.length) {
|
||||||
|
if (rules[i].constructor.name === 'CSSImportRule') {
|
||||||
|
rules.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set sheet's CSS rules to rules.
|
||||||
|
sheet.__cssRules.splice.apply(sheet.__cssRules, [0, sheet.__cssRules.length].concat(rules));
|
||||||
|
// Unset sheet’s disallow modification flag.
|
||||||
|
delete sheet.__disallowModification;
|
||||||
|
// Resolve promise with sheet.
|
||||||
|
resolve(sheet);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously replaces the rules of a {@link CSSStyleSheet}
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/cssom-1/#dom-cssstylesheet-replacesync
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleSheet.prototype.replaceSync = function(text) {
|
||||||
|
var sheet = this;
|
||||||
|
// If the constructed flag is not set, or the disallow modification flag is set, throw a NotAllowedError DOMException.
|
||||||
|
if (!sheet.__constructed || sheet.__disallowModification) {
|
||||||
|
errorUtils.throwError(sheet, 'DOMException',
|
||||||
|
"Failed to execute 'replaceSync' on '" + sheet.constructor.name + "': Not allowed.",
|
||||||
|
'NotAllowedError');
|
||||||
|
}
|
||||||
|
// Let rules be the result of running parse a stylesheet's contents from text.
|
||||||
|
var rules = new CSSOM.CSSRuleList();
|
||||||
|
CSSOM.parse(text, { styleSheet: sheet, cssRules: rules });
|
||||||
|
// If rules contains one or more @import rules, remove those rules from rules.
|
||||||
|
var i = 0;
|
||||||
|
while (i < rules.length) {
|
||||||
|
if (rules[i].constructor.name === 'CSSImportRule') {
|
||||||
|
rules.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set sheet's CSS rules to rules.
|
||||||
|
sheet.__cssRules.splice.apply(sheet.__cssRules, [0, sheet.__cssRules.length].concat(rules));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NON-STANDARD
|
||||||
|
* @return {string} serialize stylesheet
|
||||||
|
*/
|
||||||
|
CSSOM.CSSStyleSheet.prototype.toString = function() {
|
||||||
|
var result = "";
|
||||||
|
var rules = this.cssRules;
|
||||||
|
for (var i=0; i<rules.length; i++) {
|
||||||
|
result += rules[i].cssText + "\n";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSStyleSheet = CSSOM.CSSStyleSheet;
|
||||||
|
CSSOM.parse = require('./parse').parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleSheet.js
|
||||||
|
///CommonJS
|
||||||
48
web/node_modules/@acemir/cssom/lib/CSSSupportsRule.js
generated
vendored
Normal file
48
web/node_modules/@acemir/cssom/lib/CSSSupportsRule.js
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSRuleList: require("./CSSRuleList").CSSRuleList,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
CSSConditionRule: require("./CSSConditionRule").CSSConditionRule
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface
|
||||||
|
*/
|
||||||
|
CSSOM.CSSSupportsRule = function CSSSupportsRule() {
|
||||||
|
CSSOM.CSSConditionRule.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSSupportsRule.prototype = Object.create(CSSOM.CSSConditionRule.prototype);
|
||||||
|
CSSOM.CSSSupportsRule.prototype.constructor = CSSOM.CSSSupportsRule;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSSupportsRule, CSSOM.CSSConditionRule);
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "type", {
|
||||||
|
value: 12,
|
||||||
|
writable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(CSSOM.CSSSupportsRule.prototype, "cssText", {
|
||||||
|
get: function() {
|
||||||
|
var values = "";
|
||||||
|
var valuesArr = [" {"];
|
||||||
|
if (this.cssRules.length) {
|
||||||
|
valuesArr.push(this.cssRules.reduce(function(acc, rule){
|
||||||
|
if (rule.cssText !== "") {
|
||||||
|
acc.push(rule.cssText);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []).join("\n "));
|
||||||
|
}
|
||||||
|
values = valuesArr.join("\n ") + "\n}";
|
||||||
|
return "@supports " + this.conditionText + values;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSSupportsRule = CSSOM.CSSSupportsRule;
|
||||||
|
///CommonJS
|
||||||
43
web/node_modules/@acemir/cssom/lib/CSSValue.js
generated
vendored
Normal file
43
web/node_modules/@acemir/cssom/lib/CSSValue.js
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
|
||||||
|
*
|
||||||
|
* TODO: add if needed
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValue = function CSSValue() {
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSValue.prototype = {
|
||||||
|
constructor: CSSOM.CSSValue,
|
||||||
|
|
||||||
|
// @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue
|
||||||
|
set cssText(text) {
|
||||||
|
var name = this._getConstructorName();
|
||||||
|
|
||||||
|
throw new Error('DOMException: property "cssText" of "' + name + '" is readonly and can not be replaced with "' + text + '"!');
|
||||||
|
},
|
||||||
|
|
||||||
|
get cssText() {
|
||||||
|
var name = this._getConstructorName();
|
||||||
|
|
||||||
|
throw new Error('getter "cssText" of "' + name + '" is not implemented!');
|
||||||
|
},
|
||||||
|
|
||||||
|
_getConstructorName: function() {
|
||||||
|
var s = this.constructor.toString(),
|
||||||
|
c = s.match(/function\s([^\(]+)/),
|
||||||
|
name = c[1];
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSValue = CSSOM.CSSValue;
|
||||||
|
///CommonJS
|
||||||
346
web/node_modules/@acemir/cssom/lib/CSSValueExpression.js
generated
vendored
Normal file
346
web/node_modules/@acemir/cssom/lib/CSSValueExpression.js
generated
vendored
Normal file
|
|
@ -0,0 +1,346 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSValue: require('./CSSValue').CSSValue
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).aspx
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValueExpression = function CSSValueExpression(token, idx) {
|
||||||
|
this._token = token;
|
||||||
|
this._idx = idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.CSSValueExpression.prototype = Object.create(CSSOM.CSSValue.prototype);
|
||||||
|
CSSOM.CSSValueExpression.prototype.constructor = CSSOM.CSSValueExpression;
|
||||||
|
|
||||||
|
Object.setPrototypeOf(CSSOM.CSSValueExpression, CSSOM.CSSValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse css expression() value
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
* - error:
|
||||||
|
* or
|
||||||
|
* - idx:
|
||||||
|
* - expression:
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* .selector {
|
||||||
|
* zoom: expression(documentElement.clientWidth > 1000 ? '1000px' : 'auto');
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValueExpression.prototype.parse = function() {
|
||||||
|
var token = this._token,
|
||||||
|
idx = this._idx;
|
||||||
|
|
||||||
|
var character = '',
|
||||||
|
expression = '',
|
||||||
|
error = '',
|
||||||
|
info,
|
||||||
|
paren = [];
|
||||||
|
|
||||||
|
|
||||||
|
for (; ; ++idx) {
|
||||||
|
character = token.charAt(idx);
|
||||||
|
|
||||||
|
// end of token
|
||||||
|
if (character === '') {
|
||||||
|
error = 'css expression error: unfinished expression!';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(character) {
|
||||||
|
case '(':
|
||||||
|
paren.push(character);
|
||||||
|
expression += character;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ')':
|
||||||
|
paren.pop(character);
|
||||||
|
expression += character;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '/':
|
||||||
|
if ((info = this._parseJSComment(token, idx))) { // comment?
|
||||||
|
if (info.error) {
|
||||||
|
error = 'css expression error: unfinished comment in expression!';
|
||||||
|
} else {
|
||||||
|
idx = info.idx;
|
||||||
|
// ignore the comment
|
||||||
|
}
|
||||||
|
} else if ((info = this._parseJSRexExp(token, idx))) { // regexp
|
||||||
|
idx = info.idx;
|
||||||
|
expression += info.text;
|
||||||
|
} else { // other
|
||||||
|
expression += character;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "'":
|
||||||
|
case '"':
|
||||||
|
info = this._parseJSString(token, idx, character);
|
||||||
|
if (info) { // string
|
||||||
|
idx = info.idx;
|
||||||
|
expression += info.text;
|
||||||
|
} else {
|
||||||
|
expression += character;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
expression += character;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// end of expression
|
||||||
|
if (paren.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret;
|
||||||
|
if (error) {
|
||||||
|
ret = {
|
||||||
|
error: error
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
ret = {
|
||||||
|
idx: idx,
|
||||||
|
expression: expression
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return {Object|false}
|
||||||
|
* - idx:
|
||||||
|
* - text:
|
||||||
|
* or
|
||||||
|
* - error:
|
||||||
|
* or
|
||||||
|
* false
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValueExpression.prototype._parseJSComment = function(token, idx) {
|
||||||
|
var nextChar = token.charAt(idx + 1),
|
||||||
|
text;
|
||||||
|
|
||||||
|
if (nextChar === '/' || nextChar === '*') {
|
||||||
|
var startIdx = idx,
|
||||||
|
endIdx,
|
||||||
|
commentEndChar;
|
||||||
|
|
||||||
|
if (nextChar === '/') { // line comment
|
||||||
|
commentEndChar = '\n';
|
||||||
|
} else if (nextChar === '*') { // block comment
|
||||||
|
commentEndChar = '*/';
|
||||||
|
}
|
||||||
|
|
||||||
|
endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1);
|
||||||
|
if (endIdx !== -1) {
|
||||||
|
endIdx = endIdx + commentEndChar.length - 1;
|
||||||
|
text = token.substring(idx, endIdx + 1);
|
||||||
|
return {
|
||||||
|
idx: endIdx,
|
||||||
|
text: text
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
var error = 'css expression error: unfinished comment in expression!';
|
||||||
|
return {
|
||||||
|
error: error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return {Object|false}
|
||||||
|
* - idx:
|
||||||
|
* - text:
|
||||||
|
* or
|
||||||
|
* false
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValueExpression.prototype._parseJSString = function(token, idx, sep) {
|
||||||
|
var endIdx = this._findMatchedIdx(token, idx, sep),
|
||||||
|
text;
|
||||||
|
|
||||||
|
if (endIdx === -1) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
text = token.substring(idx, endIdx + sep.length);
|
||||||
|
|
||||||
|
return {
|
||||||
|
idx: endIdx,
|
||||||
|
text: text
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse regexp in css expression
|
||||||
|
*
|
||||||
|
* @return {Object|false}
|
||||||
|
* - idx:
|
||||||
|
* - regExp:
|
||||||
|
* or
|
||||||
|
* false
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
all legal RegExp
|
||||||
|
|
||||||
|
/a/
|
||||||
|
(/a/)
|
||||||
|
[/a/]
|
||||||
|
[12, /a/]
|
||||||
|
|
||||||
|
!/a/
|
||||||
|
|
||||||
|
+/a/
|
||||||
|
-/a/
|
||||||
|
* /a/
|
||||||
|
/ /a/
|
||||||
|
%/a/
|
||||||
|
|
||||||
|
===/a/
|
||||||
|
!==/a/
|
||||||
|
==/a/
|
||||||
|
!=/a/
|
||||||
|
>/a/
|
||||||
|
>=/a/
|
||||||
|
</a/
|
||||||
|
<=/a/
|
||||||
|
|
||||||
|
&/a/
|
||||||
|
|/a/
|
||||||
|
^/a/
|
||||||
|
~/a/
|
||||||
|
<</a/
|
||||||
|
>>/a/
|
||||||
|
>>>/a/
|
||||||
|
|
||||||
|
&&/a/
|
||||||
|
||/a/
|
||||||
|
?/a/
|
||||||
|
=/a/
|
||||||
|
,/a/
|
||||||
|
|
||||||
|
delete /a/
|
||||||
|
in /a/
|
||||||
|
instanceof /a/
|
||||||
|
new /a/
|
||||||
|
typeof /a/
|
||||||
|
void /a/
|
||||||
|
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValueExpression.prototype._parseJSRexExp = function(token, idx) {
|
||||||
|
var before = token.substring(0, idx).replace(/\s+$/, ""),
|
||||||
|
legalRegx = [
|
||||||
|
/^$/,
|
||||||
|
/\($/,
|
||||||
|
/\[$/,
|
||||||
|
/\!$/,
|
||||||
|
/\+$/,
|
||||||
|
/\-$/,
|
||||||
|
/\*$/,
|
||||||
|
/\/\s+/,
|
||||||
|
/\%$/,
|
||||||
|
/\=$/,
|
||||||
|
/\>$/,
|
||||||
|
/<$/,
|
||||||
|
/\&$/,
|
||||||
|
/\|$/,
|
||||||
|
/\^$/,
|
||||||
|
/\~$/,
|
||||||
|
/\?$/,
|
||||||
|
/\,$/,
|
||||||
|
/delete$/,
|
||||||
|
/in$/,
|
||||||
|
/instanceof$/,
|
||||||
|
/new$/,
|
||||||
|
/typeof$/,
|
||||||
|
/void$/
|
||||||
|
];
|
||||||
|
|
||||||
|
var isLegal = legalRegx.some(function(reg) {
|
||||||
|
return reg.test(before);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isLegal) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
var sep = '/';
|
||||||
|
|
||||||
|
// same logic as string
|
||||||
|
return this._parseJSString(token, idx, sep);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* find next sep(same line) index in `token`
|
||||||
|
*
|
||||||
|
* @return {Number}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
CSSOM.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep) {
|
||||||
|
var startIdx = idx,
|
||||||
|
endIdx;
|
||||||
|
|
||||||
|
var NOT_FOUND = -1;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
endIdx = token.indexOf(sep, startIdx + 1);
|
||||||
|
|
||||||
|
if (endIdx === -1) { // not found
|
||||||
|
endIdx = NOT_FOUND;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
var text = token.substring(idx + 1, endIdx),
|
||||||
|
matched = text.match(/\\+$/);
|
||||||
|
if (!matched || matched[0] % 2 === 0) { // not escaped
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
startIdx = endIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// boundary must be in the same line(js sting or regexp)
|
||||||
|
var nextNewLineIdx = token.indexOf('\n', idx + 1);
|
||||||
|
if (nextNewLineIdx < endIdx) {
|
||||||
|
endIdx = NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return endIdx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.CSSValueExpression = CSSOM.CSSValueExpression;
|
||||||
|
///CommonJS
|
||||||
62
web/node_modules/@acemir/cssom/lib/MatcherList.js
generated
vendored
Normal file
62
web/node_modules/@acemir/cssom/lib/MatcherList.js
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see https://developer.mozilla.org/en/CSS/@-moz-document
|
||||||
|
*/
|
||||||
|
CSSOM.MatcherList = function MatcherList(){
|
||||||
|
this.length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.MatcherList.prototype = {
|
||||||
|
|
||||||
|
constructor: CSSOM.MatcherList,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
get matcherText() {
|
||||||
|
return Array.prototype.join.call(this, ", ");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
set matcherText(value) {
|
||||||
|
// just a temporary solution, actually it may be wrong by just split the value with ',', because a url can include ','.
|
||||||
|
var values = value.split(",");
|
||||||
|
var length = this.length = values.length;
|
||||||
|
for (var i=0; i<length; i++) {
|
||||||
|
this[i] = values[i].trim();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} matcher
|
||||||
|
*/
|
||||||
|
appendMatcher: function(matcher) {
|
||||||
|
if (Array.prototype.indexOf.call(this, matcher) === -1) {
|
||||||
|
this[this.length] = matcher;
|
||||||
|
this.length++;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} matcher
|
||||||
|
*/
|
||||||
|
deleteMatcher: function(matcher) {
|
||||||
|
var index = Array.prototype.indexOf.call(this, matcher);
|
||||||
|
if (index !== -1) {
|
||||||
|
Array.prototype.splice.call(this, index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.MatcherList = CSSOM.MatcherList;
|
||||||
|
///CommonJS
|
||||||
78
web/node_modules/@acemir/cssom/lib/MediaList.js
generated
vendored
Normal file
78
web/node_modules/@acemir/cssom/lib/MediaList.js
generated
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#the-medialist-interface
|
||||||
|
*/
|
||||||
|
CSSOM.MediaList = function MediaList(){
|
||||||
|
this.length = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
CSSOM.MediaList.prototype = {
|
||||||
|
|
||||||
|
constructor: CSSOM.MediaList,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
get mediaText() {
|
||||||
|
return Array.prototype.join.call(this, ", ");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
set mediaText(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
var values = value.split(",").filter(function(text){
|
||||||
|
return !!text;
|
||||||
|
});
|
||||||
|
var length = this.length = values.length;
|
||||||
|
for (var i=0; i<length; i++) {
|
||||||
|
this[i] = values[i].trim();
|
||||||
|
}
|
||||||
|
} else if (value === null) {
|
||||||
|
var length = this.length;
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
delete this[i];
|
||||||
|
}
|
||||||
|
this.length = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} medium
|
||||||
|
*/
|
||||||
|
appendMedium: function(medium) {
|
||||||
|
if (Array.prototype.indexOf.call(this, medium) === -1) {
|
||||||
|
this[this.length] = medium;
|
||||||
|
this.length++;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} medium
|
||||||
|
*/
|
||||||
|
deleteMedium: function(medium) {
|
||||||
|
var index = Array.prototype.indexOf.call(this, medium);
|
||||||
|
if (index !== -1) {
|
||||||
|
Array.prototype.splice.call(this, index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
item: function(index) {
|
||||||
|
return this[index] || null;
|
||||||
|
},
|
||||||
|
|
||||||
|
toString: function() {
|
||||||
|
return this.mediaText;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.MediaList = CSSOM.MediaList;
|
||||||
|
///CommonJS
|
||||||
62
web/node_modules/@acemir/cssom/lib/StyleSheet.js
generated
vendored
Normal file
62
web/node_modules/@acemir/cssom/lib/StyleSheet.js
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
MediaList: require("./MediaList").MediaList
|
||||||
|
};
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface
|
||||||
|
*/
|
||||||
|
CSSOM.StyleSheet = function StyleSheet() {
|
||||||
|
this.__href = null;
|
||||||
|
this.__ownerNode = null;
|
||||||
|
this.__title = null;
|
||||||
|
this.__media = new CSSOM.MediaList();
|
||||||
|
this.__parentStyleSheet = null;
|
||||||
|
this.disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperties(CSSOM.StyleSheet.prototype, {
|
||||||
|
type: {
|
||||||
|
get: function() {
|
||||||
|
return "text/css";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
href: {
|
||||||
|
get: function() {
|
||||||
|
return this.__href;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ownerNode: {
|
||||||
|
get: function() {
|
||||||
|
return this.__ownerNode;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
get: function() {
|
||||||
|
return this.__title;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
media: {
|
||||||
|
get: function() {
|
||||||
|
return this.__media;
|
||||||
|
},
|
||||||
|
set: function(value) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
this.__media.mediaText = value;
|
||||||
|
} else {
|
||||||
|
this.__media = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parentStyleSheet: {
|
||||||
|
get: function() {
|
||||||
|
return this.__parentStyleSheet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.StyleSheet = CSSOM.StyleSheet;
|
||||||
|
///CommonJS
|
||||||
105
web/node_modules/@acemir/cssom/lib/clone.js
generated
vendored
Normal file
105
web/node_modules/@acemir/cssom/lib/clone.js
generated
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
//.CommonJS
|
||||||
|
var CSSOM = {
|
||||||
|
CSSStyleSheet: require("./CSSStyleSheet").CSSStyleSheet,
|
||||||
|
CSSRule: require("./CSSRule").CSSRule,
|
||||||
|
CSSNestedDeclarations: require("./CSSNestedDeclarations").CSSNestedDeclarations,
|
||||||
|
CSSStyleRule: require("./CSSStyleRule").CSSStyleRule,
|
||||||
|
CSSGroupingRule: require("./CSSGroupingRule").CSSGroupingRule,
|
||||||
|
CSSConditionRule: require("./CSSConditionRule").CSSConditionRule,
|
||||||
|
CSSMediaRule: require("./CSSMediaRule").CSSMediaRule,
|
||||||
|
CSSContainerRule: require("./CSSContainerRule").CSSContainerRule,
|
||||||
|
CSSSupportsRule: require("./CSSSupportsRule").CSSSupportsRule,
|
||||||
|
CSSStyleDeclaration: require("./CSSStyleDeclaration").CSSStyleDeclaration,
|
||||||
|
CSSKeyframeRule: require('./CSSKeyframeRule').CSSKeyframeRule,
|
||||||
|
CSSKeyframesRule: require('./CSSKeyframesRule').CSSKeyframesRule,
|
||||||
|
CSSScopeRule: require('./CSSScopeRule').CSSScopeRule,
|
||||||
|
CSSLayerBlockRule: require('./CSSLayerBlockRule').CSSLayerBlockRule,
|
||||||
|
CSSLayerStatementRule: require('./CSSLayerStatementRule').CSSLayerStatementRule
|
||||||
|
};
|
||||||
|
// Use cssstyle if available
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
///CommonJS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produces a deep copy of stylesheet — the instance variables of stylesheet are copied recursively.
|
||||||
|
* @param {CSSStyleSheet|CSSOM.CSSStyleSheet} stylesheet
|
||||||
|
* @nosideeffects
|
||||||
|
* @return {CSSOM.CSSStyleSheet}
|
||||||
|
*/
|
||||||
|
CSSOM.clone = function clone(stylesheet) {
|
||||||
|
|
||||||
|
var cloned = new CSSOM.CSSStyleSheet();
|
||||||
|
|
||||||
|
var rules = stylesheet.cssRules;
|
||||||
|
if (!rules) {
|
||||||
|
return cloned;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0, rulesLength = rules.length; i < rulesLength; i++) {
|
||||||
|
var rule = rules[i];
|
||||||
|
var ruleClone = cloned.cssRules[i] = new rule.constructor();
|
||||||
|
|
||||||
|
var style = rule.style;
|
||||||
|
if (style) {
|
||||||
|
var styleClone = ruleClone.style = new CSSOM.CSSStyleDeclaration();
|
||||||
|
for (var j = 0, styleLength = style.length; j < styleLength; j++) {
|
||||||
|
var name = styleClone[j] = style[j];
|
||||||
|
styleClone[name] = style[name];
|
||||||
|
styleClone._importants[name] = style.getPropertyPriority(name);
|
||||||
|
}
|
||||||
|
styleClone.length = style.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('keyText')) {
|
||||||
|
ruleClone.keyText = rule.keyText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('selectorText')) {
|
||||||
|
ruleClone.selectorText = rule.selectorText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('mediaText')) {
|
||||||
|
ruleClone.mediaText = rule.mediaText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('supportsText')) {
|
||||||
|
ruleClone.supports = rule.supports;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('conditionText')) {
|
||||||
|
ruleClone.conditionText = rule.conditionText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('layerName')) {
|
||||||
|
ruleClone.layerName = rule.layerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('href')) {
|
||||||
|
ruleClone.href = rule.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('name')) {
|
||||||
|
ruleClone.name = rule.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('nameList')) {
|
||||||
|
ruleClone.nameList = rule.nameList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.hasOwnProperty('cssRules')) {
|
||||||
|
ruleClone.cssRules = clone(rule).cssRules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloned;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.clone = CSSOM.clone;
|
||||||
|
///CommonJS
|
||||||
5
web/node_modules/@acemir/cssom/lib/cssstyleTryCatchBlock.js
generated
vendored
Normal file
5
web/node_modules/@acemir/cssom/lib/cssstyleTryCatchBlock.js
generated
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
try {
|
||||||
|
CSSOM.CSSStyleDeclaration = require("cssstyle").CSSStyleDeclaration;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
119
web/node_modules/@acemir/cssom/lib/errorUtils.js
generated
vendored
Normal file
119
web/node_modules/@acemir/cssom/lib/errorUtils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
// Utility functions for CSSOM error handling
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the appropriate error constructor from the global object context.
|
||||||
|
* Tries to find the error constructor from parentStyleSheet.__globalObject,
|
||||||
|
* then from __globalObject, then falls back to the native constructor.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The CSSOM object (rule, stylesheet, etc.)
|
||||||
|
* @param {string} errorType - The error type ('TypeError', 'RangeError', 'DOMException', etc.)
|
||||||
|
* @return {Function} The error constructor
|
||||||
|
*/
|
||||||
|
function getErrorConstructor(context, errorType) {
|
||||||
|
// Try parentStyleSheet.__globalObject first
|
||||||
|
if (context.parentStyleSheet && context.parentStyleSheet.__globalObject && context.parentStyleSheet.__globalObject[errorType]) {
|
||||||
|
return context.parentStyleSheet.__globalObject[errorType];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try __parentStyleSheet (alternative naming)
|
||||||
|
if (context.__parentStyleSheet && context.__parentStyleSheet.__globalObject && context.__parentStyleSheet.__globalObject[errorType]) {
|
||||||
|
return context.__parentStyleSheet.__globalObject[errorType];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try __globalObject on the context itself
|
||||||
|
if (context.__globalObject && context.__globalObject[errorType]) {
|
||||||
|
return context.__globalObject[errorType];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to native constructor
|
||||||
|
return (typeof global !== 'undefined' && global[errorType]) ||
|
||||||
|
(typeof window !== 'undefined' && window[errorType]) ||
|
||||||
|
eval(errorType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an appropriate error with context-aware constructor.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The CSSOM object (rule, stylesheet, etc.)
|
||||||
|
* @param {string} errorType - The error type ('TypeError', 'RangeError', 'DOMException', etc.)
|
||||||
|
* @param {string} message - The error message
|
||||||
|
* @param {string} [name] - Optional name for DOMException
|
||||||
|
*/
|
||||||
|
function createError(context, errorType, message, name) {
|
||||||
|
var ErrorConstructor = getErrorConstructor(context, errorType);
|
||||||
|
return new ErrorConstructor(message, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and throws an appropriate error with context-aware constructor.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The CSSOM object (rule, stylesheet, etc.)
|
||||||
|
* @param {string} errorType - The error type ('TypeError', 'RangeError', 'DOMException', etc.)
|
||||||
|
* @param {string} message - The error message
|
||||||
|
* @param {string} [name] - Optional name for DOMException
|
||||||
|
*/
|
||||||
|
function throwError(context, errorType, message, name) {
|
||||||
|
throw createError(context, errorType, message, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a TypeError for missing required arguments.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The CSSOM object
|
||||||
|
* @param {string} methodName - The method name (e.g., 'appendRule')
|
||||||
|
* @param {string} objectName - The object name (e.g., 'CSSKeyframesRule')
|
||||||
|
* @param {number} [required=1] - Number of required arguments
|
||||||
|
* @param {number} [provided=0] - Number of provided arguments
|
||||||
|
*/
|
||||||
|
function throwMissingArguments(context, methodName, objectName, required, provided) {
|
||||||
|
required = required || 1;
|
||||||
|
provided = provided || 0;
|
||||||
|
var message = "Failed to execute '" + methodName + "' on '" + objectName + "': " +
|
||||||
|
required + " argument" + (required > 1 ? "s" : "") + " required, but only " +
|
||||||
|
provided + " present.";
|
||||||
|
throwError(context, 'TypeError', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a DOMException for parse errors.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The CSSOM object
|
||||||
|
* @param {string} methodName - The method name
|
||||||
|
* @param {string} objectName - The object name
|
||||||
|
* @param {string} rule - The rule that failed to parse
|
||||||
|
* @param {string} [name='SyntaxError'] - The DOMException name
|
||||||
|
*/
|
||||||
|
function throwParseError(context, methodName, objectName, rule, name) {
|
||||||
|
var message = "Failed to execute '" + methodName + "' on '" + objectName + "': " +
|
||||||
|
"Failed to parse the rule '" + rule + "'.";
|
||||||
|
throwError(context, 'DOMException', message, name || 'SyntaxError');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws a DOMException for index errors.
|
||||||
|
*
|
||||||
|
* @param {Object} context - The CSSOM object
|
||||||
|
* @param {string} methodName - The method name
|
||||||
|
* @param {string} objectName - The object name
|
||||||
|
* @param {number} index - The invalid index
|
||||||
|
* @param {number} maxIndex - The maximum valid index
|
||||||
|
* @param {string} [name='IndexSizeError'] - The DOMException name
|
||||||
|
*/
|
||||||
|
function throwIndexError(context, methodName, objectName, index, maxIndex, name) {
|
||||||
|
var message = "Failed to execute '" + methodName + "' on '" + objectName + "': " +
|
||||||
|
"The index provided (" + index + ") is larger than the maximum index (" + maxIndex + ").";
|
||||||
|
throwError(context, 'DOMException', message, name || 'IndexSizeError');
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorUtils = {
|
||||||
|
createError: createError,
|
||||||
|
getErrorConstructor: getErrorConstructor,
|
||||||
|
throwError: throwError,
|
||||||
|
throwMissingArguments: throwMissingArguments,
|
||||||
|
throwParseError: throwParseError,
|
||||||
|
throwIndexError: throwIndexError
|
||||||
|
};
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.errorUtils = errorUtils;
|
||||||
|
///CommonJS
|
||||||
42
web/node_modules/@acemir/cssom/lib/index.js
generated
vendored
Normal file
42
web/node_modules/@acemir/cssom/lib/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports.setup = require('./CSSOM').setup;
|
||||||
|
|
||||||
|
require('./errorUtils');
|
||||||
|
require("./regexPatterns")
|
||||||
|
|
||||||
|
exports.CSSStyleDeclaration = require('./CSSStyleDeclaration').CSSStyleDeclaration;
|
||||||
|
|
||||||
|
require('./cssstyleTryCatchBlock');
|
||||||
|
|
||||||
|
exports.CSSRule = require('./CSSRule').CSSRule;
|
||||||
|
exports.CSSRuleList = require('./CSSRuleList').CSSRuleList;
|
||||||
|
exports.CSSNestedDeclarations = require('./CSSNestedDeclarations').CSSNestedDeclarations;
|
||||||
|
exports.CSSGroupingRule = require('./CSSGroupingRule').CSSGroupingRule;
|
||||||
|
exports.CSSCounterStyleRule = require('./CSSCounterStyleRule').CSSCounterStyleRule;
|
||||||
|
exports.CSSPropertyRule = require('./CSSPropertyRule').CSSPropertyRule;
|
||||||
|
exports.CSSConditionRule = require('./CSSConditionRule').CSSConditionRule;
|
||||||
|
exports.CSSStyleRule = require('./CSSStyleRule').CSSStyleRule;
|
||||||
|
exports.MediaList = require('./MediaList').MediaList;
|
||||||
|
exports.CSSMediaRule = require('./CSSMediaRule').CSSMediaRule;
|
||||||
|
exports.CSSContainerRule = require('./CSSContainerRule').CSSContainerRule;
|
||||||
|
exports.CSSSupportsRule = require('./CSSSupportsRule').CSSSupportsRule;
|
||||||
|
exports.CSSImportRule = require('./CSSImportRule').CSSImportRule;
|
||||||
|
exports.CSSNamespaceRule = require('./CSSNamespaceRule').CSSNamespaceRule;
|
||||||
|
exports.CSSFontFaceRule = require('./CSSFontFaceRule').CSSFontFaceRule;
|
||||||
|
exports.CSSHostRule = require('./CSSHostRule').CSSHostRule;
|
||||||
|
exports.CSSStartingStyleRule = require('./CSSStartingStyleRule').CSSStartingStyleRule;
|
||||||
|
exports.StyleSheet = require('./StyleSheet').StyleSheet;
|
||||||
|
exports.CSSStyleSheet = require('./CSSStyleSheet').CSSStyleSheet;
|
||||||
|
exports.CSSKeyframesRule = require('./CSSKeyframesRule').CSSKeyframesRule;
|
||||||
|
exports.CSSKeyframeRule = require('./CSSKeyframeRule').CSSKeyframeRule;
|
||||||
|
exports.MatcherList = require('./MatcherList').MatcherList;
|
||||||
|
exports.CSSDocumentRule = require('./CSSDocumentRule').CSSDocumentRule;
|
||||||
|
exports.CSSValue = require('./CSSValue').CSSValue;
|
||||||
|
exports.CSSValueExpression = require('./CSSValueExpression').CSSValueExpression;
|
||||||
|
exports.CSSScopeRule = require('./CSSScopeRule').CSSScopeRule;
|
||||||
|
exports.CSSLayerBlockRule = require('./CSSLayerBlockRule').CSSLayerBlockRule;
|
||||||
|
exports.CSSLayerStatementRule = require('./CSSLayerStatementRule').CSSLayerStatementRule;
|
||||||
|
exports.CSSPageRule = require('./CSSPageRule').CSSPageRule;
|
||||||
|
exports.parse = require('./parse').parse;
|
||||||
|
exports.clone = require('./clone').clone;
|
||||||
3332
web/node_modules/@acemir/cssom/lib/parse.js
generated
vendored
Normal file
3332
web/node_modules/@acemir/cssom/lib/parse.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
162
web/node_modules/@acemir/cssom/lib/regexPatterns.js
generated
vendored
Normal file
162
web/node_modules/@acemir/cssom/lib/regexPatterns.js
generated
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
// Shared regex patterns for CSS parsing and validation
|
||||||
|
// These patterns are compiled once and reused across multiple files for better performance
|
||||||
|
|
||||||
|
// Regex patterns for CSS parsing
|
||||||
|
var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g; // Match @keyframes and vendor-prefixed @keyframes
|
||||||
|
var beforeRulePortionRegExp = /{(?!.*{)|}(?!.*})|;(?!.*;)|\*\/(?!.*\*\/)/g; // Match the closest allowed character (a opening or closing brace, a semicolon or a comment ending) before the rule
|
||||||
|
var beforeRuleValidationRegExp = /^[\s{};]*(\*\/\s*)?$/; // Match that the portion before the rule is empty or contains only whitespace, semicolons, opening/closing braces, and optionally a comment ending (*/) followed by whitespace
|
||||||
|
var forwardRuleValidationRegExp = /(?:\s|\/\*|\{|\()/; // Match that the rule is followed by any whitespace, a opening comment, a condition opening parenthesis or a opening brace
|
||||||
|
var forwardImportRuleValidationRegExp = /(?:\s|\/\*|'|")/; // Match that the rule is followed by any whitespace, an opening comment, a single quote or double quote
|
||||||
|
var forwardRuleClosingBraceRegExp = /{[^{}]*}|}/; // Finds the next closing brace of a rule block
|
||||||
|
var forwardRuleSemicolonAndOpeningBraceRegExp = /^.*?({|;)/; // Finds the next semicolon or opening brace after the at-rule
|
||||||
|
|
||||||
|
// Regex patterns for CSS selector validation and parsing
|
||||||
|
var cssCustomIdentifierRegExp = /^(-?[_a-zA-Z]+(\.[_a-zA-Z]+)*[_a-zA-Z0-9-]*)$/; // Validates a css custom identifier
|
||||||
|
var startsWithCombinatorRegExp = /^\s*[>+~]/; // Checks if a selector starts with a CSS combinator (>, +, ~)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse `@page` selectorText for page name and pseudo-pages
|
||||||
|
* Valid formats:
|
||||||
|
* - (empty - no name, no pseudo-page)
|
||||||
|
* - `:left`, `:right`, `:first`, `:blank` (pseudo-page only)
|
||||||
|
* - `named` (named page only)
|
||||||
|
* - `named:first` (named page with single pseudo-page)
|
||||||
|
* - `named:first:left` (named page with multiple pseudo-pages)
|
||||||
|
*/
|
||||||
|
var atPageRuleSelectorRegExp = /^([^\s:]+)?((?::\w+)*)$/; // Validates @page rule selectors
|
||||||
|
|
||||||
|
// Regex patterns for CSSImportRule parsing
|
||||||
|
var layerRegExp = /layer\(([^)]*)\)/; // Matches layer() function in @import
|
||||||
|
var layerRuleNameRegExp = /^(-?[_a-zA-Z]+(\.[_a-zA-Z]+)*[_a-zA-Z0-9-]*)$/; // Validates layer name (same as custom identifier)
|
||||||
|
var doubleOrMoreSpacesRegExp = /\s{2,}/g; // Matches two or more consecutive whitespace characters
|
||||||
|
|
||||||
|
|
||||||
|
// Regex patterns for CSS escape sequences and identifiers
|
||||||
|
var startsWithHexEscapeRegExp = /^\\[0-9a-fA-F]/; // Checks if escape sequence starts with hex escape
|
||||||
|
var identStartCharRegExp = /[a-zA-Z_\u00A0-\uFFFF]/; // Valid identifier start character
|
||||||
|
var identCharRegExp = /^[a-zA-Z0-9_\-\u00A0-\uFFFF\\]/; // Valid identifier character
|
||||||
|
var specialCharsNeedEscapeRegExp = /[!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~\s]/; // Characters that need escaping
|
||||||
|
var combinatorOrSeparatorRegExp = /[\s>+~,()]/; // Selector boundaries and combinators
|
||||||
|
var afterHexEscapeSeparatorRegExp = /[\s>+~,(){}\[\]]/; // Characters that separate after hex escape
|
||||||
|
var trailingSpaceSeparatorRegExp = /[\s>+~,(){}]/; // Characters that allow trailing space
|
||||||
|
var endsWithHexEscapeRegExp = /\\[0-9a-fA-F]{1,6}\s+$/; // Matches selector ending with hex escape + space(s)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression to detect invalid characters in the value portion of a CSS style declaration.
|
||||||
|
*
|
||||||
|
* This regex matches a colon (:) that is not inside parentheses and not inside single or double quotes.
|
||||||
|
* It is used to ensure that the value part of a CSS property does not contain unexpected colons,
|
||||||
|
* which would indicate a malformed declaration (e.g., "color: foo:bar;" is invalid).
|
||||||
|
*
|
||||||
|
* The negative lookahead `(?![^(]*\))` ensures that the colon is not followed by a closing
|
||||||
|
* parenthesis without encountering an opening parenthesis, effectively ignoring colons inside
|
||||||
|
* function-like values (e.g., `url(data:image/png;base64,...)`).
|
||||||
|
*
|
||||||
|
* The lookahead `(?=(?:[^'"]|'[^']*'|"[^"]*")*$)` ensures that the colon is not inside single or double quotes,
|
||||||
|
* allowing colons within quoted strings (e.g., `content: ":";` or `background: url("foo:bar.png");`).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* - `color: red;` // valid, does not match
|
||||||
|
* - `background: url(data:image/png;base64,...);` // valid, does not match
|
||||||
|
* - `content: ':';` // valid, does not match
|
||||||
|
* - `color: foo:bar;` // invalid, matches
|
||||||
|
*/
|
||||||
|
var basicStylePropertyValueValidationRegExp = /:(?![^(]*\))(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/;
|
||||||
|
|
||||||
|
// Attribute selector pattern: matches attribute-name operator value
|
||||||
|
// Operators: =, ~=, |=, ^=, $=, *=
|
||||||
|
// Rewritten to avoid ReDoS by using greedy match and trimming in JavaScript
|
||||||
|
var attributeSelectorContentRegExp = /^([^\s=~|^$*]+)\s*(~=|\|=|\^=|\$=|\*=|=)\s*(.+)$/;
|
||||||
|
|
||||||
|
// Selector validation patterns
|
||||||
|
var pseudoElementRegExp = /::[a-zA-Z][\w-]*|:(before|after|first-line|first-letter)(?![a-zA-Z0-9_-])/; // Matches pseudo-elements
|
||||||
|
var invalidCombinatorLtGtRegExp = /<>/; // Invalid <> combinator
|
||||||
|
var invalidCombinatorDoubleGtRegExp = />>/; // Invalid >> combinator
|
||||||
|
var consecutiveCombinatorsRegExp = /[>+~]\s*[>+~]/; // Invalid consecutive combinators
|
||||||
|
var invalidSlottedRegExp = /(?:^|[\s>+~,\[])slotted\s*\(/i; // Invalid slotted() without ::
|
||||||
|
var invalidPartRegExp = /(?:^|[\s>+~,\[])part\s*\(/i; // Invalid part() without ::
|
||||||
|
var invalidCueRegExp = /(?:^|[\s>+~,\[])cue\s*\(/i; // Invalid cue() without ::
|
||||||
|
var invalidCueRegionRegExp = /(?:^|[\s>+~,\[])cue-region\s*\(/i; // Invalid cue-region() without ::
|
||||||
|
var invalidNestingPattern = /&(?![.\#\[:>\+~\s])[a-zA-Z]/; // Invalid & followed by type selector
|
||||||
|
var emptyPseudoClassRegExp = /:(?:is|not|where|has)\(\s*\)/; // Empty pseudo-class like :is()
|
||||||
|
var whitespaceNormalizationRegExp = /(['"])(?:\\.|[^\\])*?\1|(\r\n|\r|\n)/g; // Normalize newlines outside quotes
|
||||||
|
var newlineRemovalRegExp = /\n/g; // Remove all newlines
|
||||||
|
var whitespaceAndDotRegExp = /[\s.]/; // Matches whitespace or dot
|
||||||
|
var declarationOrOpenBraceRegExp = /[{;}]/; // Matches declaration separator or open brace
|
||||||
|
var ampersandRegExp = /&/; // Matches nesting selector
|
||||||
|
var hexEscapeSequenceRegExp = /^([0-9a-fA-F]{1,6})[ \t\r\n\f]?/; // Matches hex escape sequence (1-6 hex digits optionally followed by whitespace)
|
||||||
|
var attributeCaseFlagRegExp = /^(.+?)\s+([is])$/i; // Matches case-sensitivity flag at end of attribute value
|
||||||
|
var prependedAmpersandRegExp = /^&\s+[:\\.]/; // Matches prepended ampersand pattern (& followed by space and : or .)
|
||||||
|
var openBraceGlobalRegExp = /{/g; // Matches opening braces (global)
|
||||||
|
var closeBraceGlobalRegExp = /}/g; // Matches closing braces (global)
|
||||||
|
var scopePreludeSplitRegExp = /\s*\)\s*to\s+\(/; // Splits scope prelude by ") to ("
|
||||||
|
var leadingWhitespaceRegExp = /^\s+/; // Matches leading whitespace (used to implement a ES5-compliant alternative to trimStart())
|
||||||
|
var doubleQuoteRegExp = /"/g; // Match all double quotes (for escaping in attribute values)
|
||||||
|
var backslashRegExp = /\\/g; // Match all backslashes (for escaping in attribute values)
|
||||||
|
|
||||||
|
var regexPatterns = {
|
||||||
|
// Parsing patterns
|
||||||
|
atKeyframesRegExp: atKeyframesRegExp,
|
||||||
|
beforeRulePortionRegExp: beforeRulePortionRegExp,
|
||||||
|
beforeRuleValidationRegExp: beforeRuleValidationRegExp,
|
||||||
|
forwardRuleValidationRegExp: forwardRuleValidationRegExp,
|
||||||
|
forwardImportRuleValidationRegExp: forwardImportRuleValidationRegExp,
|
||||||
|
forwardRuleClosingBraceRegExp: forwardRuleClosingBraceRegExp,
|
||||||
|
forwardRuleSemicolonAndOpeningBraceRegExp: forwardRuleSemicolonAndOpeningBraceRegExp,
|
||||||
|
|
||||||
|
// Selector validation patterns
|
||||||
|
cssCustomIdentifierRegExp: cssCustomIdentifierRegExp,
|
||||||
|
startsWithCombinatorRegExp: startsWithCombinatorRegExp,
|
||||||
|
atPageRuleSelectorRegExp: atPageRuleSelectorRegExp,
|
||||||
|
|
||||||
|
// Parsing patterns used in CSSImportRule
|
||||||
|
layerRegExp: layerRegExp,
|
||||||
|
layerRuleNameRegExp: layerRuleNameRegExp,
|
||||||
|
doubleOrMoreSpacesRegExp: doubleOrMoreSpacesRegExp,
|
||||||
|
|
||||||
|
// Escape sequence and identifier patterns
|
||||||
|
startsWithHexEscapeRegExp: startsWithHexEscapeRegExp,
|
||||||
|
identStartCharRegExp: identStartCharRegExp,
|
||||||
|
identCharRegExp: identCharRegExp,
|
||||||
|
specialCharsNeedEscapeRegExp: specialCharsNeedEscapeRegExp,
|
||||||
|
combinatorOrSeparatorRegExp: combinatorOrSeparatorRegExp,
|
||||||
|
afterHexEscapeSeparatorRegExp: afterHexEscapeSeparatorRegExp,
|
||||||
|
trailingSpaceSeparatorRegExp: trailingSpaceSeparatorRegExp,
|
||||||
|
endsWithHexEscapeRegExp: endsWithHexEscapeRegExp,
|
||||||
|
|
||||||
|
// Basic style property value validation
|
||||||
|
basicStylePropertyValueValidationRegExp: basicStylePropertyValueValidationRegExp,
|
||||||
|
|
||||||
|
// Attribute selector patterns
|
||||||
|
attributeSelectorContentRegExp: attributeSelectorContentRegExp,
|
||||||
|
|
||||||
|
// Selector validation patterns
|
||||||
|
pseudoElementRegExp: pseudoElementRegExp,
|
||||||
|
invalidCombinatorLtGtRegExp: invalidCombinatorLtGtRegExp,
|
||||||
|
invalidCombinatorDoubleGtRegExp: invalidCombinatorDoubleGtRegExp,
|
||||||
|
consecutiveCombinatorsRegExp: consecutiveCombinatorsRegExp,
|
||||||
|
invalidSlottedRegExp: invalidSlottedRegExp,
|
||||||
|
invalidPartRegExp: invalidPartRegExp,
|
||||||
|
invalidCueRegExp: invalidCueRegExp,
|
||||||
|
invalidCueRegionRegExp: invalidCueRegionRegExp,
|
||||||
|
invalidNestingPattern: invalidNestingPattern,
|
||||||
|
emptyPseudoClassRegExp: emptyPseudoClassRegExp,
|
||||||
|
whitespaceNormalizationRegExp: whitespaceNormalizationRegExp,
|
||||||
|
newlineRemovalRegExp: newlineRemovalRegExp,
|
||||||
|
whitespaceAndDotRegExp: whitespaceAndDotRegExp,
|
||||||
|
declarationOrOpenBraceRegExp: declarationOrOpenBraceRegExp,
|
||||||
|
ampersandRegExp: ampersandRegExp,
|
||||||
|
hexEscapeSequenceRegExp: hexEscapeSequenceRegExp,
|
||||||
|
attributeCaseFlagRegExp: attributeCaseFlagRegExp,
|
||||||
|
prependedAmpersandRegExp: prependedAmpersandRegExp,
|
||||||
|
openBraceGlobalRegExp: openBraceGlobalRegExp,
|
||||||
|
closeBraceGlobalRegExp: closeBraceGlobalRegExp,
|
||||||
|
scopePreludeSplitRegExp: scopePreludeSplitRegExp,
|
||||||
|
leadingWhitespaceRegExp: leadingWhitespaceRegExp,
|
||||||
|
doubleQuoteRegExp: doubleQuoteRegExp,
|
||||||
|
backslashRegExp: backslashRegExp
|
||||||
|
};
|
||||||
|
|
||||||
|
//.CommonJS
|
||||||
|
exports.regexPatterns = regexPatterns;
|
||||||
|
///CommonJS
|
||||||
32
web/node_modules/@acemir/cssom/package.json
generated
vendored
Normal file
32
web/node_modules/@acemir/cssom/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "@acemir/cssom",
|
||||||
|
"description": "CSS Object Model implementation and CSS parser",
|
||||||
|
"keywords": [
|
||||||
|
"CSS",
|
||||||
|
"CSSOM",
|
||||||
|
"parser",
|
||||||
|
"styleSheet"
|
||||||
|
],
|
||||||
|
"version": "0.9.31",
|
||||||
|
"author": "Nikita Vasilyev <me@elv1s.ru>",
|
||||||
|
"contributors": [
|
||||||
|
"Acemir Sousa Mendes <acemirsm@gmail.com>"
|
||||||
|
],
|
||||||
|
"repository": "acemir/CSSOM",
|
||||||
|
"files": [
|
||||||
|
"lib/",
|
||||||
|
"build/"
|
||||||
|
],
|
||||||
|
"browser": "./build/CSSOM.js",
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"build": "node build.js",
|
||||||
|
"release": "npm run build && changeset publish"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@changesets/changelog-github": "^0.5.2",
|
||||||
|
"@changesets/cli": "^2.29.8",
|
||||||
|
"@changesets/get-release-plan": "^4.0.14"
|
||||||
|
}
|
||||||
|
}
|
||||||
21
web/node_modules/@antfu/install-pkg/LICENSE
generated
vendored
Normal file
21
web/node_modules/@antfu/install-pkg/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Anthony Fu <https://github.com/antfu>
|
||||||
|
|
||||||
|
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.
|
||||||
27
web/node_modules/@antfu/install-pkg/README.md
generated
vendored
Normal file
27
web/node_modules/@antfu/install-pkg/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# install-pkg
|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/@antfu/install-pkg)
|
||||||
|
|
||||||
|
Install package programmatically. Detect package managers automatically (`npm`, `yarn`, `bun` and `pnpm`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm i @antfu/install-pkg
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { installPackage } from '@antfu/install-pkg'
|
||||||
|
|
||||||
|
await installPackage('vite', { silent: true })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
|
||||||
|
<img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg'/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](./LICENSE) License © 2021 [Anthony Fu](https://github.com/antfu)
|
||||||
58
web/node_modules/@antfu/install-pkg/package.json
generated
vendored
Normal file
58
web/node_modules/@antfu/install-pkg/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"name": "@antfu/install-pkg",
|
||||||
|
"type": "module",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"description": "Install package programmatically.",
|
||||||
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": "https://github.com/sponsors/antfu",
|
||||||
|
"homepage": "https://github.com/antfu/install-pkg#readme",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/antfu/install-pkg.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/antfu/install-pkg/issues"
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": {
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"default": "./dist/index.js"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"types": "./dist/index.d.cts",
|
||||||
|
"default": "./dist/index.cjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"module": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"package-manager-detector": "^1.3.0",
|
||||||
|
"tinyexec": "^1.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@antfu/eslint-config": "^4.12.1",
|
||||||
|
"@antfu/ni": "^24.3.0",
|
||||||
|
"@types/node": "^22.15.12",
|
||||||
|
"bumpp": "^10.1.0",
|
||||||
|
"eslint": "^9.26.0",
|
||||||
|
"publint": "^0.3.12",
|
||||||
|
"tsup": "^8.4.0",
|
||||||
|
"tsx": "^4.19.4",
|
||||||
|
"typescript": "^5.8.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nr build --watch",
|
||||||
|
"start": "tsx src/index.ts",
|
||||||
|
"build": "tsup src/index.ts --format cjs,esm --dts --no-splitting",
|
||||||
|
"release": "bumpp --commit --push --tag && pnpm publish",
|
||||||
|
"lint": "eslint ."
|
||||||
|
}
|
||||||
|
}
|
||||||
21
web/node_modules/@asamuzakjp/css-color/LICENSE
generated
vendored
Normal file
21
web/node_modules/@asamuzakjp/css-color/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
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
web/node_modules/@asamuzakjp/css-color/README.md
generated
vendored
Normal file
316
web/node_modules/@asamuzakjp/css-color/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,316 @@
|
||||||
|
# CSS color
|
||||||
|
|
||||||
|
[](https://github.com/asamuzaK/cssColor/actions/workflows/node.js.yml)
|
||||||
|
[](https://github.com/asamuzaK/cssColor/actions/workflows/github-code-scanning/codeql)
|
||||||
|
[](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 = convert.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
|
||||||
72
web/node_modules/@asamuzakjp/css-color/package.json
generated
vendored
Normal file
72
web/node_modules/@asamuzakjp/css-color/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
{
|
||||||
|
"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",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/esm/index.d.ts",
|
||||||
|
"default": "./dist/esm/index.js"
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@csstools/css-calc": "^3.1.1",
|
||||||
|
"@csstools/css-color-parser": "^4.0.2",
|
||||||
|
"@csstools/css-parser-algorithms": "^4.0.0",
|
||||||
|
"@csstools/css-tokenizer": "^4.0.0",
|
||||||
|
"lru-cache": "^11.2.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tanstack/vite-config": "^0.4.3",
|
||||||
|
"@vitest/coverage-istanbul": "^4.0.18",
|
||||||
|
"esbuild": "^0.27.3",
|
||||||
|
"eslint": "^9.39.3",
|
||||||
|
"eslint-plugin-regexp": "^3.0.0",
|
||||||
|
"globals": "^17.3.0",
|
||||||
|
"knip": "^5.85.0",
|
||||||
|
"neostandard": "^0.12.2",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"publint": "^0.3.17",
|
||||||
|
"rimraf": "^6.1.3",
|
||||||
|
"typescript": "^5.9.3",
|
||||||
|
"vite": "^7.3.1",
|
||||||
|
"vitest": "^4.0.18"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@10.30.1",
|
||||||
|
"pnpm": {
|
||||||
|
"onlyBuiltDependencies": [
|
||||||
|
"esbuild",
|
||||||
|
"oxc-resolver",
|
||||||
|
"unrs-resolver"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm run clean && pnpm run test && pnpm run knip && vite build && pnpm run publint",
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||||
|
},
|
||||||
|
"version": "5.0.1"
|
||||||
|
}
|
||||||
30
web/node_modules/@asamuzakjp/css-color/src/index.ts
generated
vendored
Normal file
30
web/node_modules/@asamuzakjp/css-color/src/index.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*!
|
||||||
|
* CSS color - Resolve, parse, convert CSS color.
|
||||||
|
* @license MIT
|
||||||
|
* @copyright asamuzaK (Kazz)
|
||||||
|
* @see {@link https://github.com/asamuzaK/cssColor/blob/main/LICENSE}
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { cssCalc } from './js/css-calc';
|
||||||
|
import { isGradient, resolveGradient } from './js/css-gradient';
|
||||||
|
import { cssVar } from './js/css-var';
|
||||||
|
import {
|
||||||
|
extractDashedIdent,
|
||||||
|
isColor,
|
||||||
|
resolveLengthInPixels,
|
||||||
|
splitValue
|
||||||
|
} from './js/util';
|
||||||
|
|
||||||
|
export { convert } from './js/convert';
|
||||||
|
export { resolve } from './js/resolve';
|
||||||
|
/* utils */
|
||||||
|
export const utils = {
|
||||||
|
cssCalc,
|
||||||
|
cssVar,
|
||||||
|
extractDashedIdent,
|
||||||
|
isColor,
|
||||||
|
isGradient,
|
||||||
|
resolveGradient,
|
||||||
|
resolveLengthInPixels,
|
||||||
|
splitValue
|
||||||
|
};
|
||||||
114
web/node_modules/@asamuzakjp/css-color/src/js/cache.ts
generated
vendored
Normal file
114
web/node_modules/@asamuzakjp/css-color/src/js/cache.ts
generated
vendored
Normal 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;
|
||||||
|
};
|
||||||
3511
web/node_modules/@asamuzakjp/css-color/src/js/color.ts
generated
vendored
Normal file
3511
web/node_modules/@asamuzakjp/css-color/src/js/color.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
31
web/node_modules/@asamuzakjp/css-color/src/js/common.ts
generated
vendored
Normal file
31
web/node_modules/@asamuzakjp/css-color/src/js/common.ts
generated
vendored
Normal 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';
|
||||||
68
web/node_modules/@asamuzakjp/css-color/src/js/constant.ts
generated
vendored
Normal file
68
web/node_modules/@asamuzakjp/css-color/src/js/constant.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
* 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_LIGHT_DARK = 'light-dark(';
|
||||||
|
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_LIGHT_DARK = '^light-dark\\(';
|
||||||
|
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
web/node_modules/@asamuzakjp/css-color/src/js/convert.ts
generated
vendored
Normal file
469
web/node_modules/@asamuzakjp/css-color/src/js/convert.ts
generated
vendored
Normal 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
|
||||||
|
};
|
||||||
955
web/node_modules/@asamuzakjp/css-color/src/js/css-calc.ts
generated
vendored
Normal file
955
web/node_modules/@asamuzakjp/css-color/src/js/css-calc.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,955 @@
|
||||||
|
/**
|
||||||
|
* 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 { resolveLengthInPixels, 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_CALC_NUM = new RegExp(`^calc\\((${NUM})\\)$`);
|
||||||
|
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.sort(this.#dimSum).join(' + ');
|
||||||
|
}
|
||||||
|
if (this.#dimSub.length) {
|
||||||
|
sub = this.sort(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(' ').replace(/\+\s-/g, '- ');
|
||||||
|
} else {
|
||||||
|
resolvedValue = sortedValues.join(' ').replace(/\+\s-/g, '- ');
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
resolvedValue.startsWith('(') &&
|
||||||
|
resolvedValue.endsWith(')') &&
|
||||||
|
resolvedValue.lastIndexOf('(') === 0 &&
|
||||||
|
resolvedValue.indexOf(')') === resolvedValue.length - 1
|
||||||
|
) {
|
||||||
|
resolvedValue = resolvedValue.replace(/^\(/, '').replace(/\)$/, '');
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
if (unit === 'px') {
|
||||||
|
return `${value}${unit}`;
|
||||||
|
}
|
||||||
|
const pixelValue = resolveLengthInPixels(Number(value), unit, opt);
|
||||||
|
if (Number.isFinite(pixelValue)) {
|
||||||
|
return `${roundToPrecision(pixelValue, HEX)}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})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (format === VAL_SPEC) {
|
||||||
|
if (/\s[-+*/]\s/.test(resolvedValue) && !resolvedValue.includes('NaN')) {
|
||||||
|
resolvedValue = serializeCalc(resolvedValue, opt);
|
||||||
|
} else if (REG_FN_CALC_NUM.test(resolvedValue)) {
|
||||||
|
const [, val] = resolvedValue.match(REG_FN_CALC_NUM) as MatchedRegExp;
|
||||||
|
resolvedValue = `calc(${roundToPrecision(Number(val), HEX)})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCache(cacheKey, resolvedValue);
|
||||||
|
return resolvedValue;
|
||||||
|
};
|
||||||
384
web/node_modules/@asamuzakjp/css-color/src/js/css-gradient.ts
generated
vendored
Normal file
384
web/node_modules/@asamuzakjp/css-color/src/js/css-gradient.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,384 @@
|
||||||
|
/**
|
||||||
|
* css-gradient
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CacheItem, createCacheKey, getCache, setCache } from './cache';
|
||||||
|
import { resolveColor } from './resolve';
|
||||||
|
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,
|
||||||
|
VAL_COMP,
|
||||||
|
VAL_SPEC
|
||||||
|
} 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 ValidateGradientLine - validate gradient line
|
||||||
|
* @property line - gradient line
|
||||||
|
* @property valid - result
|
||||||
|
*/
|
||||||
|
interface ValidateGradientLine {
|
||||||
|
line: string;
|
||||||
|
valid: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef ValidateColorStops - validate color stops
|
||||||
|
* @property colorStops - list of color stops
|
||||||
|
* @property valid - result
|
||||||
|
*/
|
||||||
|
interface ValidateColorStops {
|
||||||
|
colorStops: string[];
|
||||||
|
valid: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
): ValidateGradientLine => {
|
||||||
|
if (isString(value) && isString(type)) {
|
||||||
|
value = value.trim();
|
||||||
|
type = type.trim();
|
||||||
|
let lineSyntax = '';
|
||||||
|
const defaultValues = [];
|
||||||
|
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('|');
|
||||||
|
defaultValues.push(/to\s+bottom/);
|
||||||
|
} 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('|');
|
||||||
|
defaultValues.push(/ellipse/, /farthest-corner/, /at\s+center/);
|
||||||
|
} 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('|');
|
||||||
|
defaultValues.push(/at\s+center/);
|
||||||
|
}
|
||||||
|
if (lineSyntax) {
|
||||||
|
const reg = new RegExp(`^(?:${lineSyntax})$`);
|
||||||
|
const valid = reg.test(value);
|
||||||
|
if (valid) {
|
||||||
|
let line = value;
|
||||||
|
for (const defaultValue of defaultValues) {
|
||||||
|
line = line.replace(defaultValue, '');
|
||||||
|
}
|
||||||
|
line = line.replace(/\s{2,}/g, ' ').trim();
|
||||||
|
return {
|
||||||
|
line,
|
||||||
|
valid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
line: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
line: value,
|
||||||
|
valid: false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validate color stop list
|
||||||
|
* @param list
|
||||||
|
* @param type
|
||||||
|
* @param [opt]
|
||||||
|
* @returns result
|
||||||
|
*/
|
||||||
|
export const validateColorStopList = (
|
||||||
|
list: string[],
|
||||||
|
type: string,
|
||||||
|
opt: Options = {}
|
||||||
|
): ValidateColorStops => {
|
||||||
|
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 valueTypes = [];
|
||||||
|
const valueList = [];
|
||||||
|
for (const item of list) {
|
||||||
|
if (isString(item)) {
|
||||||
|
if (regColorHint.test(item)) {
|
||||||
|
valueTypes.push('hint');
|
||||||
|
valueList.push(item);
|
||||||
|
} else {
|
||||||
|
const itemColor = item.replace(regDimension, '');
|
||||||
|
if (isColor(itemColor, { format: VAL_SPEC })) {
|
||||||
|
const resolvedColor = resolveColor(itemColor, opt) as string;
|
||||||
|
valueTypes.push('color');
|
||||||
|
valueList.push(item.replace(itemColor, resolvedColor));
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
colorStops: list,
|
||||||
|
valid: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const valid = /^color(?:,(?:hint,)?color)+$/.test(valueTypes.join(','));
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
colorStops: valueList
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
colorStops: list,
|
||||||
|
valid: 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 = '', ...itemList] = splitValue(gradValue, {
|
||||||
|
delimiter: ','
|
||||||
|
});
|
||||||
|
const dimension = /^(?:repeating-)?conic-gradient$/.test(type)
|
||||||
|
? DIM_ANGLE_PCT
|
||||||
|
: DIM_LEN_PCT;
|
||||||
|
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
|
||||||
|
let colorStop = '';
|
||||||
|
if (regDimension.test(lineOrColorStop)) {
|
||||||
|
const itemColor = lineOrColorStop.replace(regDimension, '');
|
||||||
|
if (isColor(itemColor, { format: VAL_SPEC })) {
|
||||||
|
const resolvedColor = resolveColor(itemColor, opt) as string;
|
||||||
|
colorStop = lineOrColorStop.replace(itemColor, resolvedColor);
|
||||||
|
}
|
||||||
|
} else if (isColor(lineOrColorStop, { format: VAL_SPEC })) {
|
||||||
|
colorStop = resolveColor(lineOrColorStop, opt) as string;
|
||||||
|
}
|
||||||
|
if (colorStop) {
|
||||||
|
itemList.unshift(colorStop);
|
||||||
|
const { colorStops, valid } = validateColorStopList(
|
||||||
|
itemList,
|
||||||
|
type,
|
||||||
|
opt
|
||||||
|
);
|
||||||
|
if (valid) {
|
||||||
|
const res: Gradient = {
|
||||||
|
value,
|
||||||
|
type,
|
||||||
|
colorStopList: colorStops as ColorStopList
|
||||||
|
};
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} else if (itemList.length > 1) {
|
||||||
|
const { line: gradientLine, valid: validLine } = validateGradientLine(
|
||||||
|
lineOrColorStop,
|
||||||
|
type
|
||||||
|
);
|
||||||
|
const { colorStops, valid: validColorStops } = validateColorStopList(
|
||||||
|
itemList,
|
||||||
|
type,
|
||||||
|
opt
|
||||||
|
);
|
||||||
|
if (validLine && validColorStops) {
|
||||||
|
const res: Gradient = {
|
||||||
|
value,
|
||||||
|
type,
|
||||||
|
gradientLine,
|
||||||
|
colorStopList: colorStops as ColorStopList
|
||||||
|
};
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCache(cacheKey, null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve CSS gradient
|
||||||
|
* @param value - CSS value
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns result
|
||||||
|
*/
|
||||||
|
export const resolveGradient = (value: string, opt: Options = {}): string => {
|
||||||
|
const { format = VAL_COMP } = opt;
|
||||||
|
const gradient = parseGradient(value, opt);
|
||||||
|
if (gradient) {
|
||||||
|
const { type = '', gradientLine = '', colorStopList = [] } = gradient;
|
||||||
|
if (type && Array.isArray(colorStopList) && colorStopList.length > 1) {
|
||||||
|
if (gradientLine) {
|
||||||
|
return `${type}(${gradientLine}, ${colorStopList.join(', ')})`;
|
||||||
|
}
|
||||||
|
return `${type}(${colorStopList.join(', ')})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (format === VAL_SPEC) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return 'none';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
};
|
||||||
250
web/node_modules/@asamuzakjp/css-color/src/js/css-var.ts
generated
vendored
Normal file
250
web/node_modules/@asamuzakjp/css-color/src/js/css-var.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
||||||
|
/**
|
||||||
|
* css-var
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CSSToken, TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||||
|
import {
|
||||||
|
CacheItem,
|
||||||
|
NullObject,
|
||||||
|
createCacheKey,
|
||||||
|
getCache,
|
||||||
|
setCache
|
||||||
|
} from './cache';
|
||||||
|
import { isString } from './common';
|
||||||
|
import { cssCalc } from './css-calc';
|
||||||
|
import { isColor } from './util';
|
||||||
|
import { Options } from './typedef';
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
import { FN_VAR, SYN_FN_CALC, SYN_FN_VAR, VAL_SPEC } from './constant';
|
||||||
|
const {
|
||||||
|
CloseParen: PAREN_CLOSE,
|
||||||
|
Comment: COMMENT,
|
||||||
|
EOF,
|
||||||
|
Ident: IDENT,
|
||||||
|
Whitespace: W_SPACE
|
||||||
|
} = TokenType;
|
||||||
|
const NAMESPACE = 'css-var';
|
||||||
|
|
||||||
|
/* regexp */
|
||||||
|
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
|
||||||
|
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve custom property
|
||||||
|
* @param tokens - CSS tokens
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns result - [tokens, resolvedValue]
|
||||||
|
*/
|
||||||
|
export function resolveCustomProperty(
|
||||||
|
tokens: CSSToken[],
|
||||||
|
opt: Options = {}
|
||||||
|
): [CSSToken[], string] {
|
||||||
|
if (!Array.isArray(tokens)) {
|
||||||
|
throw new TypeError(`${tokens} is not an array.`);
|
||||||
|
}
|
||||||
|
const { customProperty = {} } = opt;
|
||||||
|
const items: 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];
|
||||||
|
// end of var()
|
||||||
|
if (type === PAREN_CLOSE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// nested var()
|
||||||
|
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.hasOwn(customProperty, value)) {
|
||||||
|
item = customProperty[value] as string;
|
||||||
|
} 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)) {
|
||||||
|
// recurse resolveVar()
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse tokens
|
||||||
|
* @param tokens - CSS tokens
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns parsed tokens
|
||||||
|
*/
|
||||||
|
export function parseTokens(
|
||||||
|
tokens: CSSToken[],
|
||||||
|
opt: Options = {}
|
||||||
|
): string[] | NullObject {
|
||||||
|
const res: string[] = [];
|
||||||
|
while (tokens.length) {
|
||||||
|
const token = tokens.shift();
|
||||||
|
const [type = '', value = ''] = token as [TokenType, string];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve CSS var()
|
||||||
|
* @param value - CSS value including var()
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns resolved value
|
||||||
|
*/
|
||||||
|
export function resolveVar(
|
||||||
|
value: string,
|
||||||
|
opt: Options = {}
|
||||||
|
): string | NullObject {
|
||||||
|
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: string = createCacheKey(
|
||||||
|
{
|
||||||
|
namespace: NAMESPACE,
|
||||||
|
name: 'resolveVar',
|
||||||
|
value
|
||||||
|
},
|
||||||
|
opt
|
||||||
|
);
|
||||||
|
const cachedResult = getCache(cacheKey);
|
||||||
|
if (cachedResult instanceof CacheItem) {
|
||||||
|
if (cachedResult.isNull) {
|
||||||
|
return cachedResult as NullObject;
|
||||||
|
}
|
||||||
|
return cachedResult.item as string;
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS var()
|
||||||
|
* @param value - CSS value including var()
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns resolved value
|
||||||
|
*/
|
||||||
|
export const cssVar = (value: string, opt: Options = {}): string => {
|
||||||
|
const resolvedValue = resolveVar(value, opt);
|
||||||
|
if (isString(resolvedValue)) {
|
||||||
|
return resolvedValue;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
635
web/node_modules/@asamuzakjp/css-color/src/js/relative-color.ts
generated
vendored
Normal file
635
web/node_modules/@asamuzakjp/css-color/src/js/relative-color.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,635 @@
|
||||||
|
/**
|
||||||
|
* relative-color
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SyntaxFlag, color as colorParser } from '@csstools/css-color-parser';
|
||||||
|
import {
|
||||||
|
ComponentValue,
|
||||||
|
parseComponentValue
|
||||||
|
} from '@csstools/css-parser-algorithms';
|
||||||
|
import { CSSToken, TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||||
|
import {
|
||||||
|
CacheItem,
|
||||||
|
NullObject,
|
||||||
|
createCacheKey,
|
||||||
|
getCache,
|
||||||
|
setCache
|
||||||
|
} from './cache';
|
||||||
|
import { NAMED_COLORS, convertColorToRgb } from './color';
|
||||||
|
import { isString, isStringOrNumber } from './common';
|
||||||
|
import { resolveDimension, serializeCalc } from './css-calc';
|
||||||
|
import { resolveColor } from './resolve';
|
||||||
|
import { roundToPrecision, splitValue } from './util';
|
||||||
|
import {
|
||||||
|
ColorChannels,
|
||||||
|
MatchedRegExp,
|
||||||
|
Options,
|
||||||
|
StringColorChannels
|
||||||
|
} from './typedef';
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
import {
|
||||||
|
CS_LAB,
|
||||||
|
CS_LCH,
|
||||||
|
FN_LIGHT_DARK,
|
||||||
|
FN_REL,
|
||||||
|
FN_REL_CAPT,
|
||||||
|
FN_VAR,
|
||||||
|
NONE,
|
||||||
|
SYN_COLOR_TYPE,
|
||||||
|
SYN_FN_MATH_START,
|
||||||
|
SYN_FN_VAR,
|
||||||
|
SYN_MIX,
|
||||||
|
VAL_SPEC
|
||||||
|
} from './constant';
|
||||||
|
const {
|
||||||
|
CloseParen: PAREN_CLOSE,
|
||||||
|
Comment: COMMENT,
|
||||||
|
Delim: DELIM,
|
||||||
|
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';
|
||||||
|
|
||||||
|
/* numeric constants */
|
||||||
|
const OCT = 8;
|
||||||
|
const DEC = 10;
|
||||||
|
const HEX = 16;
|
||||||
|
const MAX_PCT = 100;
|
||||||
|
const MAX_RGB = 255;
|
||||||
|
|
||||||
|
/* type definitions */
|
||||||
|
/**
|
||||||
|
* @type NumberOrStringColorChannels - color channel
|
||||||
|
*/
|
||||||
|
type NumberOrStringColorChannels = ColorChannels & StringColorChannels;
|
||||||
|
|
||||||
|
/* regexp */
|
||||||
|
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_CALC_SUM = /^(?:abs|sig?n|cos|tan)\(/;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve relative color channels
|
||||||
|
* @param tokens - CSS tokens
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns resolved color channels
|
||||||
|
*/
|
||||||
|
export function resolveColorChannels(
|
||||||
|
tokens: CSSToken[],
|
||||||
|
opt: Options = {}
|
||||||
|
): NumberOrStringColorChannels | NullObject {
|
||||||
|
if (!Array.isArray(tokens)) {
|
||||||
|
throw new TypeError(`${tokens} is not an array.`);
|
||||||
|
}
|
||||||
|
const { colorSpace = '', format = '' } = opt;
|
||||||
|
const colorChannels = 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);
|
||||||
|
// invalid color channel
|
||||||
|
if (!colorChannel) {
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
const mathFunc = new Set();
|
||||||
|
const channels: [
|
||||||
|
(number | string)[],
|
||||||
|
(number | string)[],
|
||||||
|
(number | string)[],
|
||||||
|
(number | string)[]
|
||||||
|
] = [[], [], [], []];
|
||||||
|
let i = 0;
|
||||||
|
let nest = 0;
|
||||||
|
let func = '';
|
||||||
|
let precededPct = 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 as [
|
||||||
|
TokenType,
|
||||||
|
string,
|
||||||
|
number,
|
||||||
|
number,
|
||||||
|
{ value: string | number } | undefined
|
||||||
|
];
|
||||||
|
const channel = channels[i];
|
||||||
|
if (Array.isArray(channel)) {
|
||||||
|
switch (type) {
|
||||||
|
case DELIM: {
|
||||||
|
if (func) {
|
||||||
|
if (
|
||||||
|
(value === '+' || value === '-') &&
|
||||||
|
precededPct &&
|
||||||
|
!REG_FN_CALC_SUM.test(func)
|
||||||
|
) {
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
precededPct = false;
|
||||||
|
channel.push(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DIM: {
|
||||||
|
if (!func || !REG_FN_CALC_SUM.test(func)) {
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
const resolvedValue = resolveDimension(token, opt);
|
||||||
|
if (isString(resolvedValue)) {
|
||||||
|
channel.push(resolvedValue);
|
||||||
|
} else {
|
||||||
|
channel.push(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUNC: {
|
||||||
|
channel.push(value);
|
||||||
|
func = value;
|
||||||
|
nest++;
|
||||||
|
if (REG_FN_MATH_START.test(value)) {
|
||||||
|
mathFunc.add(nest);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IDENT: {
|
||||||
|
// invalid channel key
|
||||||
|
if (!colorChannel.includes(value)) {
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
channel.push(value);
|
||||||
|
if (!func) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NUM: {
|
||||||
|
channel.push(Number(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 = '';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PCT: {
|
||||||
|
if (!func) {
|
||||||
|
return new NullObject();
|
||||||
|
} else if (!REG_FN_CALC_SUM.test(func)) {
|
||||||
|
const lastValue = channel.toReversed().find(v => v !== ' ');
|
||||||
|
if (lastValue === '+' || lastValue === '-') {
|
||||||
|
return new NullObject();
|
||||||
|
} else if (lastValue === '*' || lastValue === '/') {
|
||||||
|
precededPct = false;
|
||||||
|
} else {
|
||||||
|
precededPct = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channel.push(Number(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 as NumberOrStringColorChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract origin color
|
||||||
|
* @param value - CSS color value
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns origin color value
|
||||||
|
*/
|
||||||
|
export function extractOriginColor(
|
||||||
|
value: string,
|
||||||
|
opt: Options = {}
|
||||||
|
): string | NullObject {
|
||||||
|
const { colorScheme = 'normal', 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: string = createCacheKey(
|
||||||
|
{
|
||||||
|
namespace: NAMESPACE,
|
||||||
|
name: 'extractOriginColor',
|
||||||
|
value
|
||||||
|
},
|
||||||
|
opt
|
||||||
|
);
|
||||||
|
const cachedResult = getCache(cacheKey);
|
||||||
|
if (cachedResult instanceof CacheItem) {
|
||||||
|
if (cachedResult.isNull) {
|
||||||
|
return cachedResult as NullObject;
|
||||||
|
}
|
||||||
|
return cachedResult.item as string;
|
||||||
|
}
|
||||||
|
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) as MatchedRegExp;
|
||||||
|
}
|
||||||
|
opt.colorSpace = colorSpace;
|
||||||
|
if (value.includes(FN_LIGHT_DARK)) {
|
||||||
|
const colorParts = value
|
||||||
|
.replace(new RegExp(`^${colorSpace}\\(`), '')
|
||||||
|
.replace(/\)$/, '');
|
||||||
|
const [, originColor = ''] = splitValue(colorParts);
|
||||||
|
const specifiedOriginColor = resolveColor(originColor, {
|
||||||
|
colorScheme,
|
||||||
|
format: VAL_SPEC
|
||||||
|
}) as string;
|
||||||
|
if (specifiedOriginColor === '') {
|
||||||
|
setCache(cacheKey, null);
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
if (format === VAL_SPEC) {
|
||||||
|
value = value.replace(originColor, specifiedOriginColor);
|
||||||
|
} else {
|
||||||
|
const resolvedOriginColor = resolveColor(specifiedOriginColor, opt);
|
||||||
|
if (isString(resolvedOriginColor)) {
|
||||||
|
value = value.replace(originColor, resolvedOriginColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (REG_COLOR_CAPT.test(value)) {
|
||||||
|
const [, originColor] = value.match(REG_COLOR_CAPT) as MatchedRegExp;
|
||||||
|
const [, restValue] = value.split(originColor) as MatchedRegExp;
|
||||||
|
if (/^[a-z]+$/.test(originColor)) {
|
||||||
|
if (
|
||||||
|
!/^transparent$/.test(originColor) &&
|
||||||
|
!Object.hasOwn(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// nested relative color
|
||||||
|
} else {
|
||||||
|
const [, restValue] = value.split(REG_FN_REL_START) as MatchedRegExp;
|
||||||
|
const tokens = tokenize({ css: restValue });
|
||||||
|
const originColor: string[] = [];
|
||||||
|
let nest = 0;
|
||||||
|
while (tokens.length) {
|
||||||
|
const [type, tokenValue] = tokens.shift() as [TokenType, string];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve relative color
|
||||||
|
* @param value - CSS relative color value
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns resolved value
|
||||||
|
*/
|
||||||
|
export function resolveRelativeColor(
|
||||||
|
value: string,
|
||||||
|
opt: Options = {}
|
||||||
|
): string | NullObject {
|
||||||
|
const { format = '' } = opt;
|
||||||
|
if (isString(value)) {
|
||||||
|
if (REG_FN_VAR.test(value)) {
|
||||||
|
if (format === VAL_SPEC) {
|
||||||
|
return value;
|
||||||
|
// var() must be resolved before resolveRelativeColor()
|
||||||
|
} 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: string = createCacheKey(
|
||||||
|
{
|
||||||
|
namespace: NAMESPACE,
|
||||||
|
name: 'resolveRelativeColor',
|
||||||
|
value
|
||||||
|
},
|
||||||
|
opt
|
||||||
|
);
|
||||||
|
const cachedResult = getCache(cacheKey);
|
||||||
|
if (cachedResult instanceof CacheItem) {
|
||||||
|
if (cachedResult.isNull) {
|
||||||
|
return cachedResult as NullObject;
|
||||||
|
}
|
||||||
|
return cachedResult.item as string;
|
||||||
|
}
|
||||||
|
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) as ComponentValue;
|
||||||
|
const parsedComponents = colorParser(components);
|
||||||
|
if (!parsedComponents) {
|
||||||
|
setCache(cacheKey, null);
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
alpha: alphaComponent,
|
||||||
|
channels: channelsComponent,
|
||||||
|
colorNotation,
|
||||||
|
syntaxFlags
|
||||||
|
} = parsedComponents;
|
||||||
|
let alpha: number | string;
|
||||||
|
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: number | string;
|
||||||
|
let v2: number | string;
|
||||||
|
let v3: number | string;
|
||||||
|
[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})`
|
||||||
|
) as ColorChannels;
|
||||||
|
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;
|
||||||
|
}
|
||||||
443
web/node_modules/@asamuzakjp/css-color/src/js/resolve.ts
generated
vendored
Normal file
443
web/node_modules/@asamuzakjp/css-color/src/js/resolve.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,443 @@
|
||||||
|
/**
|
||||||
|
* resolve
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
CacheItem,
|
||||||
|
NullObject,
|
||||||
|
createCacheKey,
|
||||||
|
getCache,
|
||||||
|
setCache
|
||||||
|
} from './cache';
|
||||||
|
import {
|
||||||
|
convertRgbToHex,
|
||||||
|
resolveColorFunc,
|
||||||
|
resolveColorMix,
|
||||||
|
resolveColorValue
|
||||||
|
} from './color';
|
||||||
|
import { isString } from './common';
|
||||||
|
import { cssCalc } from './css-calc';
|
||||||
|
import { resolveVar } from './css-var';
|
||||||
|
import { resolveRelativeColor } from './relative-color';
|
||||||
|
import { splitValue } from './util';
|
||||||
|
import {
|
||||||
|
ComputedColorChannels,
|
||||||
|
Options,
|
||||||
|
SpecifiedColorChannels
|
||||||
|
} from './typedef';
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
import {
|
||||||
|
FN_COLOR,
|
||||||
|
FN_MIX,
|
||||||
|
SYN_FN_CALC,
|
||||||
|
SYN_FN_LIGHT_DARK,
|
||||||
|
SYN_FN_REL,
|
||||||
|
SYN_FN_VAR,
|
||||||
|
VAL_COMP,
|
||||||
|
VAL_SPEC
|
||||||
|
} from './constant';
|
||||||
|
const NAMESPACE = 'resolve';
|
||||||
|
const RGB_TRANSPARENT = 'rgba(0, 0, 0, 0)';
|
||||||
|
|
||||||
|
/* regexp */
|
||||||
|
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
|
||||||
|
const REG_FN_LIGHT_DARK = new RegExp(SYN_FN_LIGHT_DARK);
|
||||||
|
const REG_FN_REL = new RegExp(SYN_FN_REL);
|
||||||
|
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve color
|
||||||
|
* @param value - CSS color value
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns resolved color
|
||||||
|
*/
|
||||||
|
export const resolveColor = (
|
||||||
|
value: string,
|
||||||
|
opt: Options = {}
|
||||||
|
): string | NullObject => {
|
||||||
|
if (isString(value)) {
|
||||||
|
value = value.trim();
|
||||||
|
} else {
|
||||||
|
throw new TypeError(`${value} is not a string.`);
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
colorScheme = 'normal',
|
||||||
|
currentColor = '',
|
||||||
|
format = VAL_COMP,
|
||||||
|
nullable = false
|
||||||
|
} = opt;
|
||||||
|
const cacheKey: string = createCacheKey(
|
||||||
|
{
|
||||||
|
namespace: NAMESPACE,
|
||||||
|
name: 'resolve',
|
||||||
|
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)) {
|
||||||
|
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 res = RGB_TRANSPARENT;
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = resolvedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opt.format !== format) {
|
||||||
|
opt.format = format;
|
||||||
|
}
|
||||||
|
value = value.toLowerCase();
|
||||||
|
if (REG_FN_LIGHT_DARK.test(value) && value.endsWith(')')) {
|
||||||
|
const colorParts = value.replace(REG_FN_LIGHT_DARK, '').replace(/\)$/, '');
|
||||||
|
const [light = '', dark = ''] = splitValue(colorParts, {
|
||||||
|
delimiter: ','
|
||||||
|
});
|
||||||
|
if (light && dark) {
|
||||||
|
if (format === VAL_SPEC) {
|
||||||
|
const lightColor = resolveColor(light, opt);
|
||||||
|
const darkColor = resolveColor(dark, opt);
|
||||||
|
let res;
|
||||||
|
if (lightColor && darkColor) {
|
||||||
|
res = `light-dark(${lightColor}, ${darkColor})`;
|
||||||
|
} else {
|
||||||
|
res = '';
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
let resolvedValue;
|
||||||
|
if (colorScheme === 'dark') {
|
||||||
|
resolvedValue = resolveColor(dark, opt);
|
||||||
|
} else {
|
||||||
|
resolvedValue = resolveColor(light, opt);
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
if (resolvedValue instanceof NullObject) {
|
||||||
|
if (nullable) {
|
||||||
|
res = resolvedValue;
|
||||||
|
} else {
|
||||||
|
res = RGB_TRANSPARENT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = resolvedValue;
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// invalid value
|
||||||
|
switch (format) {
|
||||||
|
case VAL_SPEC: {
|
||||||
|
setCache(cacheKey, '');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
case 'hex':
|
||||||
|
case 'hexAlpha': {
|
||||||
|
setCache(cacheKey, null);
|
||||||
|
return new NullObject();
|
||||||
|
}
|
||||||
|
case VAL_COMP:
|
||||||
|
default: {
|
||||||
|
const res = RGB_TRANSPARENT;
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (REG_FN_REL.test(value)) {
|
||||||
|
const resolvedValue = resolveRelativeColor(value, opt);
|
||||||
|
if (format === VAL_COMP) {
|
||||||
|
let res;
|
||||||
|
if (resolvedValue instanceof NullObject) {
|
||||||
|
if (nullable) {
|
||||||
|
res = resolvedValue;
|
||||||
|
} else {
|
||||||
|
res = RGB_TRANSPARENT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = resolvedValue;
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (format === VAL_SPEC) {
|
||||||
|
let res = '';
|
||||||
|
if (resolvedValue instanceof NullObject) {
|
||||||
|
res = '';
|
||||||
|
} else {
|
||||||
|
res = resolvedValue;
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
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 res = '#00000000';
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
case VAL_COMP:
|
||||||
|
default: {
|
||||||
|
const res = RGB_TRANSPARENT;
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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 as ComputedColorChannels;
|
||||||
|
} else if (format === VAL_COMP) {
|
||||||
|
const res = RGB_TRANSPARENT;
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} else if (format === VAL_SPEC) {
|
||||||
|
if (value.startsWith(FN_MIX)) {
|
||||||
|
const res = resolveColorMix(value, opt) as string;
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
} else if (value.startsWith(FN_COLOR)) {
|
||||||
|
const [scs, rr, gg, bb, aa] = resolveColorFunc(
|
||||||
|
value,
|
||||||
|
opt
|
||||||
|
) as SpecifiedColorChannels;
|
||||||
|
let res = '';
|
||||||
|
if (aa === 1) {
|
||||||
|
res = `color(${scs} ${rr} ${gg} ${bb})`;
|
||||||
|
} else {
|
||||||
|
res = `color(${scs} ${rr} ${gg} ${bb} / ${aa})`;
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
const rgb = resolveColorValue(value, opt);
|
||||||
|
if (isString(rgb)) {
|
||||||
|
setCache(cacheKey, rgb);
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
const [scs, rr, gg, bb, aa] = rgb as SpecifiedColorChannels;
|
||||||
|
let res = '';
|
||||||
|
if (scs === 'rgb') {
|
||||||
|
if (aa === 1) {
|
||||||
|
res = `${scs}(${rr}, ${gg}, ${bb})`;
|
||||||
|
} else {
|
||||||
|
res = `${scs}a(${rr}, ${gg}, ${bb}, ${aa})`;
|
||||||
|
}
|
||||||
|
} else if (aa === 1) {
|
||||||
|
res = `${scs}(${rr} ${gg} ${bb})`;
|
||||||
|
} else {
|
||||||
|
res = `${scs}(${rr} ${gg} ${bb} / ${aa})`;
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} 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 as ComputedColorChannels;
|
||||||
|
} 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 as ComputedColorChannels;
|
||||||
|
} else if (value) {
|
||||||
|
const resolvedValue = resolveColorValue(value, opt);
|
||||||
|
if (resolvedValue instanceof NullObject) {
|
||||||
|
setCache(cacheKey, resolvedValue);
|
||||||
|
return resolvedValue;
|
||||||
|
}
|
||||||
|
[cs, r, g, b, alpha] = resolvedValue as ComputedColorChannels;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 const resolve = (value: string, opt: Options = {}): string | null => {
|
||||||
|
opt.nullable = false;
|
||||||
|
const resolvedValue = resolveColor(value, opt);
|
||||||
|
if (resolvedValue instanceof NullObject) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return resolvedValue as string;
|
||||||
|
};
|
||||||
88
web/node_modules/@asamuzakjp/css-color/src/js/typedef.ts
generated
vendored
Normal file
88
web/node_modules/@asamuzakjp/css-color/src/js/typedef.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
* typedef
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* type definitions */
|
||||||
|
/**
|
||||||
|
* @typedef Options - options
|
||||||
|
* @property [alpha] - enable alpha
|
||||||
|
* @property [colorSpace] - color space
|
||||||
|
* @property [currentColor] - color for currentcolor
|
||||||
|
* @property [customProperty] - custom properties
|
||||||
|
* @property [d50] - white point in d50
|
||||||
|
* @property [dimension] - dimension
|
||||||
|
* @property [format] - output format
|
||||||
|
* @property [key] - key
|
||||||
|
*/
|
||||||
|
export interface Options {
|
||||||
|
alpha?: boolean;
|
||||||
|
colorScheme?: string;
|
||||||
|
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;
|
||||||
|
preserveComment?: 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
|
||||||
|
];
|
||||||
443
web/node_modules/@asamuzakjp/css-color/src/js/util.ts
generated
vendored
Normal file
443
web/node_modules/@asamuzakjp/css-color/src/js/util.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,443 @@
|
||||||
|
/**
|
||||||
|
* util
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||||
|
import { CacheItem, createCacheKey, getCache, setCache } from './cache';
|
||||||
|
import { isString } from './common';
|
||||||
|
import { resolveColor } from './resolve';
|
||||||
|
import { Options } from './typedef';
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
import { NAMED_COLORS } from './color';
|
||||||
|
import { SYN_COLOR_TYPE, SYN_MIX, VAL_SPEC } from './constant';
|
||||||
|
const {
|
||||||
|
CloseParen: PAREN_CLOSE,
|
||||||
|
Comma: COMMA,
|
||||||
|
Comment: COMMENT,
|
||||||
|
Delim: DELIM,
|
||||||
|
EOF,
|
||||||
|
Function: FUNC,
|
||||||
|
Ident: IDENT,
|
||||||
|
OpenParen: PAREN_OPEN,
|
||||||
|
Whitespace: W_SPACE
|
||||||
|
} = TokenType;
|
||||||
|
const NAMESPACE = 'util';
|
||||||
|
|
||||||
|
/* numeric constants */
|
||||||
|
const DEC = 10;
|
||||||
|
const HEX = 16;
|
||||||
|
const DEG = 360;
|
||||||
|
const DEG_HALF = 180;
|
||||||
|
|
||||||
|
/* regexp */
|
||||||
|
const REG_COLOR = new RegExp(`^(?:${SYN_COLOR_TYPE})$`);
|
||||||
|
const REG_FN_COLOR =
|
||||||
|
/^(?:(?:ok)?l(?:ab|ch)|color(?:-mix)?|hsla?|hwb|rgba?|var)\(/;
|
||||||
|
const REG_MIX = new RegExp(SYN_MIX);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* split value
|
||||||
|
* NOTE: comments are stripped, it can be preserved if, in the options param,
|
||||||
|
* `delimiter` is either ',' or '/' and with `preserveComment` set to `true`
|
||||||
|
* @param value - CSS value
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns array of values
|
||||||
|
*/
|
||||||
|
export const splitValue = (value: string, opt: Options = {}): string[] => {
|
||||||
|
if (isString(value)) {
|
||||||
|
value = value.trim();
|
||||||
|
} else {
|
||||||
|
throw new TypeError(`${value} is not a string.`);
|
||||||
|
}
|
||||||
|
const { delimiter = ' ', preserveComment = false } = opt;
|
||||||
|
const cacheKey: string = createCacheKey(
|
||||||
|
{
|
||||||
|
namespace: NAMESPACE,
|
||||||
|
name: 'splitValue',
|
||||||
|
value
|
||||||
|
},
|
||||||
|
{
|
||||||
|
delimiter,
|
||||||
|
preserveComment
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const cachedResult = getCache(cacheKey);
|
||||||
|
if (cachedResult instanceof CacheItem) {
|
||||||
|
return cachedResult.item as string[];
|
||||||
|
}
|
||||||
|
let regDelimiter;
|
||||||
|
if (delimiter === ',') {
|
||||||
|
regDelimiter = /^,$/;
|
||||||
|
} else if (delimiter === '/') {
|
||||||
|
regDelimiter = /^\/$/;
|
||||||
|
} else {
|
||||||
|
regDelimiter = /^\s+$/;
|
||||||
|
}
|
||||||
|
const tokens = tokenize({ css: value });
|
||||||
|
let nest = 0;
|
||||||
|
let str = '';
|
||||||
|
const res: string[] = [];
|
||||||
|
while (tokens.length) {
|
||||||
|
const [type, value] = tokens.shift() as [TokenType, string];
|
||||||
|
switch (type) {
|
||||||
|
case COMMA: {
|
||||||
|
if (regDelimiter.test(value)) {
|
||||||
|
if (nest === 0) {
|
||||||
|
res.push(str.trim());
|
||||||
|
str = '';
|
||||||
|
} else {
|
||||||
|
str += value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str += value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DELIM: {
|
||||||
|
if (regDelimiter.test(value)) {
|
||||||
|
if (nest === 0) {
|
||||||
|
res.push(str.trim());
|
||||||
|
str = '';
|
||||||
|
} else {
|
||||||
|
str += value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str += value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case COMMENT: {
|
||||||
|
if (preserveComment && (delimiter === ',' || delimiter === '/')) {
|
||||||
|
str += value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FUNC:
|
||||||
|
case PAREN_OPEN: {
|
||||||
|
str += value;
|
||||||
|
nest++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PAREN_CLOSE: {
|
||||||
|
str += value;
|
||||||
|
nest--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case W_SPACE: {
|
||||||
|
if (regDelimiter.test(value)) {
|
||||||
|
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 += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract dashed-ident tokens
|
||||||
|
* @param value - CSS value
|
||||||
|
* @returns array of dashed-ident tokens
|
||||||
|
*/
|
||||||
|
export const extractDashedIdent = (value: string): string[] => {
|
||||||
|
if (isString(value)) {
|
||||||
|
value = value.trim();
|
||||||
|
} else {
|
||||||
|
throw new TypeError(`${value} is not a string.`);
|
||||||
|
}
|
||||||
|
const cacheKey: string = createCacheKey({
|
||||||
|
namespace: NAMESPACE,
|
||||||
|
name: 'extractDashedIdent',
|
||||||
|
value
|
||||||
|
});
|
||||||
|
const cachedResult = getCache(cacheKey);
|
||||||
|
if (cachedResult instanceof CacheItem) {
|
||||||
|
return cachedResult.item as string[];
|
||||||
|
}
|
||||||
|
const tokens = tokenize({ css: value });
|
||||||
|
const items = new Set();
|
||||||
|
while (tokens.length) {
|
||||||
|
const [type, value] = tokens.shift() as [TokenType, string];
|
||||||
|
if (type === IDENT && value.startsWith('--')) {
|
||||||
|
items.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const res = [...items] as string[];
|
||||||
|
setCache(cacheKey, res);
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is color
|
||||||
|
* @param value - CSS value
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns result
|
||||||
|
*/
|
||||||
|
export const isColor = (value: unknown, opt: Options = {}): boolean => {
|
||||||
|
if (isString(value)) {
|
||||||
|
value = value.toLowerCase().trim();
|
||||||
|
if (value && isString(value)) {
|
||||||
|
if (/^[a-z]+$/.test(value)) {
|
||||||
|
if (
|
||||||
|
/^(?:currentcolor|transparent)$/.test(value) ||
|
||||||
|
Object.hasOwn(NAMED_COLORS, value)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (REG_COLOR.test(value) || REG_MIX.test(value)) {
|
||||||
|
return true;
|
||||||
|
} else if (REG_FN_COLOR.test(value)) {
|
||||||
|
opt.nullable = true;
|
||||||
|
if (!opt.format) {
|
||||||
|
opt.format = VAL_SPEC;
|
||||||
|
}
|
||||||
|
const resolvedValue = resolveColor(value, opt);
|
||||||
|
if (resolvedValue) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value to JSON string
|
||||||
|
* @param value - CSS value
|
||||||
|
* @param [func] - stringify function
|
||||||
|
* @returns stringified value in JSON notation
|
||||||
|
*/
|
||||||
|
export const valueToJsonString = (
|
||||||
|
value: unknown,
|
||||||
|
func: boolean = false
|
||||||
|
): string => {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* round to specified precision
|
||||||
|
* @param value - numeric value
|
||||||
|
* @param bit - minimum bits
|
||||||
|
* @returns rounded value
|
||||||
|
*/
|
||||||
|
export const roundToPrecision = (value: number, bit: number = 0): number => {
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interpolate hue
|
||||||
|
* @param hueA - hue value
|
||||||
|
* @param hueB - hue value
|
||||||
|
* @param arc - shorter | longer | increasing | decreasing
|
||||||
|
* @returns result - [hueA, hueB]
|
||||||
|
*/
|
||||||
|
export const interpolateHue = (
|
||||||
|
hueA: number,
|
||||||
|
hueB: number,
|
||||||
|
arc: string = 'shorter'
|
||||||
|
): [number, number] => {
|
||||||
|
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];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* absolute font size to pixel ratio */
|
||||||
|
const absoluteFontSize = new Map([
|
||||||
|
['xx-small', 9 / 16],
|
||||||
|
['x-small', 5 / 8],
|
||||||
|
['small', 13 / 16],
|
||||||
|
['medium', 1],
|
||||||
|
['large', 9 / 8],
|
||||||
|
['x-large', 3 / 2],
|
||||||
|
['xx-large', 2],
|
||||||
|
['xxx-large', 3]
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* relative font size to pixel ratio */
|
||||||
|
const relativeFontSize = new Map([
|
||||||
|
['smaller', 1 / 1.2],
|
||||||
|
['larger', 1.2]
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* absolute length to pixel ratio */
|
||||||
|
const absoluteLength = new Map([
|
||||||
|
['cm', 96 / 2.54],
|
||||||
|
['mm', 96 / 2.54 / 10],
|
||||||
|
['q', 96 / 2.54 / 40],
|
||||||
|
['in', 96],
|
||||||
|
['pc', 96 / 6],
|
||||||
|
['pt', 96 / 72],
|
||||||
|
['px', 1]
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* relative length to pixel ratio */
|
||||||
|
const relativeLength = new Map([
|
||||||
|
['rcap', 1],
|
||||||
|
['rch', 0.5],
|
||||||
|
['rem', 1],
|
||||||
|
['rex', 0.5],
|
||||||
|
['ric', 1],
|
||||||
|
['rlh', 1.2]
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resolve length in pixels
|
||||||
|
* @param value - value
|
||||||
|
* @param unit - unit
|
||||||
|
* @param [opt] - options
|
||||||
|
* @returns pixelated value
|
||||||
|
*/
|
||||||
|
export const resolveLengthInPixels = (
|
||||||
|
value: number | string,
|
||||||
|
unit: string | undefined,
|
||||||
|
opt: Options = {}
|
||||||
|
): number => {
|
||||||
|
const { dimension = {} } = opt;
|
||||||
|
const { callback, em, rem, vh, vw } = dimension as {
|
||||||
|
callback: (K: string) => number;
|
||||||
|
em: number;
|
||||||
|
rem: number;
|
||||||
|
vh: number;
|
||||||
|
vw: number;
|
||||||
|
};
|
||||||
|
if (isString(value)) {
|
||||||
|
value = value.toLowerCase().trim();
|
||||||
|
if (absoluteFontSize.has(value)) {
|
||||||
|
return Number(absoluteFontSize.get(value)) * rem;
|
||||||
|
} else if (relativeFontSize.has(value)) {
|
||||||
|
return Number(relativeFontSize.get(value)) * em;
|
||||||
|
}
|
||||||
|
return Number.NaN;
|
||||||
|
} else if (Number.isFinite(value) && unit) {
|
||||||
|
if (Object.hasOwn(dimension, unit)) {
|
||||||
|
return value * Number(dimension[unit]);
|
||||||
|
} else if (typeof callback === 'function') {
|
||||||
|
return value * callback(unit);
|
||||||
|
} else if (absoluteLength.has(unit)) {
|
||||||
|
return value * Number(absoluteLength.get(unit));
|
||||||
|
} else if (relativeLength.has(unit)) {
|
||||||
|
return value * Number(relativeLength.get(unit)) * rem;
|
||||||
|
} else if (relativeLength.has(`r${unit}`)) {
|
||||||
|
return value * Number(relativeLength.get(`r${unit}`)) * em;
|
||||||
|
} else {
|
||||||
|
switch (unit) {
|
||||||
|
case 'vb':
|
||||||
|
case 'vi': {
|
||||||
|
return value * vw;
|
||||||
|
}
|
||||||
|
case 'vmax': {
|
||||||
|
if (vh > vw) {
|
||||||
|
return value * vh;
|
||||||
|
}
|
||||||
|
return value * vw;
|
||||||
|
}
|
||||||
|
case 'vmin': {
|
||||||
|
if (vh < vw) {
|
||||||
|
return value * vh;
|
||||||
|
}
|
||||||
|
return value * vw;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// unsupported or invalid unit
|
||||||
|
return Number.NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// unsupported or invalid value
|
||||||
|
return Number.NaN;
|
||||||
|
};
|
||||||
21
web/node_modules/@asamuzakjp/dom-selector/LICENSE
generated
vendored
Normal file
21
web/node_modules/@asamuzakjp/dom-selector/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 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.
|
||||||
324
web/node_modules/@asamuzakjp/dom-selector/README.md
generated
vendored
Normal file
324
web/node_modules/@asamuzakjp/dom-selector/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,324 @@
|
||||||
|
# DOM Selector
|
||||||
|
|
||||||
|
[](https://github.com/asamuzaK/domSelector/actions/workflows/node.js.yml)
|
||||||
|
[](https://github.com/asamuzaK/domSelector/actions/workflows/github-code-scanning/codeql)
|
||||||
|
[](https://www.npmjs.com/package/@asamuzakjp/dom-selector)
|
||||||
|
|
||||||
|
A CSS selector engine.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```console
|
||||||
|
npm i @asamuzakjp/dom-selector
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { DOMSelector } from '@asamuzakjp/dom-selector';
|
||||||
|
import { JSDOM } from 'jsdom';
|
||||||
|
|
||||||
|
const { window } = new JSDOM();
|
||||||
|
const {
|
||||||
|
closest, matches, querySelector, querySelectorAll
|
||||||
|
} = new DOMSelector(window);
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
||||||
|
|
||||||
|
### matches(selector, node, opt)
|
||||||
|
|
||||||
|
matches - equivalent to [Element.matches()][64]
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `selector` **[string][59]** CSS selector
|
||||||
|
- `node` **[object][60]** Element node
|
||||||
|
- `opt` **[object][60]?** options
|
||||||
|
- `opt.noexcept` **[boolean][61]?** no exception
|
||||||
|
- `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
|
||||||
|
|
||||||
|
Returns **[boolean][61]** `true` if matched, `false` otherwise
|
||||||
|
|
||||||
|
|
||||||
|
### closest(selector, node, opt)
|
||||||
|
|
||||||
|
closest - equivalent to [Element.closest()][65]
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `selector` **[string][59]** CSS selector
|
||||||
|
- `node` **[object][60]** Element node
|
||||||
|
- `opt` **[object][60]?** options
|
||||||
|
- `opt.noexcept` **[boolean][61]?** no exception
|
||||||
|
- `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
|
||||||
|
|
||||||
|
Returns **[object][60]?** matched node
|
||||||
|
|
||||||
|
|
||||||
|
### querySelector(selector, node, opt)
|
||||||
|
|
||||||
|
querySelector - equivalent to [Document.querySelector()][66], [DocumentFragment.querySelector()][67] and [Element.querySelector()][68]
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `selector` **[string][59]** CSS selector
|
||||||
|
- `node` **[object][60]** Document, DocumentFragment or Element node
|
||||||
|
- `opt` **[object][60]?** options
|
||||||
|
- `opt.noexcept` **[boolean][61]?** no exception
|
||||||
|
- `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
|
||||||
|
|
||||||
|
Returns **[object][60]?** matched node
|
||||||
|
|
||||||
|
|
||||||
|
### querySelectorAll(selector, node, opt)
|
||||||
|
|
||||||
|
querySelectorAll - equivalent to [Document.querySelectorAll()][69], [DocumentFragment.querySelectorAll()][70] and [Element.querySelectorAll()][71]
|
||||||
|
**NOTE**: returns Array, not NodeList
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `selector` **[string][59]** CSS selector
|
||||||
|
- `node` **[object][60]** Document, DocumentFragment or Element node
|
||||||
|
- `opt` **[object][60]?** options
|
||||||
|
- `opt.noexcept` **[boolean][61]?** no exception
|
||||||
|
- `opt.warn` **[boolean][61]?** console warn e.g. unsupported pseudo-class
|
||||||
|
|
||||||
|
Returns **[Array][62]<([object][60] \| [undefined][63])>** array of matched nodes
|
||||||
|
|
||||||
|
|
||||||
|
## Monkey patch jsdom
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
import { DOMSelector } from '@asamuzakjp/dom-selector';
|
||||||
|
import { JSDOM } from 'jsdom';
|
||||||
|
|
||||||
|
const dom = new JSDOM('', {
|
||||||
|
runScripts: 'dangerously',
|
||||||
|
url: 'http://localhost/',
|
||||||
|
beforeParse: window => {
|
||||||
|
const domSelector = new DOMSelector(window);
|
||||||
|
|
||||||
|
const matches = domSelector.matches.bind(domSelector);
|
||||||
|
window.Element.prototype.matches = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return matches(selector, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closest = domSelector.closest.bind(domSelector);
|
||||||
|
window.Element.prototype.closest = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return closest(selector, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
const querySelector = domSelector.querySelector.bind(domSelector);
|
||||||
|
window.Document.prototype.querySelector = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return querySelector(selector, this);
|
||||||
|
};
|
||||||
|
window.DocumentFragment.prototype.querySelector = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return querySelector(selector, this);
|
||||||
|
};
|
||||||
|
window.Element.prototype.querySelector = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return querySelector(selector, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
const querySelectorAll = domSelector.querySelectorAll.bind(domSelector);
|
||||||
|
window.Document.prototype.querySelectorAll = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return querySelectorAll(selector, this);
|
||||||
|
};
|
||||||
|
window.DocumentFragment.prototype.querySelectorAll = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return querySelectorAll(selector, this);
|
||||||
|
};
|
||||||
|
window.Element.prototype.querySelectorAll = function (...args) {
|
||||||
|
if (!args.length) {
|
||||||
|
throw new window.TypeError('1 argument required, but only 0 present.');
|
||||||
|
}
|
||||||
|
const [selector] = args;
|
||||||
|
return querySelectorAll(selector, this);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Supported CSS selectors
|
||||||
|
|
||||||
|
|Pattern|Supported|Note|
|
||||||
|
|:--------|:-------:|:--------|
|
||||||
|
|\*|✓| |
|
||||||
|
|E|✓| |
|
||||||
|
|ns\|E|✓| |
|
||||||
|
|\*\|E|✓| |
|
||||||
|
|\|E|✓| |
|
||||||
|
|E F|✓| |
|
||||||
|
|E > F|✓| |
|
||||||
|
|E + F|✓| |
|
||||||
|
|E ~ F|✓| |
|
||||||
|
|F \|\| E|Unsupported| |
|
||||||
|
|E.warning|✓| |
|
||||||
|
|E#myid|✓| |
|
||||||
|
|E\[foo\]|✓| |
|
||||||
|
|E\[foo="bar"\]|✓| |
|
||||||
|
|E\[foo="bar" i\]|✓| |
|
||||||
|
|E\[foo="bar" s\]|✓| |
|
||||||
|
|E\[foo~="bar"\]|✓| |
|
||||||
|
|E\[foo^="bar"\]|✓| |
|
||||||
|
|E\[foo$="bar"\]|✓| |
|
||||||
|
|E\[foo*="bar"\]|✓| |
|
||||||
|
|E\[foo\|="en"\]|✓| |
|
||||||
|
|E:is(s1, s2, …)|✓| |
|
||||||
|
|E:not(s1, s2, …)|✓| |
|
||||||
|
|E:where(s1, s2, …)|✓| |
|
||||||
|
|E:has(rs1, rs2, …)|✓| |
|
||||||
|
|E:defined|Partially supported|Matching with MathML is not yet supported.|
|
||||||
|
|E:dir(ltr)|✓| |
|
||||||
|
|E:lang(en)|✓| |
|
||||||
|
|E:any‑link|✓| |
|
||||||
|
|E:link|✓| |
|
||||||
|
|E:visited|✓|Returns `false` or `null` to prevent fingerprinting.|
|
||||||
|
|E:local‑link|✓| |
|
||||||
|
|E:target|✓| |
|
||||||
|
|E:target‑within|✓| |
|
||||||
|
|E:scope|✓| |
|
||||||
|
|E:hover|✓| |
|
||||||
|
|E:active|✓| |
|
||||||
|
|E:focus|✓| |
|
||||||
|
|E:focus‑visible|✓| |
|
||||||
|
|E:focus‑within|✓| |
|
||||||
|
|E:current|Unsupported| |
|
||||||
|
|E:current(s)|Unsupported| |
|
||||||
|
|E:past|Unsupported| |
|
||||||
|
|E:future|Unsupported| |
|
||||||
|
|E:open<br>E:closed|Partially supported|Matching with <select>, e.g. `select:open`, is not supported.|
|
||||||
|
|E:popover-open|✓| |
|
||||||
|
|E:enabled<br>E:disabled|✓| |
|
||||||
|
|E:read‑write<br>E:read‑only|✓| |
|
||||||
|
|E:placeholder‑shown|✓| |
|
||||||
|
|E:default|✓| |
|
||||||
|
|E:checked|✓| |
|
||||||
|
|E:indeterminate|✓| |
|
||||||
|
|E:blank|Unsupported| |
|
||||||
|
|E:valid<br>E:invalid|✓| |
|
||||||
|
|E:in-range<br>E:out-of-range|✓| |
|
||||||
|
|E:required<br>E:optional|✓| |
|
||||||
|
|E:user‑valid<br>E:user‑invalid|Unsupported| |
|
||||||
|
|E:root|✓| |
|
||||||
|
|E:empty|✓| |
|
||||||
|
|E:nth‑child(n [of S]?)|✓| |
|
||||||
|
|E:nth‑last‑child(n [of S]?)|✓| |
|
||||||
|
|E:first‑child|✓| |
|
||||||
|
|E:last‑child|✓| |
|
||||||
|
|E:only‑child|✓| |
|
||||||
|
|E:nth‑of‑type(n)|✓| |
|
||||||
|
|E:nth‑last‑of‑type(n)|✓| |
|
||||||
|
|E:first‑of‑type|✓| |
|
||||||
|
|E:last‑of‑type|✓| |
|
||||||
|
|E:only‑of‑type|✓| |
|
||||||
|
|E:nth‑col(n)|Unsupported| |
|
||||||
|
|E:nth‑last‑col(n)|Unsupported| |
|
||||||
|
|CE:state(v)|✓|*1|
|
||||||
|
|:host|✓| |
|
||||||
|
|:host(s)|✓| |
|
||||||
|
|:host(:state(v))|✓|*1|
|
||||||
|
|:host:has(rs1, rs2, ...)|✓| |
|
||||||
|
|:host(s):has(rs1, rs2, ...)|✓| |
|
||||||
|
|:host‑context(s)|✓| |
|
||||||
|
|:host‑context(s):has(rs1, rs2, ...)|✓| |
|
||||||
|
|&|✓|Only supports outermost `&`, i.e. equivalent to `:scope`|
|
||||||
|
|
||||||
|
*1: `ElementInternals.states`, i.e. `CustomStateSet`, is not implemented in jsdom, so you need to apply a patch in the custom element constructor.
|
||||||
|
|
||||||
|
``` javascript
|
||||||
|
class LabeledCheckbox extends window.HTMLElement {
|
||||||
|
#internals;
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.#internals = this.attachInternals();
|
||||||
|
// patch CustomStateSet
|
||||||
|
if (!this.#internals.states) {
|
||||||
|
this.#internals.states = new Set();
|
||||||
|
}
|
||||||
|
this.addEventListener('click', this._onClick.bind(this));
|
||||||
|
}
|
||||||
|
get checked() {
|
||||||
|
return this.#internals.states.has('checked');
|
||||||
|
}
|
||||||
|
set checked(flag) {
|
||||||
|
if (flag) {
|
||||||
|
this.#internals.states.add('checked');
|
||||||
|
} else {
|
||||||
|
this.#internals.states.delete('checked');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_onClick(event) {
|
||||||
|
this.checked = !this.checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
See [benchmark](https://github.com/asamuzaK/domSelector/actions/workflows/benchmark.yml) for the latest results.
|
||||||
|
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
The following resources have been of great help in the development of the DOM Selector.
|
||||||
|
|
||||||
|
- [CSSTree](https://github.com/csstree/csstree)
|
||||||
|
- [selery](https://github.com/danburzo/selery)
|
||||||
|
- [jsdom](https://github.com/jsdom/jsdom)
|
||||||
|
- [nwsapi](https://github.com/dperini/nwsapi)
|
||||||
|
|
||||||
|
---
|
||||||
|
Copyright (c) 2023 [asamuzaK (Kazz)](https://github.com/asamuzaK/)
|
||||||
|
|
||||||
|
|
||||||
|
[1]: #matches
|
||||||
|
[2]: #parameters
|
||||||
|
[3]: #closest
|
||||||
|
[4]: #parameters-1
|
||||||
|
[5]: #queryselector
|
||||||
|
[6]: #parameters-2
|
||||||
|
[7]: #queryselectorall
|
||||||
|
[8]: #parameters-3
|
||||||
|
[59]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
|
||||||
|
[60]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
|
||||||
|
[61]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
|
||||||
|
[62]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
|
||||||
|
[63]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined
|
||||||
|
[64]: https://developer.mozilla.org/docs/Web/API/Element/matches
|
||||||
|
[65]: https://developer.mozilla.org/docs/Web/API/Element/closest
|
||||||
|
[66]: https://developer.mozilla.org/docs/Web/API/Document/querySelector
|
||||||
|
[67]: https://developer.mozilla.org/docs/Web/API/DocumentFragment/querySelector
|
||||||
|
[68]: https://developer.mozilla.org/docs/Web/API/Element/querySelector
|
||||||
|
[69]: https://developer.mozilla.org/docs/Web/API/Document/querySelectorAll
|
||||||
|
[70]: https://developer.mozilla.org/docs/Web/API/DocumentFragment/querySelectorAll
|
||||||
|
[71]: https://developer.mozilla.org/docs/Web/API/Element/querySelectorAll
|
||||||
81
web/node_modules/@asamuzakjp/dom-selector/package.json
generated
vendored
Normal file
81
web/node_modules/@asamuzakjp/dom-selector/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"name": "@asamuzakjp/dom-selector",
|
||||||
|
"description": "A CSS selector engine.",
|
||||||
|
"author": "asamuzaK",
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://github.com/asamuzaK/domSelector#readme",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/asamuzaK/domSelector/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/asamuzaK/domSelector.git"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"src",
|
||||||
|
"types"
|
||||||
|
],
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
"import": {
|
||||||
|
"types": "./types/index.d.ts",
|
||||||
|
"default": "./src/index.js"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"types": "./dist/cjs/index.d.cts",
|
||||||
|
"default": "./dist/cjs/index.cjs"
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"types": "./dist/cjs/types/index.d.cts",
|
||||||
|
"default": "./dist/cjs/index.cjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"types": "types/index.d.ts",
|
||||||
|
"dependencies": {
|
||||||
|
"@asamuzakjp/nwsapi": "^2.3.9",
|
||||||
|
"bidi-js": "^1.0.3",
|
||||||
|
"css-tree": "^3.1.0",
|
||||||
|
"is-potential-custom-element-name": "^1.0.1",
|
||||||
|
"lru-cache": "^11.2.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/css-tree": "^2.3.11",
|
||||||
|
"benchmark": "^2.1.4",
|
||||||
|
"c8": "^10.1.3",
|
||||||
|
"chai": "^6.2.2",
|
||||||
|
"commander": "^14.0.3",
|
||||||
|
"esbuild": "^0.27.3",
|
||||||
|
"eslint": "^9.39.2",
|
||||||
|
"eslint-config-prettier": "^10.1.8",
|
||||||
|
"eslint-plugin-jsdoc": "^62.5.4",
|
||||||
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
|
"eslint-plugin-regexp": "^3.0.0",
|
||||||
|
"eslint-plugin-unicorn": "^63.0.0",
|
||||||
|
"globals": "^17.3.0",
|
||||||
|
"jsdom": "^28.0.0",
|
||||||
|
"mocha": "^11.7.5",
|
||||||
|
"neostandard": "^0.12.2",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"sinon": "^21.0.1",
|
||||||
|
"tsup": "^8.5.1",
|
||||||
|
"typescript": "^5.9.3",
|
||||||
|
"wpt-runner": "^6.1.0"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"jsdom": "$jsdom"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"bench": "node benchmark/bench.js",
|
||||||
|
"bench:sizzle": "node benchmark/bench-sizzle.js",
|
||||||
|
"build": "npm run tsc && npm run lint && npm test && npm run bundle && npm run test:cjs",
|
||||||
|
"bundle": "tsup src/index.js --format=cjs --platform=node --outDir=dist/cjs/ --sourcemap --dts",
|
||||||
|
"lint": "eslint --fix .",
|
||||||
|
"test": "c8 --reporter=text mocha --parallel --exit test/**/*.test.js",
|
||||||
|
"test:cjs": "mocha --exit test/index.test.cjs",
|
||||||
|
"test:wpt": "node test/wpt/wpt-runner.js",
|
||||||
|
"tsc": "node scripts/index clean --dir=types -i && npx tsc",
|
||||||
|
"update:wpt": "git submodule update --init --recursive --remote"
|
||||||
|
},
|
||||||
|
"version": "6.8.1"
|
||||||
|
}
|
||||||
336
web/node_modules/@asamuzakjp/dom-selector/src/index.js
generated
vendored
Normal file
336
web/node_modules/@asamuzakjp/dom-selector/src/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1,336 @@
|
||||||
|
/*!
|
||||||
|
* DOM Selector - A CSS selector engine.
|
||||||
|
* @license MIT
|
||||||
|
* @copyright asamuzaK (Kazz)
|
||||||
|
* @see {@link https://github.com/asamuzaK/domSelector/blob/main/LICENSE}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* import */
|
||||||
|
import { LRUCache } from 'lru-cache';
|
||||||
|
import { Finder } from './js/finder.js';
|
||||||
|
import { filterSelector, getType, initNwsapi } from './js/utility.js';
|
||||||
|
|
||||||
|
/* constants */
|
||||||
|
import {
|
||||||
|
DOCUMENT_NODE,
|
||||||
|
DOCUMENT_FRAGMENT_NODE,
|
||||||
|
ELEMENT_NODE,
|
||||||
|
TARGET_ALL,
|
||||||
|
TARGET_FIRST,
|
||||||
|
TARGET_LINEAL,
|
||||||
|
TARGET_SELF
|
||||||
|
} from './js/constant.js';
|
||||||
|
const MAX_CACHE = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} CheckResult
|
||||||
|
* @property {boolean} match - The match result.
|
||||||
|
* @property {string?} pseudoElement - The pseudo-element, if any.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* DOMSelector */
|
||||||
|
export class DOMSelector {
|
||||||
|
/* private fields */
|
||||||
|
#window;
|
||||||
|
#document;
|
||||||
|
#finder;
|
||||||
|
#idlUtils;
|
||||||
|
#nwsapi;
|
||||||
|
#cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of DOMSelector.
|
||||||
|
* @param {Window} window - The window object.
|
||||||
|
* @param {Document} document - The document object.
|
||||||
|
* @param {object} [opt] - Options.
|
||||||
|
*/
|
||||||
|
constructor(window, document, opt = {}) {
|
||||||
|
const { idlUtils } = opt;
|
||||||
|
this.#window = window;
|
||||||
|
this.#document = document ?? window.document;
|
||||||
|
this.#finder = new Finder(window);
|
||||||
|
this.#idlUtils = idlUtils;
|
||||||
|
this.#nwsapi = initNwsapi(window, document);
|
||||||
|
this.#cache = new LRUCache({
|
||||||
|
max: MAX_CACHE
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the internal cache of finder results.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
clear = () => {
|
||||||
|
this.#finder.clearResults(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an element matches a CSS selector.
|
||||||
|
* @param {string} selector - The CSS selector to check against.
|
||||||
|
* @param {Element} node - The element node to check.
|
||||||
|
* @param {object} [opt] - Optional parameters.
|
||||||
|
* @returns {CheckResult} An object containing the check result.
|
||||||
|
*/
|
||||||
|
check = (selector, node, opt = {}) => {
|
||||||
|
if (!node?.nodeType) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
} else if (node.nodeType !== ELEMENT_NODE) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
const document = node.ownerDocument;
|
||||||
|
if (
|
||||||
|
document === this.#document &&
|
||||||
|
document.contentType === 'text/html' &&
|
||||||
|
document.documentElement &&
|
||||||
|
node.parentNode
|
||||||
|
) {
|
||||||
|
const cacheKey = `check_${selector}`;
|
||||||
|
let filterMatches = false;
|
||||||
|
if (this.#cache.has(cacheKey)) {
|
||||||
|
filterMatches = this.#cache.get(cacheKey);
|
||||||
|
} else {
|
||||||
|
filterMatches = filterSelector(selector, TARGET_SELF);
|
||||||
|
this.#cache.set(cacheKey, filterMatches);
|
||||||
|
}
|
||||||
|
if (filterMatches) {
|
||||||
|
try {
|
||||||
|
const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
|
||||||
|
const match = this.#nwsapi.match(selector, n);
|
||||||
|
let ast = null;
|
||||||
|
if (match) {
|
||||||
|
const astCacheKey = `check_ast_${selector}`;
|
||||||
|
if (this.#cache.has(astCacheKey)) {
|
||||||
|
ast = this.#cache.get(astCacheKey);
|
||||||
|
} else {
|
||||||
|
ast = this.#finder.getAST(selector);
|
||||||
|
this.#cache.set(astCacheKey, ast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
match,
|
||||||
|
ast,
|
||||||
|
pseudoElement: null
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
if (this.#idlUtils) {
|
||||||
|
node = this.#idlUtils.wrapperForImpl(node);
|
||||||
|
}
|
||||||
|
opt.check = true;
|
||||||
|
opt.noexept = true;
|
||||||
|
opt.warn = false;
|
||||||
|
this.#finder.setup(selector, node, opt);
|
||||||
|
res = this.#finder.find(TARGET_SELF);
|
||||||
|
} catch (e) {
|
||||||
|
this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the element matches the selector.
|
||||||
|
* @param {string} selector - The CSS selector to match against.
|
||||||
|
* @param {Element} node - The element node to test.
|
||||||
|
* @param {object} [opt] - Optional parameters.
|
||||||
|
* @returns {boolean} `true` if the element matches, or `false` otherwise.
|
||||||
|
*/
|
||||||
|
matches = (selector, node, opt = {}) => {
|
||||||
|
if (!node?.nodeType) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
} else if (node.nodeType !== ELEMENT_NODE) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
const document = node.ownerDocument;
|
||||||
|
if (
|
||||||
|
document === this.#document &&
|
||||||
|
document.contentType === 'text/html' &&
|
||||||
|
document.documentElement &&
|
||||||
|
node.parentNode
|
||||||
|
) {
|
||||||
|
const cacheKey = `matches_${selector}`;
|
||||||
|
let filterMatches = false;
|
||||||
|
if (this.#cache.has(cacheKey)) {
|
||||||
|
filterMatches = this.#cache.get(cacheKey);
|
||||||
|
} else {
|
||||||
|
filterMatches = filterSelector(selector, TARGET_SELF);
|
||||||
|
this.#cache.set(cacheKey, filterMatches);
|
||||||
|
}
|
||||||
|
if (filterMatches) {
|
||||||
|
try {
|
||||||
|
const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
|
||||||
|
const res = this.#nwsapi.match(selector, n);
|
||||||
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
if (this.#idlUtils) {
|
||||||
|
node = this.#idlUtils.wrapperForImpl(node);
|
||||||
|
}
|
||||||
|
this.#finder.setup(selector, node, opt);
|
||||||
|
const nodes = this.#finder.find(TARGET_SELF);
|
||||||
|
res = nodes.size;
|
||||||
|
} catch (e) {
|
||||||
|
this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
return !!res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traverses up the DOM tree to find the first node that matches the selector.
|
||||||
|
* @param {string} selector - The CSS selector to match against.
|
||||||
|
* @param {Element} node - The element from which to start traversing.
|
||||||
|
* @param {object} [opt] - Optional parameters.
|
||||||
|
* @returns {?Element} The first matching ancestor element, or `null`.
|
||||||
|
*/
|
||||||
|
closest = (selector, node, opt = {}) => {
|
||||||
|
if (!node?.nodeType) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
} else if (node.nodeType !== ELEMENT_NODE) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected node ${node.nodeName}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
const document = node.ownerDocument;
|
||||||
|
if (
|
||||||
|
document === this.#document &&
|
||||||
|
document.contentType === 'text/html' &&
|
||||||
|
document.documentElement &&
|
||||||
|
node.parentNode
|
||||||
|
) {
|
||||||
|
const cacheKey = `closest_${selector}`;
|
||||||
|
let filterMatches = false;
|
||||||
|
if (this.#cache.has(cacheKey)) {
|
||||||
|
filterMatches = this.#cache.get(cacheKey);
|
||||||
|
} else {
|
||||||
|
filterMatches = filterSelector(selector, TARGET_LINEAL);
|
||||||
|
this.#cache.set(cacheKey, filterMatches);
|
||||||
|
}
|
||||||
|
if (filterMatches) {
|
||||||
|
try {
|
||||||
|
const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
|
||||||
|
const res = this.#nwsapi.closest(selector, n);
|
||||||
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
if (this.#idlUtils) {
|
||||||
|
node = this.#idlUtils.wrapperForImpl(node);
|
||||||
|
}
|
||||||
|
this.#finder.setup(selector, node, opt);
|
||||||
|
const nodes = this.#finder.find(TARGET_LINEAL);
|
||||||
|
if (nodes.size) {
|
||||||
|
let refNode = node;
|
||||||
|
while (refNode) {
|
||||||
|
if (nodes.has(refNode)) {
|
||||||
|
res = refNode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
refNode = refNode.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
return res ?? null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the first element within the subtree that matches the selector.
|
||||||
|
* @param {string} selector - The CSS selector to match.
|
||||||
|
* @param {Document|DocumentFragment|Element} node - The node to find within.
|
||||||
|
* @param {object} [opt] - Optional parameters.
|
||||||
|
* @returns {?Element} The first matching element, or `null`.
|
||||||
|
*/
|
||||||
|
querySelector = (selector, node, opt = {}) => {
|
||||||
|
if (!node?.nodeType) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
if (this.#idlUtils) {
|
||||||
|
node = this.#idlUtils.wrapperForImpl(node);
|
||||||
|
}
|
||||||
|
this.#finder.setup(selector, node, opt);
|
||||||
|
const nodes = this.#finder.find(TARGET_FIRST);
|
||||||
|
if (nodes.size) {
|
||||||
|
[res] = [...nodes];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
return res ?? null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of elements within the subtree that match the selector.
|
||||||
|
* Note: This method returns an Array, not a NodeList.
|
||||||
|
* @param {string} selector - The CSS selector to match.
|
||||||
|
* @param {Document|DocumentFragment|Element} node - The node to find within.
|
||||||
|
* @param {object} [opt] - Optional parameters.
|
||||||
|
* @returns {Array<Element>} An array of elements, or an empty array.
|
||||||
|
*/
|
||||||
|
querySelectorAll = (selector, node, opt = {}) => {
|
||||||
|
if (!node?.nodeType) {
|
||||||
|
const e = new this.#window.TypeError(`Unexpected type ${getType(node)}`);
|
||||||
|
return this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
const document =
|
||||||
|
node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument;
|
||||||
|
if (
|
||||||
|
document === this.#document &&
|
||||||
|
document.contentType === 'text/html' &&
|
||||||
|
document.documentElement &&
|
||||||
|
(node.nodeType !== DOCUMENT_FRAGMENT_NODE || !node.host)
|
||||||
|
) {
|
||||||
|
const cacheKey = `querySelectorAll_${selector}`;
|
||||||
|
let filterMatches = false;
|
||||||
|
if (this.#cache.has(cacheKey)) {
|
||||||
|
filterMatches = this.#cache.get(cacheKey);
|
||||||
|
} else {
|
||||||
|
filterMatches = filterSelector(selector, TARGET_ALL);
|
||||||
|
this.#cache.set(cacheKey, filterMatches);
|
||||||
|
}
|
||||||
|
if (filterMatches) {
|
||||||
|
try {
|
||||||
|
const n = this.#idlUtils ? this.#idlUtils.wrapperForImpl(node) : node;
|
||||||
|
const res = this.#nwsapi.select(selector, n);
|
||||||
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
if (this.#idlUtils) {
|
||||||
|
node = this.#idlUtils.wrapperForImpl(node);
|
||||||
|
}
|
||||||
|
this.#finder.setup(selector, node, opt);
|
||||||
|
const nodes = this.#finder.find(TARGET_ALL);
|
||||||
|
if (nodes.size) {
|
||||||
|
res = [...nodes];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.#finder.onError(e, opt);
|
||||||
|
}
|
||||||
|
return res ?? [];
|
||||||
|
};
|
||||||
|
}
|
||||||
129
web/node_modules/@asamuzakjp/dom-selector/src/js/constant.js
generated
vendored
Normal file
129
web/node_modules/@asamuzakjp/dom-selector/src/js/constant.js
generated
vendored
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
/**
|
||||||
|
* constant.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* string */
|
||||||
|
export const ATRULE = 'Atrule';
|
||||||
|
export const ATTR_SELECTOR = 'AttributeSelector';
|
||||||
|
export const CLASS_SELECTOR = 'ClassSelector';
|
||||||
|
export const COMBINATOR = 'Combinator';
|
||||||
|
export const IDENT = 'Identifier';
|
||||||
|
export const ID_SELECTOR = 'IdSelector';
|
||||||
|
export const NOT_SUPPORTED_ERR = 'NotSupportedError';
|
||||||
|
export const NTH = 'Nth';
|
||||||
|
export const OPERATOR = 'Operator';
|
||||||
|
export const PS_CLASS_SELECTOR = 'PseudoClassSelector';
|
||||||
|
export const PS_ELEMENT_SELECTOR = 'PseudoElementSelector';
|
||||||
|
export const RULE = 'Rule';
|
||||||
|
export const SCOPE = 'Scope';
|
||||||
|
export const SELECTOR = 'Selector';
|
||||||
|
export const SELECTOR_LIST = 'SelectorList';
|
||||||
|
export const STRING = 'String';
|
||||||
|
export const SYNTAX_ERR = 'SyntaxError';
|
||||||
|
export const TARGET_ALL = 'all';
|
||||||
|
export const TARGET_FIRST = 'first';
|
||||||
|
export const TARGET_LINEAL = 'lineal';
|
||||||
|
export const TARGET_SELF = 'self';
|
||||||
|
export const TYPE_SELECTOR = 'TypeSelector';
|
||||||
|
|
||||||
|
/* numeric */
|
||||||
|
export const BIT_01 = 1;
|
||||||
|
export const BIT_02 = 2;
|
||||||
|
export const BIT_04 = 4;
|
||||||
|
export const BIT_08 = 8;
|
||||||
|
export const BIT_16 = 0x10;
|
||||||
|
export const BIT_32 = 0x20;
|
||||||
|
export const BIT_FFFF = 0xffff;
|
||||||
|
export const DUO = 2;
|
||||||
|
export const HEX = 16;
|
||||||
|
export const TYPE_FROM = 8;
|
||||||
|
export const TYPE_TO = -1;
|
||||||
|
|
||||||
|
/* Node */
|
||||||
|
export const ELEMENT_NODE = 1;
|
||||||
|
export const TEXT_NODE = 3;
|
||||||
|
export const DOCUMENT_NODE = 9;
|
||||||
|
export const DOCUMENT_FRAGMENT_NODE = 11;
|
||||||
|
export const DOCUMENT_POSITION_PRECEDING = 2;
|
||||||
|
export const DOCUMENT_POSITION_CONTAINS = 8;
|
||||||
|
export const DOCUMENT_POSITION_CONTAINED_BY = 0x10;
|
||||||
|
|
||||||
|
/* NodeFilter */
|
||||||
|
export const SHOW_ALL = 0xffffffff;
|
||||||
|
export const SHOW_CONTAINER = 0x501;
|
||||||
|
export const SHOW_DOCUMENT = 0x100;
|
||||||
|
export const SHOW_DOCUMENT_FRAGMENT = 0x400;
|
||||||
|
export const SHOW_ELEMENT = 1;
|
||||||
|
|
||||||
|
/* selectors */
|
||||||
|
export const ALPHA_NUM = '[A-Z\\d]+';
|
||||||
|
export const CHILD_IDX = '(?:first|last|only)-(?:child|of-type)';
|
||||||
|
export const DIGIT = '(?:0|[1-9]\\d*)';
|
||||||
|
export const LANG_PART = `(?:-${ALPHA_NUM})*`;
|
||||||
|
export const PSEUDO_CLASS = `(?:any-)?link|${CHILD_IDX}|checked|empty|indeterminate|read-(?:only|write)|target`;
|
||||||
|
export const ANB = `[+-]?(?:${DIGIT}n?|n)|(?:[+-]?${DIGIT})?n\\s*[+-]\\s*${DIGIT}`;
|
||||||
|
// combinators
|
||||||
|
export const COMBO = '\\s?[\\s>~+]\\s?';
|
||||||
|
export const DESCEND = '\\s?[\\s>]\\s?';
|
||||||
|
export const SIBLING = '\\s?[+~]\\s?';
|
||||||
|
// LOGIC_IS: :is()
|
||||||
|
export const LOGIC_IS = `:is\\(\\s*[^)]+\\s*\\)`;
|
||||||
|
// N_TH: excludes An+B with selector list, e.g. :nth-child(2n+1 of .foo)
|
||||||
|
export const N_TH = `nth-(?:last-)?(?:child|of-type)\\(\\s*(?:even|odd|${ANB})\\s*\\)`;
|
||||||
|
// SUB_TYPE: attr, id, class, pseudo-class, note that [foo|=bar] is excluded
|
||||||
|
export const SUB_TYPE = '\\[[^|\\]]+\\]|[#.:][\\w-]+';
|
||||||
|
export const SUB_TYPE_WO_PSEUDO = '\\[[^|\\]]+\\]|[#.][\\w-]+';
|
||||||
|
// TAG_TYPE: *, tag
|
||||||
|
export const TAG_TYPE = '\\*|[A-Za-z][\\w-]*';
|
||||||
|
export const TAG_TYPE_I = '\\*|[A-Z][\\w-]*';
|
||||||
|
export const COMPOUND = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE})+)`;
|
||||||
|
export const COMPOUND_L = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE}|${LOGIC_IS})+)`;
|
||||||
|
export const COMPOUND_I = `(?:${TAG_TYPE_I}|(?:${TAG_TYPE_I})?(?:${SUB_TYPE})+)`;
|
||||||
|
export const COMPOUND_WO_PSEUDO = `(?:${TAG_TYPE}|(?:${TAG_TYPE})?(?:${SUB_TYPE_WO_PSEUDO})+)`;
|
||||||
|
export const COMPLEX = `${COMPOUND}(?:${COMBO}${COMPOUND})*`;
|
||||||
|
export const COMPLEX_L = `${COMPOUND_L}(?:${COMBO}${COMPOUND_L})*`;
|
||||||
|
export const HAS_COMPOUND = `has\\([\\s>]?\\s*${COMPOUND_WO_PSEUDO}\\s*\\)`;
|
||||||
|
export const LOGIC_COMPOUND = `(?:is|not)\\(\\s*${COMPOUND_L}(?:\\s*,\\s*${COMPOUND_L})*\\s*\\)`;
|
||||||
|
export const LOGIC_COMPLEX = `(?:is|not)\\(\\s*${COMPLEX_L}(?:\\s*,\\s*${COMPLEX_L})*\\s*\\)`;
|
||||||
|
|
||||||
|
/* forms and input types */
|
||||||
|
export const FORM_PARTS = Object.freeze([
|
||||||
|
'button',
|
||||||
|
'input',
|
||||||
|
'select',
|
||||||
|
'textarea'
|
||||||
|
]);
|
||||||
|
export const INPUT_BUTTON = Object.freeze(['button', 'reset', 'submit']);
|
||||||
|
export const INPUT_CHECK = Object.freeze(['checkbox', 'radio']);
|
||||||
|
export const INPUT_DATE = Object.freeze([
|
||||||
|
'date',
|
||||||
|
'datetime-local',
|
||||||
|
'month',
|
||||||
|
'time',
|
||||||
|
'week'
|
||||||
|
]);
|
||||||
|
export const INPUT_TEXT = Object.freeze([
|
||||||
|
'email',
|
||||||
|
'password',
|
||||||
|
'search',
|
||||||
|
'tel',
|
||||||
|
'text',
|
||||||
|
'url'
|
||||||
|
]);
|
||||||
|
export const INPUT_EDIT = Object.freeze([
|
||||||
|
...INPUT_DATE,
|
||||||
|
...INPUT_TEXT,
|
||||||
|
'number'
|
||||||
|
]);
|
||||||
|
export const INPUT_LTR = Object.freeze([
|
||||||
|
...INPUT_CHECK,
|
||||||
|
'color',
|
||||||
|
'date',
|
||||||
|
'image',
|
||||||
|
'number',
|
||||||
|
'range',
|
||||||
|
'time'
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* logical combination pseudo-classes */
|
||||||
|
export const KEYS_LOGICAL = new Set(['has', 'is', 'not', 'where']);
|
||||||
3139
web/node_modules/@asamuzakjp/dom-selector/src/js/finder.js
generated
vendored
Normal file
3139
web/node_modules/@asamuzakjp/dom-selector/src/js/finder.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue