version 02
This commit is contained in:
parent
50469288e1
commit
deb60c112f
estilo.cssindex.html
node_modules
.package-lock.json
.vite/deps
_metadata.jsonchunk-FFYJRC36.js.mapchunk-ZPUNMYDO.jschunk-ZPUNMYDO.js.mapra-core.jsra-core.js.mapra-data-local-forage.js
@asamuzakjp/css-color
@babel
core
generator
helper-compilation-targets
helper-create-class-features-plugin
lib
package.jsonhelper-create-regexp-features-plugin
helper-define-polyfill-provider
esm
lib
node_modules
|
@ -0,0 +1,54 @@
|
|||
.footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 15px;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
background: white;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.todo-count {
|
||||
flex: 1;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.filters {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.filters li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.filters a {
|
||||
padding: 3px 7px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.filters a.selected {
|
||||
border-color: rgba(175, 47, 47, 0.2);
|
||||
}
|
||||
|
||||
.clear-completed {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
text-align: right;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #cc9a9a;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
<link rel="icon" href="/favicon.ico">
|
||||
<link rel="apple-touch-icon" href="/180.png" sizes="180x180">
|
||||
<title>React Admin ToDo</title>
|
||||
<link rel="stylesheet" href="/estilo.css" />
|
||||
<meta name="description" content="A ToDo application implemented with React Admin" />
|
||||
</head>
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,73 +1,73 @@
|
|||
{
|
||||
"hash": "c02679aa",
|
||||
"configHash": "475f182c",
|
||||
"lockfileHash": "07ad5253",
|
||||
"browserHash": "80c74427",
|
||||
"hash": "536f3c70",
|
||||
"configHash": "4b3d8f8b",
|
||||
"lockfileHash": "0b0e3dce",
|
||||
"browserHash": "7f27dcc2",
|
||||
"optimized": {
|
||||
"react": {
|
||||
"src": "../../react/index.js",
|
||||
"file": "react.js",
|
||||
"fileHash": "f9bb28ca",
|
||||
"fileHash": "8db10fd1",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react-dom": {
|
||||
"src": "../../react-dom/index.js",
|
||||
"file": "react-dom.js",
|
||||
"fileHash": "6267f293",
|
||||
"fileHash": "5df02561",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-dev-runtime": {
|
||||
"src": "../../react/jsx-dev-runtime.js",
|
||||
"file": "react_jsx-dev-runtime.js",
|
||||
"fileHash": "761aecf0",
|
||||
"fileHash": "454d74b2",
|
||||
"needsInterop": true
|
||||
},
|
||||
"react/jsx-runtime": {
|
||||
"src": "../../react/jsx-runtime.js",
|
||||
"file": "react_jsx-runtime.js",
|
||||
"fileHash": "992e0135",
|
||||
"fileHash": "f9fb0493",
|
||||
"needsInterop": true
|
||||
},
|
||||
"clsx": {
|
||||
"src": "../../clsx/dist/clsx.mjs",
|
||||
"file": "clsx.js",
|
||||
"fileHash": "ff4e198a",
|
||||
"fileHash": "0acaaaf7",
|
||||
"needsInterop": false
|
||||
},
|
||||
"localforage": {
|
||||
"src": "../../localforage/dist/localforage.js",
|
||||
"file": "localforage.js",
|
||||
"fileHash": "d190f5b3",
|
||||
"fileHash": "e76b88f1",
|
||||
"needsInterop": true
|
||||
},
|
||||
"ra-core": {
|
||||
"src": "../../ra-core/dist/esm/index.js",
|
||||
"file": "ra-core.js",
|
||||
"fileHash": "7c2c0698",
|
||||
"fileHash": "6a13df7d",
|
||||
"needsInterop": false
|
||||
},
|
||||
"ra-data-local-forage": {
|
||||
"src": "../../ra-data-local-forage/dist/esm/index.js",
|
||||
"file": "ra-data-local-forage.js",
|
||||
"fileHash": "ec695e6c",
|
||||
"fileHash": "cd41ed79",
|
||||
"needsInterop": false
|
||||
},
|
||||
"react-dom/client": {
|
||||
"src": "../../react-dom/client.js",
|
||||
"file": "react-dom_client.js",
|
||||
"fileHash": "9229e105",
|
||||
"fileHash": "b0b6a4aa",
|
||||
"needsInterop": true
|
||||
}
|
||||
},
|
||||
"chunks": {
|
||||
"chunk-CPGX2YFR": {
|
||||
"file": "chunk-CPGX2YFR.js"
|
||||
},
|
||||
"chunk-L7VO4W5A": {
|
||||
"file": "chunk-L7VO4W5A.js"
|
||||
},
|
||||
"chunk-FFYJRC36": {
|
||||
"file": "chunk-FFYJRC36.js"
|
||||
"chunk-CPGX2YFR": {
|
||||
"file": "chunk-CPGX2YFR.js"
|
||||
},
|
||||
"chunk-ZPUNMYDO": {
|
||||
"file": "chunk-ZPUNMYDO.js"
|
||||
},
|
||||
"chunk-MUYQS5ZK": {
|
||||
"file": "chunk-MUYQS5ZK.js"
|
||||
|
|
File diff suppressed because one or more lines are too long
76
node_modules/.vite/deps/chunk-FFYJRC36.js → node_modules/.vite/deps/chunk-ZPUNMYDO.js
generated
vendored
76
node_modules/.vite/deps/chunk-FFYJRC36.js → node_modules/.vite/deps/chunk-ZPUNMYDO.js
generated
vendored
|
@ -2,20 +2,6 @@ import {
|
|||
__commonJS
|
||||
} from "./chunk-SNAQBZPT.js";
|
||||
|
||||
// node_modules/lodash/_arrayMap.js
|
||||
var require_arrayMap = __commonJS({
|
||||
"node_modules/lodash/_arrayMap.js"(exports, module) {
|
||||
function arrayMap(array, iteratee) {
|
||||
var index = -1, length = array == null ? 0 : array.length, result = Array(length);
|
||||
while (++index < length) {
|
||||
result[index] = iteratee(array[index], index, array);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
module.exports = arrayMap;
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/lodash/_freeGlobal.js
|
||||
var require_freeGlobal = __commonJS({
|
||||
"node_modules/lodash/_freeGlobal.js"(exports, module) {
|
||||
|
@ -615,6 +601,34 @@ var require_memoize = __commonJS({
|
|||
}
|
||||
});
|
||||
|
||||
// node_modules/lodash/_arrayMap.js
|
||||
var require_arrayMap = __commonJS({
|
||||
"node_modules/lodash/_arrayMap.js"(exports, module) {
|
||||
function arrayMap(array, iteratee) {
|
||||
var index = -1, length = array == null ? 0 : array.length, result = Array(length);
|
||||
while (++index < length) {
|
||||
result[index] = iteratee(array[index], index, array);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
module.exports = arrayMap;
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/lodash/_isIndex.js
|
||||
var require_isIndex = __commonJS({
|
||||
"node_modules/lodash/_isIndex.js"(exports, module) {
|
||||
var MAX_SAFE_INTEGER = 9007199254740991;
|
||||
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
||||
function isIndex(value, length) {
|
||||
var type = typeof value;
|
||||
length = length == null ? MAX_SAFE_INTEGER : length;
|
||||
return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
|
||||
}
|
||||
module.exports = isIndex;
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/lodash/isArray.js
|
||||
var require_isArray = __commonJS({
|
||||
"node_modules/lodash/isArray.js"(exports, module) {
|
||||
|
@ -806,20 +820,6 @@ var require_get = __commonJS({
|
|||
}
|
||||
});
|
||||
|
||||
// node_modules/lodash/_isIndex.js
|
||||
var require_isIndex = __commonJS({
|
||||
"node_modules/lodash/_isIndex.js"(exports, module) {
|
||||
var MAX_SAFE_INTEGER = 9007199254740991;
|
||||
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
||||
function isIndex(value, length) {
|
||||
var type = typeof value;
|
||||
length = length == null ? MAX_SAFE_INTEGER : length;
|
||||
return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
|
||||
}
|
||||
module.exports = isIndex;
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/lodash/_arrayPush.js
|
||||
var require_arrayPush = __commonJS({
|
||||
"node_modules/lodash/_arrayPush.js"(exports, module) {
|
||||
|
@ -1130,36 +1130,36 @@ var require_baseUnset = __commonJS({
|
|||
});
|
||||
|
||||
export {
|
||||
require_arrayMap,
|
||||
require_isArray,
|
||||
require_freeGlobal,
|
||||
require_root,
|
||||
require_Symbol,
|
||||
require_baseGetTag,
|
||||
require_isObjectLike,
|
||||
require_isSymbol,
|
||||
require_isObject,
|
||||
require_isFunction,
|
||||
require_toSource,
|
||||
require_getNative,
|
||||
require_defineProperty,
|
||||
require_eq,
|
||||
require_isArray,
|
||||
require_isObjectLike,
|
||||
require_isSymbol,
|
||||
require_ListCache,
|
||||
require_Map,
|
||||
require_MapCache,
|
||||
require_memoize,
|
||||
require_arrayMap,
|
||||
require_castPath,
|
||||
require_isIndex,
|
||||
require_toKey,
|
||||
require_baseGet,
|
||||
require_get,
|
||||
require_baseUnset,
|
||||
require_isIndex,
|
||||
require_get,
|
||||
require_arrayPush,
|
||||
require_isArguments,
|
||||
require_baseFlatten,
|
||||
require_overRest,
|
||||
require_defineProperty,
|
||||
require_identity,
|
||||
require_overRest,
|
||||
require_setToString,
|
||||
require_baseFlatten,
|
||||
require_flatRest
|
||||
};
|
||||
//# sourceMappingURL=chunk-FFYJRC36.js.map
|
||||
//# sourceMappingURL=chunk-ZPUNMYDO.js.map
|
File diff suppressed because one or more lines are too long
|
@ -32,7 +32,7 @@ import {
|
|||
require_setToString,
|
||||
require_toKey,
|
||||
require_toSource
|
||||
} from "./chunk-FFYJRC36.js";
|
||||
} from "./chunk-ZPUNMYDO.js";
|
||||
import {
|
||||
require_react_dom
|
||||
} from "./chunk-MUYQS5ZK.js";
|
||||
|
@ -3957,9 +3957,9 @@ var require_defaults = __commonJS({
|
|||
}
|
||||
});
|
||||
|
||||
// node_modules/react-is/cjs/react-is.development.js
|
||||
// node_modules/ra-core/node_modules/react-is/cjs/react-is.development.js
|
||||
var require_react_is_development = __commonJS({
|
||||
"node_modules/react-is/cjs/react-is.development.js"(exports) {
|
||||
"node_modules/ra-core/node_modules/react-is/cjs/react-is.development.js"(exports) {
|
||||
"use strict";
|
||||
(function() {
|
||||
function typeOf(object) {
|
||||
|
@ -4051,9 +4051,9 @@ var require_react_is_development = __commonJS({
|
|||
}
|
||||
});
|
||||
|
||||
// node_modules/react-is/index.js
|
||||
// node_modules/ra-core/node_modules/react-is/index.js
|
||||
var require_react_is = __commonJS({
|
||||
"node_modules/react-is/index.js"(exports, module) {
|
||||
"node_modules/ra-core/node_modules/react-is/index.js"(exports, module) {
|
||||
"use strict";
|
||||
if (false) {
|
||||
module.exports = null;
|
||||
|
@ -7559,7 +7559,7 @@ function useInfiniteQuery(options, queryClient) {
|
|||
// node_modules/ra-core/dist/esm/auth/useLogout.js
|
||||
var import_react151 = __toESM(require_react());
|
||||
|
||||
// node_modules/react-router/dist/development/chunk-HA7DTUK3.mjs
|
||||
// node_modules/react-router/dist/development/chunk-GNGMS2XR.mjs
|
||||
var React32 = __toESM(require_react(), 1);
|
||||
var React11 = __toESM(require_react(), 1);
|
||||
var React22 = __toESM(require_react(), 1);
|
||||
|
@ -7570,7 +7570,7 @@ var React42 = __toESM(require_react(), 1);
|
|||
// node_modules/turbo-stream/dist/turbo-stream.mjs
|
||||
var objectProtoNames = Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
|
||||
|
||||
// node_modules/react-router/dist/development/chunk-HA7DTUK3.mjs
|
||||
// node_modules/react-router/dist/development/chunk-GNGMS2XR.mjs
|
||||
var React82 = __toESM(require_react(), 1);
|
||||
var React72 = __toESM(require_react(), 1);
|
||||
var React52 = __toESM(require_react(), 1);
|
||||
|
@ -7580,6 +7580,12 @@ var React12 = __toESM(require_react(), 1);
|
|||
var React13 = __toESM(require_react(), 1);
|
||||
var import_cookie = __toESM(require_dist(), 1);
|
||||
var import_set_cookie_parser = __toESM(require_set_cookie(), 1);
|
||||
var __typeError = (msg) => {
|
||||
throw TypeError(msg);
|
||||
};
|
||||
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
||||
var __privateGet2 = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
||||
var __privateAdd2 = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
||||
var Action = ((Action2) => {
|
||||
Action2["Pop"] = "POP";
|
||||
Action2["Push"] = "PUSH";
|
||||
|
@ -7897,6 +7903,30 @@ function getUrlBasedHistory(getLocation, createHref2, validateLocation, options
|
|||
};
|
||||
return history;
|
||||
}
|
||||
var _map;
|
||||
var unstable_RouterContextProvider = class {
|
||||
constructor(init) {
|
||||
__privateAdd2(this, _map, /* @__PURE__ */ new Map());
|
||||
if (init) {
|
||||
for (let [context, value] of init) {
|
||||
this.set(context, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
get(context) {
|
||||
if (__privateGet2(this, _map).has(context)) {
|
||||
return __privateGet2(this, _map).get(context);
|
||||
}
|
||||
if (context.defaultValue !== void 0) {
|
||||
return context.defaultValue;
|
||||
}
|
||||
throw new Error("No value found for context");
|
||||
}
|
||||
set(context, value) {
|
||||
__privateGet2(this, _map).set(context, value);
|
||||
}
|
||||
};
|
||||
_map = /* @__PURE__ */ new WeakMap();
|
||||
var immutableRouteKeys = /* @__PURE__ */ new Set([
|
||||
"lazy",
|
||||
"caseSensitive",
|
||||
|
@ -8391,9 +8421,9 @@ function createRouter(init) {
|
|||
);
|
||||
let inFlightDataRoutes;
|
||||
let basename = init.basename || "/";
|
||||
let dataStrategyImpl = init.dataStrategy || defaultDataStrategy;
|
||||
let patchRoutesOnNavigationImpl = init.patchRoutesOnNavigation;
|
||||
let dataStrategyImpl = init.dataStrategy || defaultDataStrategyWithMiddleware;
|
||||
let future = {
|
||||
unstable_middleware: false,
|
||||
...init.future
|
||||
};
|
||||
let unlistenHistory = null;
|
||||
|
@ -8405,7 +8435,7 @@ function createRouter(init) {
|
|||
let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
|
||||
let initialMatchesIsFOW = false;
|
||||
let initialErrors = null;
|
||||
if (initialMatches == null && !patchRoutesOnNavigationImpl) {
|
||||
if (initialMatches == null && !init.patchRoutesOnNavigation) {
|
||||
let error = getInternalRouterError(404, {
|
||||
pathname: init.history.location.pathname
|
||||
});
|
||||
|
@ -8837,6 +8867,9 @@ function createRouter(init) {
|
|||
pendingNavigationController.signal,
|
||||
opts && opts.submission
|
||||
);
|
||||
let scopedContext = new unstable_RouterContextProvider(
|
||||
init.unstable_getContext ? await init.unstable_getContext() : void 0
|
||||
);
|
||||
let pendingActionResult;
|
||||
if (opts && opts.pendingError) {
|
||||
pendingActionResult = [
|
||||
|
@ -8849,6 +8882,7 @@ function createRouter(init) {
|
|||
location,
|
||||
opts.submission,
|
||||
matches,
|
||||
scopedContext,
|
||||
fogOfWar.active,
|
||||
{ replace: opts.replace, flushSync: flushSync2 }
|
||||
);
|
||||
|
@ -8889,6 +8923,7 @@ function createRouter(init) {
|
|||
request,
|
||||
location,
|
||||
matches,
|
||||
scopedContext,
|
||||
fogOfWar.active,
|
||||
loadingNavigation,
|
||||
opts && opts.submission,
|
||||
|
@ -8909,7 +8944,7 @@ function createRouter(init) {
|
|||
errors
|
||||
});
|
||||
}
|
||||
async function handleAction(request, location, submission, matches, isFogOfWar, opts = {}) {
|
||||
async function handleAction(request, location, submission, matches, scopedContext, isFogOfWar, opts = {}) {
|
||||
interruptActiveLoads();
|
||||
let navigation = getSubmittingNavigation(location, submission);
|
||||
updateState({ navigation }, { flushSync: opts.flushSync === true });
|
||||
|
@ -8965,13 +9000,21 @@ function createRouter(init) {
|
|||
} else {
|
||||
let results = await callDataStrategy(
|
||||
"action",
|
||||
state,
|
||||
request,
|
||||
[actionMatch],
|
||||
matches,
|
||||
scopedContext,
|
||||
null
|
||||
);
|
||||
result = results[actionMatch.route.id];
|
||||
if (!result) {
|
||||
for (let match2 of matches) {
|
||||
if (results[match2.route.id]) {
|
||||
result = results[match2.route.id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (request.signal.aborted) {
|
||||
return { shortCircuited: true };
|
||||
}
|
||||
|
@ -9009,7 +9052,7 @@ function createRouter(init) {
|
|||
pendingActionResult: [actionMatch.route.id, result]
|
||||
};
|
||||
}
|
||||
async function handleLoaders(request, location, matches, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync2, pendingActionResult) {
|
||||
async function handleLoaders(request, location, matches, scopedContext, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace2, initialHydration, flushSync2, pendingActionResult) {
|
||||
let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);
|
||||
let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);
|
||||
let shouldUpdateNavigationState = !isUninterruptedRevalidation && !initialHydration;
|
||||
|
@ -9119,11 +9162,11 @@ function createRouter(init) {
|
|||
);
|
||||
}
|
||||
let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
|
||||
state,
|
||||
matches,
|
||||
matchesToLoad,
|
||||
revalidatingFetchers,
|
||||
request
|
||||
request,
|
||||
scopedContext
|
||||
);
|
||||
if (request.signal.aborted) {
|
||||
return { shortCircuited: true };
|
||||
|
@ -9231,6 +9274,9 @@ function createRouter(init) {
|
|||
return;
|
||||
}
|
||||
let match2 = getTargetMatch(matches, path);
|
||||
let scopedContext = new unstable_RouterContextProvider(
|
||||
init.unstable_getContext ? await init.unstable_getContext() : void 0
|
||||
);
|
||||
let preventScrollReset = (opts && opts.preventScrollReset) === true;
|
||||
if (submission && isMutationMethod(submission.formMethod)) {
|
||||
await handleFetcherAction(
|
||||
|
@ -9239,6 +9285,7 @@ function createRouter(init) {
|
|||
path,
|
||||
match2,
|
||||
matches,
|
||||
scopedContext,
|
||||
fogOfWar.active,
|
||||
flushSync2,
|
||||
preventScrollReset,
|
||||
|
@ -9253,13 +9300,14 @@ function createRouter(init) {
|
|||
path,
|
||||
match2,
|
||||
matches,
|
||||
scopedContext,
|
||||
fogOfWar.active,
|
||||
flushSync2,
|
||||
preventScrollReset,
|
||||
submission
|
||||
);
|
||||
}
|
||||
async function handleFetcherAction(key, routeId, path, match2, requestMatches, isFogOfWar, flushSync2, preventScrollReset, submission) {
|
||||
async function handleFetcherAction(key, routeId, path, match2, requestMatches, scopedContext, isFogOfWar, flushSync2, preventScrollReset, submission) {
|
||||
interruptActiveLoads();
|
||||
fetchLoadMatches.delete(key);
|
||||
function detectAndHandle405Error(m) {
|
||||
|
@ -9292,7 +9340,8 @@ function createRouter(init) {
|
|||
let discoverResult = await discoverRoutes(
|
||||
requestMatches,
|
||||
path,
|
||||
fetchRequest.signal
|
||||
fetchRequest.signal,
|
||||
key
|
||||
);
|
||||
if (discoverResult.type === "aborted") {
|
||||
return;
|
||||
|
@ -9319,10 +9368,10 @@ function createRouter(init) {
|
|||
let originatingLoadId = incrementingLoadId;
|
||||
let actionResults = await callDataStrategy(
|
||||
"action",
|
||||
state,
|
||||
fetchRequest,
|
||||
[match2],
|
||||
requestMatches,
|
||||
scopedContext,
|
||||
key
|
||||
);
|
||||
let actionResult = actionResults[match2.route.id];
|
||||
|
@ -9406,11 +9455,11 @@ function createRouter(init) {
|
|||
abortPendingFetchRevalidations
|
||||
);
|
||||
let { loaderResults, fetcherResults } = await callLoadersAndMaybeResolveData(
|
||||
state,
|
||||
matches,
|
||||
matchesToLoad,
|
||||
revalidatingFetchers,
|
||||
revalidationRequest
|
||||
revalidationRequest,
|
||||
scopedContext
|
||||
);
|
||||
if (abortController.signal.aborted) {
|
||||
return;
|
||||
|
@ -9477,7 +9526,7 @@ function createRouter(init) {
|
|||
isRevalidationRequired = false;
|
||||
}
|
||||
}
|
||||
async function handleFetcherLoader(key, routeId, path, match2, matches, isFogOfWar, flushSync2, preventScrollReset, submission) {
|
||||
async function handleFetcherLoader(key, routeId, path, match2, matches, scopedContext, isFogOfWar, flushSync2, preventScrollReset, submission) {
|
||||
let existingFetcher = state.fetchers.get(key);
|
||||
updateFetcherState(
|
||||
key,
|
||||
|
@ -9497,7 +9546,8 @@ function createRouter(init) {
|
|||
let discoverResult = await discoverRoutes(
|
||||
matches,
|
||||
path,
|
||||
fetchRequest.signal
|
||||
fetchRequest.signal,
|
||||
key
|
||||
);
|
||||
if (discoverResult.type === "aborted") {
|
||||
return;
|
||||
|
@ -9521,10 +9571,10 @@ function createRouter(init) {
|
|||
let originatingLoadId = incrementingLoadId;
|
||||
let results = await callDataStrategy(
|
||||
"loader",
|
||||
state,
|
||||
fetchRequest,
|
||||
[match2],
|
||||
matches,
|
||||
scopedContext,
|
||||
key
|
||||
);
|
||||
let result = results[match2.route.id];
|
||||
|
@ -9626,20 +9676,21 @@ function createRouter(init) {
|
|||
});
|
||||
}
|
||||
}
|
||||
async function callDataStrategy(type, state2, request, matchesToLoad, matches, fetcherKey) {
|
||||
async function callDataStrategy(type, request, matchesToLoad, matches, scopedContext, fetcherKey) {
|
||||
let results;
|
||||
let dataResults = {};
|
||||
try {
|
||||
results = await callDataStrategyImpl(
|
||||
dataStrategyImpl,
|
||||
type,
|
||||
state2,
|
||||
request,
|
||||
matchesToLoad,
|
||||
matches,
|
||||
fetcherKey,
|
||||
manifest,
|
||||
mapRouteProperties2
|
||||
mapRouteProperties2,
|
||||
scopedContext,
|
||||
future.unstable_middleware
|
||||
);
|
||||
} catch (e) {
|
||||
matchesToLoad.forEach((m) => {
|
||||
|
@ -9671,13 +9722,13 @@ function createRouter(init) {
|
|||
}
|
||||
return dataResults;
|
||||
}
|
||||
async function callLoadersAndMaybeResolveData(state2, matches, matchesToLoad, fetchersToLoad, request) {
|
||||
async function callLoadersAndMaybeResolveData(matches, matchesToLoad, fetchersToLoad, request, scopedContext) {
|
||||
let loaderResultsPromise = callDataStrategy(
|
||||
"loader",
|
||||
state2,
|
||||
request,
|
||||
matchesToLoad,
|
||||
matches,
|
||||
scopedContext,
|
||||
null
|
||||
);
|
||||
let fetcherResultsPromise = Promise.all(
|
||||
|
@ -9685,10 +9736,10 @@ function createRouter(init) {
|
|||
if (f.matches && f.match && f.controller) {
|
||||
let results = await callDataStrategy(
|
||||
"loader",
|
||||
state2,
|
||||
createClientSideRequest(init.history, f.path, f.controller.signal),
|
||||
[f.match],
|
||||
f.matches,
|
||||
scopedContext,
|
||||
f.key
|
||||
);
|
||||
let result = results[f.match.route.id];
|
||||
|
@ -9910,7 +9961,7 @@ function createRouter(init) {
|
|||
return null;
|
||||
}
|
||||
function checkFogOfWar(matches, routesToUse, pathname) {
|
||||
if (patchRoutesOnNavigationImpl) {
|
||||
if (init.patchRoutesOnNavigation) {
|
||||
if (!matches) {
|
||||
let fogMatches = matchRoutesImpl(
|
||||
routesToUse,
|
||||
|
@ -9933,8 +9984,8 @@ function createRouter(init) {
|
|||
}
|
||||
return { active: false, matches: null };
|
||||
}
|
||||
async function discoverRoutes(matches, pathname, signal) {
|
||||
if (!patchRoutesOnNavigationImpl) {
|
||||
async function discoverRoutes(matches, pathname, signal, fetcherKey) {
|
||||
if (!init.patchRoutesOnNavigation) {
|
||||
return { type: "success", matches };
|
||||
}
|
||||
let partialMatches = matches;
|
||||
|
@ -9943,10 +9994,11 @@ function createRouter(init) {
|
|||
let routesToUse = inFlightDataRoutes || dataRoutes;
|
||||
let localManifest = manifest;
|
||||
try {
|
||||
await patchRoutesOnNavigationImpl({
|
||||
await init.patchRoutesOnNavigation({
|
||||
signal,
|
||||
path: pathname,
|
||||
matches: partialMatches,
|
||||
fetcherKey,
|
||||
patch: (routeId, children) => {
|
||||
if (signal.aborted) return;
|
||||
patchRoutesImpl(
|
||||
|
@ -10434,20 +10486,127 @@ async function loadLazyRouteModule(route, mapRouteProperties2, manifest) {
|
|||
lazy: void 0
|
||||
});
|
||||
}
|
||||
async function defaultDataStrategy({
|
||||
matches
|
||||
}) {
|
||||
let matchesToLoad = matches.filter((m) => m.shouldLoad);
|
||||
async function defaultDataStrategy(args) {
|
||||
let matchesToLoad = args.matches.filter((m) => m.shouldLoad);
|
||||
let keyedResults = {};
|
||||
let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
|
||||
return results.reduce(
|
||||
(acc, result, i) => Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
|
||||
{}
|
||||
results.forEach((result, i) => {
|
||||
keyedResults[matchesToLoad[i].route.id] = result;
|
||||
});
|
||||
return keyedResults;
|
||||
}
|
||||
async function defaultDataStrategyWithMiddleware(args) {
|
||||
if (!args.matches.some((m) => m.route.unstable_middleware)) {
|
||||
return defaultDataStrategy(args);
|
||||
}
|
||||
return runMiddlewarePipeline(
|
||||
args,
|
||||
false,
|
||||
() => defaultDataStrategy(args),
|
||||
(error, routeId) => ({ [routeId]: { type: "error", result: error } })
|
||||
);
|
||||
}
|
||||
async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, requestContext) {
|
||||
async function runMiddlewarePipeline(args, propagateResult, handler, errorHandler) {
|
||||
let { matches, request, params, context } = args;
|
||||
let middlewareState = {
|
||||
handlerResult: void 0
|
||||
};
|
||||
try {
|
||||
let tuples = matches.flatMap(
|
||||
(m) => m.route.unstable_middleware ? m.route.unstable_middleware.map((fn) => [m.route.id, fn]) : []
|
||||
);
|
||||
let result = await callRouteMiddleware(
|
||||
{ request, params, context },
|
||||
tuples,
|
||||
propagateResult,
|
||||
middlewareState,
|
||||
handler
|
||||
);
|
||||
return propagateResult ? result : middlewareState.handlerResult;
|
||||
} catch (e) {
|
||||
if (!middlewareState.middlewareError) {
|
||||
throw e;
|
||||
}
|
||||
let result = await errorHandler(
|
||||
middlewareState.middlewareError.error,
|
||||
middlewareState.middlewareError.routeId
|
||||
);
|
||||
if (propagateResult || !middlewareState.handlerResult) {
|
||||
return result;
|
||||
}
|
||||
return Object.assign(middlewareState.handlerResult, result);
|
||||
}
|
||||
}
|
||||
async function callRouteMiddleware(args, middlewares, propagateResult, middlewareState, handler, idx = 0) {
|
||||
let { request } = args;
|
||||
if (request.signal.aborted) {
|
||||
if (request.signal.reason) {
|
||||
throw request.signal.reason;
|
||||
}
|
||||
throw new Error(
|
||||
`Request aborted without an \`AbortSignal.reason\`: ${request.method} ${request.url}`
|
||||
);
|
||||
}
|
||||
let tuple = middlewares[idx];
|
||||
if (!tuple) {
|
||||
middlewareState.handlerResult = await handler();
|
||||
return middlewareState.handlerResult;
|
||||
}
|
||||
let [routeId, middleware] = tuple;
|
||||
let nextCalled = false;
|
||||
let nextResult = void 0;
|
||||
let next = async () => {
|
||||
if (nextCalled) {
|
||||
throw new Error("You may only call `next()` once per middleware");
|
||||
}
|
||||
nextCalled = true;
|
||||
let result = await callRouteMiddleware(
|
||||
args,
|
||||
middlewares,
|
||||
propagateResult,
|
||||
middlewareState,
|
||||
handler,
|
||||
idx + 1
|
||||
);
|
||||
if (propagateResult) {
|
||||
nextResult = result;
|
||||
return nextResult;
|
||||
}
|
||||
};
|
||||
try {
|
||||
let result = await middleware(
|
||||
{
|
||||
request: args.request,
|
||||
params: args.params,
|
||||
context: args.context
|
||||
},
|
||||
next
|
||||
);
|
||||
if (nextCalled) {
|
||||
if (result === void 0) {
|
||||
return nextResult;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
return next();
|
||||
}
|
||||
} catch (error) {
|
||||
if (!middlewareState.middlewareError) {
|
||||
middlewareState.middlewareError = { routeId, error };
|
||||
} else if (middlewareState.middlewareError.error !== error) {
|
||||
middlewareState.middlewareError = { routeId, error };
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async function callDataStrategyImpl(dataStrategyImpl, type, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties2, scopedContext, enableMiddleware) {
|
||||
let loadRouteDefinitionsPromises = matches.map(
|
||||
(m) => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties2, manifest) : void 0
|
||||
);
|
||||
if (enableMiddleware) {
|
||||
await Promise.all(loadRouteDefinitionsPromises);
|
||||
}
|
||||
let dsMatches = matches.map((match2, i) => {
|
||||
let loadRoutePromise = loadRouteDefinitionsPromises[i];
|
||||
let shouldLoad = matchesToLoad.some((m) => m.route.id === match2.route.id);
|
||||
|
@ -10461,7 +10620,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matc
|
|||
match2,
|
||||
loadRoutePromise,
|
||||
handlerOverride,
|
||||
requestContext
|
||||
scopedContext
|
||||
) : Promise.resolve({ type: "data", result: void 0 });
|
||||
};
|
||||
return {
|
||||
|
@ -10475,7 +10634,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matc
|
|||
request,
|
||||
params: matches[0].params,
|
||||
fetcherKey,
|
||||
context: requestContext
|
||||
context: scopedContext
|
||||
});
|
||||
try {
|
||||
await Promise.all(loadRouteDefinitionsPromises);
|
||||
|
@ -10483,7 +10642,7 @@ async function callDataStrategyImpl(dataStrategyImpl, type, state, request, matc
|
|||
}
|
||||
return results;
|
||||
}
|
||||
async function callLoaderOrAction(type, request, match2, loadRoutePromise, handlerOverride, staticContext) {
|
||||
async function callLoaderOrAction(type, request, match2, loadRoutePromise, handlerOverride, scopedContext) {
|
||||
let result;
|
||||
let onReject;
|
||||
let runHandler = (handler) => {
|
||||
|
@ -10503,7 +10662,7 @@ async function callLoaderOrAction(type, request, match2, loadRoutePromise, handl
|
|||
{
|
||||
request,
|
||||
params: match2.params,
|
||||
context: staticContext
|
||||
context: scopedContext
|
||||
},
|
||||
...ctx !== void 0 ? [ctx] : []
|
||||
);
|
||||
|
@ -11762,6 +11921,7 @@ function mapRouteProperties(route) {
|
|||
function createMemoryRouter(routes, opts) {
|
||||
return createRouter({
|
||||
basename: opts == null ? void 0 : opts.basename,
|
||||
unstable_getContext: opts == null ? void 0 : opts.unstable_getContext,
|
||||
future: opts == null ? void 0 : opts.future,
|
||||
history: createMemoryHistory({
|
||||
initialEntries: opts == null ? void 0 : opts.initialEntries,
|
||||
|
@ -12383,7 +12543,7 @@ function dedupeLinkDescriptors(descriptors, preloads) {
|
|||
}, []);
|
||||
}
|
||||
var SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
|
||||
function singleFetchUrl(reqUrl) {
|
||||
function singleFetchUrl(reqUrl, basename) {
|
||||
let url = typeof reqUrl === "string" ? new URL(
|
||||
reqUrl,
|
||||
// This can be called during the SSR flow via PrefetchPageLinksImpl so
|
||||
|
@ -12392,6 +12552,8 @@ function singleFetchUrl(reqUrl) {
|
|||
) : reqUrl;
|
||||
if (url.pathname === "/") {
|
||||
url.pathname = "_root.data";
|
||||
} else if (basename && stripBasename(url.pathname, basename) === "/") {
|
||||
url.pathname = `${basename.replace(/\/$/, "")}/_root.data`;
|
||||
} else {
|
||||
url.pathname = `${url.pathname.replace(/\/$/, "")}.data`;
|
||||
}
|
||||
|
@ -12528,6 +12690,7 @@ function PrefetchPageLinksImpl({
|
|||
}) {
|
||||
let location = useLocation();
|
||||
let { manifest, routeModules } = useFrameworkContext();
|
||||
let { basename } = useDataRouterContext2();
|
||||
let { loaderData, matches } = useDataRouterStateContext();
|
||||
let newMatchesForData = React92.useMemo(
|
||||
() => getNewMatchesForLinks(
|
||||
|
@ -12574,7 +12737,7 @@ function PrefetchPageLinksImpl({
|
|||
if (routesParams.size === 0) {
|
||||
return [];
|
||||
}
|
||||
let url = singleFetchUrl(page);
|
||||
let url = singleFetchUrl(page, basename);
|
||||
if (foundOptOutRoute && routesParams.size > 0) {
|
||||
url.searchParams.set(
|
||||
"_routes",
|
||||
|
@ -12583,6 +12746,7 @@ function PrefetchPageLinksImpl({
|
|||
}
|
||||
return [url.pathname + url.search];
|
||||
}, [
|
||||
basename,
|
||||
loaderData,
|
||||
location,
|
||||
manifest,
|
||||
|
@ -12616,13 +12780,14 @@ function mergeRefs(...refs) {
|
|||
var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
||||
try {
|
||||
if (isBrowser) {
|
||||
window.__reactRouterVersion = "7.2.0";
|
||||
window.__reactRouterVersion = "7.4.0";
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
function createHashRouter(routes, opts) {
|
||||
return createRouter({
|
||||
basename: opts == null ? void 0 : opts.basename,
|
||||
unstable_getContext: opts == null ? void 0 : opts.unstable_getContext,
|
||||
future: opts == null ? void 0 : opts.future,
|
||||
history: createHashHistory({ window: opts == null ? void 0 : opts.window }),
|
||||
hydrationData: (opts == null ? void 0 : opts.hydrationData) || parseHydrationData(),
|
||||
|
@ -14604,6 +14769,7 @@ var useRedirect = function() {
|
|||
var basename = useBasename();
|
||||
var createPath2 = useCreatePath();
|
||||
return (0, import_react34.useCallback)(function(redirectTo, resource, id, data2, state) {
|
||||
var _a11;
|
||||
if (resource === void 0) {
|
||||
resource = "";
|
||||
}
|
||||
|
@ -14614,7 +14780,7 @@ var useRedirect = function() {
|
|||
return;
|
||||
} else if (typeof redirectTo === "function") {
|
||||
var target = redirectTo(resource, id, data2);
|
||||
var absoluteTarget = typeof target === "string" ? "".concat(basename, "/").concat(target) : __assign3({ pathname: "".concat(basename, "/").concat(target.pathname) }, target);
|
||||
var absoluteTarget = typeof target === "string" ? "".concat(basename).concat(target.startsWith("/") ? "" : "/").concat(target) : __assign3({ pathname: "".concat(basename).concat(((_a11 = target.pathname) === null || _a11 === void 0 ? void 0 : _a11.startsWith("/")) ? "" : "/").concat(target.pathname) }, target);
|
||||
navigate(absoluteTarget, {
|
||||
state: __assign3({ _scrollToTop: true }, state)
|
||||
});
|
||||
|
@ -19222,7 +19388,17 @@ var useListController = function(props) {
|
|||
_: error2 === null || error2 === void 0 ? void 0 : error2.message
|
||||
}
|
||||
});
|
||||
} }, otherQueryOptions)), data2 = _k.data, pageInfo = _k.pageInfo, total = _k.total, responseMeta = _k.meta, error = _k.error, isLoading = _k.isLoading, isFetching = _k.isFetching, isPending = _k.isPending, refetch2 = _k.refetch;
|
||||
} }, otherQueryOptions)), data2 = _k.data, pageInfo = _k.pageInfo, total = _k.total, responseMeta = _k.meta, error = _k.error, isLoading = _k.isLoading, isFetching = _k.isFetching, isPending = _k.isPending, refetch2 = _k.refetch, isPaused = _k.isPaused, isPlaceholderData = _k.isPlaceholderData;
|
||||
(0, import_react76.useEffect)(function() {
|
||||
if (isPaused && isPlaceholderData) {
|
||||
notify("ra.message.placeholder_data_warning", {
|
||||
type: "warning",
|
||||
messageArgs: {
|
||||
_: "Network issue: Data refresh failed."
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [isPaused, isPlaceholderData, notify]);
|
||||
(0, import_react76.useEffect)(function() {
|
||||
if (query.page <= 0 || !isFetching && query.page > 1 && (data2 == null || (data2 === null || data2 === void 0 ? void 0 : data2.length) === 0)) {
|
||||
queryModifiers.setPage(1);
|
||||
|
@ -33117,9 +33293,9 @@ inflection/lib/inflection.js:
|
|||
* A port of inflection-js to node.js module.
|
||||
*)
|
||||
|
||||
react-router/dist/development/chunk-HA7DTUK3.mjs:
|
||||
react-router/dist/development/chunk-GNGMS2XR.mjs:
|
||||
(**
|
||||
* react-router v7.2.0
|
||||
* react-router v7.4.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
|
@ -33131,7 +33307,7 @@ react-router/dist/development/chunk-HA7DTUK3.mjs:
|
|||
|
||||
react-router/dist/development/dom-export.mjs:
|
||||
(**
|
||||
* react-router v7.2.0
|
||||
* react-router v7.4.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
|
@ -33143,7 +33319,7 @@ react-router/dist/development/dom-export.mjs:
|
|||
|
||||
react-router/dist/development/index.mjs:
|
||||
(**
|
||||
* react-router v7.2.0
|
||||
* react-router v7.4.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
|
@ -33155,7 +33331,7 @@ react-router/dist/development/index.mjs:
|
|||
|
||||
react-router-dom/dist/index.mjs:
|
||||
(**
|
||||
* react-router-dom v7.2.0
|
||||
* react-router-dom v7.4.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -8,7 +8,7 @@ import {
|
|||
require_get,
|
||||
require_isIndex,
|
||||
require_isSymbol
|
||||
} from "./chunk-FFYJRC36.js";
|
||||
} from "./chunk-ZPUNMYDO.js";
|
||||
import {
|
||||
__commonJS,
|
||||
__toESM
|
||||
|
|
|
@ -15,7 +15,7 @@ npm i @asamuzakjp/css-color
|
|||
## Usage
|
||||
|
||||
```javascript
|
||||
import { convert, isColor, resolve } from '@asamuzakjp/css-color';
|
||||
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))'
|
||||
|
@ -25,7 +25,7 @@ const resolvedValue = resolve(
|
|||
const convertedValue = covert.colorToHex('lab(46.2775% -47.5621 48.5837)');
|
||||
// '#008000'
|
||||
|
||||
const result = isColor('green');
|
||||
const result = utils.isColor('green');
|
||||
// true
|
||||
```
|
||||
|
||||
|
@ -38,9 +38,7 @@ 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
|
||||
|
@ -86,7 +84,7 @@ resolves CSS color
|
|||
```javascript
|
||||
const opt = {
|
||||
dimension: {
|
||||
callback: (unit) => {
|
||||
callback: unit => {
|
||||
switch (unit) {
|
||||
case 'em':
|
||||
return 12;
|
||||
|
@ -107,10 +105,8 @@ resolves CSS 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`
|
||||
- `opt.key` **any?**
|
||||
- key to return with the value, e.g. CSS property `background-color`
|
||||
|
||||
Returns **([string][133]? | [Array][137])** 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`, or `[key, rgba?()]` etc. if `key` is specified
|
||||
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
|
||||
|
@ -283,7 +279,11 @@ convert color to xyz-d50
|
|||
|
||||
Returns **[Array][137]<[number][134]>** \[x, y, z, alpha]
|
||||
|
||||
### isColor(color)
|
||||
### utils
|
||||
|
||||
Contains utility functions.
|
||||
|
||||
### utils.isColor(color)
|
||||
|
||||
is valid color type
|
||||
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
"dist",
|
||||
"src"
|
||||
],
|
||||
"packageManager": "pnpm@9.15.3",
|
||||
"type": "module",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"main": "dist/cjs/index.cjs",
|
||||
"module": "dist/esm/index.js",
|
||||
"main": "dist/cjs/index.cjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": {
|
||||
|
@ -33,40 +32,45 @@
|
|||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"packageManager": "pnpm@10.6.1",
|
||||
"dependencies": {
|
||||
"@csstools/css-calc": "^2.1.1",
|
||||
"@csstools/css-color-parser": "^3.0.7",
|
||||
"@csstools/css-calc": "^2.1.2",
|
||||
"@csstools/css-color-parser": "^3.0.8",
|
||||
"@csstools/css-parser-algorithms": "^3.0.4",
|
||||
"@csstools/css-tokenizer": "^3.0.3",
|
||||
"lru-cache": "^10.4.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tanstack/config": "^0.15.1",
|
||||
"@vitest/coverage-istanbul": "^2.1.8",
|
||||
"esbuild": "^0.24.2",
|
||||
"eslint": "^9.18.0",
|
||||
"knip": "^5.42.0",
|
||||
"neostandard": "^0.12.0",
|
||||
"prettier": "^3.4.2",
|
||||
"publint": "^0.3.2",
|
||||
"@tanstack/vite-config": "^0.1.0",
|
||||
"@vitest/coverage-istanbul": "^3.0.8",
|
||||
"esbuild": "^0.25.0",
|
||||
"eslint": "^9.22.0",
|
||||
"eslint-plugin-import-x": "^4.6.1",
|
||||
"eslint-plugin-regexp": "^2.7.0",
|
||||
"globals": "^16.0.0",
|
||||
"knip": "^5.45.0",
|
||||
"neostandard": "^0.12.1",
|
||||
"prettier": "^3.5.3",
|
||||
"publint": "^0.3.8",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.0.7",
|
||||
"vitest": "^2.1.8"
|
||||
"tsup": "^8.4.0",
|
||||
"typescript": "^5.8.2",
|
||||
"vite": "^6.2.1",
|
||||
"vitest": "^3.0.8"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm run build:rest && pnpm run build:min",
|
||||
"build:min": "vite build -c vite.browser.config.ts",
|
||||
"build:rest": "vite build",
|
||||
"clean": "rimraf ./dist && rimraf ./coverage",
|
||||
"prettier": "prettier --ignore-unknown .",
|
||||
"prettier:write": "pnpm run prettier --write",
|
||||
"test": "pnpm run \"/^test:.*/\" && pnpm run build && pnpm run publint",
|
||||
"build": "pnpm run clean && pnpm run test && pnpm run knip && pnpm run build:prod && pnpm run build:cjs && pnpm run build:browser && pnpm run publint",
|
||||
"build:browser": "vite build -c ./vite.browser.config.ts",
|
||||
"build:prod": "vite build",
|
||||
"build:cjs": "tsup ./src/index.ts --format=cjs --platform=node --outDir=./dist/cjs/ --sourcemap --dts",
|
||||
"clean": "rimraf ./coverage ./dist",
|
||||
"knip": "knip",
|
||||
"prettier": "prettier . --ignore-unknown --write",
|
||||
"publint": "publint --strict",
|
||||
"test:lib": "vitest",
|
||||
"test:eslint": "eslint ./src ./tests",
|
||||
"test:knip": "knip",
|
||||
"test:types": "tsc"
|
||||
"test": "pnpm run prettier && pnpm run --stream \"/^test:.*/\"",
|
||||
"test:eslint": "eslint ./src ./test --fix",
|
||||
"test:types": "tsc",
|
||||
"test:unit": "vitest"
|
||||
},
|
||||
"version": "2.8.3"
|
||||
"version": "3.1.1"
|
||||
}
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
/* !
|
||||
/*!
|
||||
* CSS color - Resolve, parse, convert CSS color.
|
||||
* @license MIT
|
||||
* @copyright asamuzaK (Kazz)
|
||||
* @see {@link https://github.com/asamuzaK/cssColor/blob/main/LICENSE}
|
||||
*/
|
||||
|
||||
import { cssCalc as csscalc } from './js/css-calc';
|
||||
import { isGradient } from './js/css-gradient';
|
||||
import { cssVar } from './js/css-var';
|
||||
import { extractDashedIdent, isColor as iscolor, splitValue } from './js/util';
|
||||
|
||||
export { convert } from './js/convert';
|
||||
export { cssCalc } from './js/css-calc';
|
||||
export { resolve } from './js/resolve';
|
||||
export { isColor } from './js/util';
|
||||
/* utils */
|
||||
export const utils = {
|
||||
cssCalc: csscalc,
|
||||
cssVar,
|
||||
extractDashedIdent,
|
||||
isColor: iscolor,
|
||||
isGradient,
|
||||
splitValue
|
||||
};
|
||||
/* TODO: remove later */
|
||||
/* alias */
|
||||
export const isColor = utils.isColor;
|
||||
export const cssCalc = utils.cssCalc;
|
||||
|
|
|
@ -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;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,23 +1,31 @@
|
|||
/**
|
||||
* common.js
|
||||
* common
|
||||
*/
|
||||
|
||||
/* constants */
|
||||
/* numeric constants */
|
||||
const TYPE_FROM = 8;
|
||||
const TYPE_TO = -1;
|
||||
|
||||
/**
|
||||
* get type
|
||||
* @param {*} o - object to check
|
||||
* @returns {string} - type of object
|
||||
* @param o - object to check
|
||||
* @returns type of object
|
||||
*/
|
||||
export const getType = (o: any): string =>
|
||||
export const getType = (o: unknown): string =>
|
||||
Object.prototype.toString.call(o).slice(TYPE_FROM, TYPE_TO);
|
||||
|
||||
/**
|
||||
* is string
|
||||
* @param {*} o - object to check
|
||||
* @returns {boolean} - result
|
||||
* @param o - object to check
|
||||
* @returns result
|
||||
*/
|
||||
export const isString = (o: any): o is string =>
|
||||
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';
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
/**
|
||||
* constant.js
|
||||
* constant
|
||||
*/
|
||||
|
||||
/* constants */
|
||||
export const VAL_COMP = 'computedValue';
|
||||
export const VAL_SPEC = 'specifiedValue';
|
||||
|
||||
/* values and units */
|
||||
const _DIGIT = '(?:0|[1-9]\\d*)';
|
||||
const _COMP = 'clamp|max|min';
|
||||
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 _EXP = 'exp|hypot|log|pow|sqrt';
|
||||
const _SIGN = 'abs|sign';
|
||||
const _MATH = `${_COMP}|${_STEP}|${_TRIG}|${_EXP}|${_SIGN}`;
|
||||
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_MATH = `^(?:${_MATH})\\($`;
|
||||
export const SYN_FN_MATH_CALC = `^(?:${_CALC})\\(|(?<=[*\\/\\s\\(])(?:${_CALC})\\(`;
|
||||
export const SYN_FN_MATH_VAR = `^(?:${_VAR})\\(`;
|
||||
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}))?`;
|
||||
|
@ -42,7 +41,8 @@ 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_MIX = `${CS_HUE}|${CS_LAB}|${CS_SRGB}|${CS_XYZ}`;
|
||||
export const CS_RECT = `${CS_LAB}|${CS_RGB}|${CS_XYZ}`;
|
||||
export const CS_MIX = `${CS_HUE}|${CS_RECT}`;
|
||||
export const FN_COLOR = 'color(';
|
||||
export const FN_MIX = 'color-mix(';
|
||||
export const FN_REL = `(?:${_COLOR_FUNC})\\(\\s*from\\s+`;
|
||||
|
@ -59,3 +59,8 @@ export const SYN_COLOR_TYPE = `${_COLOR_KEY}|hsla?\\(\\s*${SYN_HSL_LV3}\\s*\\)|r
|
|||
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';
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
/**
|
||||
* convert.js
|
||||
* convert
|
||||
*/
|
||||
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import {
|
||||
CacheItem,
|
||||
NullObject,
|
||||
createCacheKey,
|
||||
getCache,
|
||||
setCache
|
||||
} from './cache';
|
||||
import {
|
||||
convertColorToHsl,
|
||||
convertColorToHwb,
|
||||
|
@ -17,571 +23,434 @@ import {
|
|||
} from './color';
|
||||
import { isString } from './common';
|
||||
import { cssCalc } from './css-calc';
|
||||
import { cssVar } from './css-var';
|
||||
import { resolveVar } from './css-var';
|
||||
import { resolveRelativeColor } from './relative-color';
|
||||
import { resolve } from './resolve';
|
||||
import { valueToJsonString } from './util';
|
||||
import { resolveColor } from './resolve';
|
||||
import { ColorChannels, ComputedColorChannels, Options } from './typedef';
|
||||
|
||||
/* constants */
|
||||
import {
|
||||
SYN_FN_MATH_CALC,
|
||||
SYN_FN_REL,
|
||||
SYN_FN_VAR,
|
||||
VAL_COMP
|
||||
} from './constant.js';
|
||||
import { SYN_FN_CALC, SYN_FN_REL, SYN_FN_VAR, VAL_COMP } from './constant';
|
||||
const NAMESPACE = 'convert';
|
||||
|
||||
/* regexp */
|
||||
const REG_FN_MATH_CALC = new RegExp(SYN_FN_MATH_CALC);
|
||||
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);
|
||||
|
||||
/* cached results */
|
||||
export const cachedResults = new LRUCache({
|
||||
max: 4096
|
||||
});
|
||||
|
||||
/**
|
||||
* pre process
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {?string} - value
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns value
|
||||
*/
|
||||
export const preProcess = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null => {
|
||||
opt: Options = {}
|
||||
): string | NullObject => {
|
||||
if (isString(value)) {
|
||||
value = value.trim();
|
||||
if (!value) {
|
||||
return null;
|
||||
return new NullObject();
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
return new NullObject();
|
||||
}
|
||||
const { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{preProcess:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
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 = cssVar(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue as string;
|
||||
const resolvedValue = resolveVar(value, opt);
|
||||
if (isString(resolvedValue)) {
|
||||
value = resolvedValue;
|
||||
} else {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, resolvedValue!);
|
||||
}
|
||||
return null;
|
||||
setCache(cacheKey, null);
|
||||
return new NullObject();
|
||||
}
|
||||
}
|
||||
if (REG_FN_REL.test(value)) {
|
||||
value = resolveRelativeColor(value, opt) as string;
|
||||
} else if (REG_FN_MATH_CALC.test(value)) {
|
||||
const resolvedValue = cssCalc(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue as string;
|
||||
const resolvedValue = resolveRelativeColor(value, opt);
|
||||
if (isString(resolvedValue)) {
|
||||
value = resolvedValue;
|
||||
} else {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, resolvedValue!);
|
||||
}
|
||||
return null;
|
||||
setCache(cacheKey, null);
|
||||
return new NullObject();
|
||||
}
|
||||
} else if (REG_FN_CALC.test(value)) {
|
||||
value = cssCalc(value, opt);
|
||||
}
|
||||
if (value.startsWith('color-mix')) {
|
||||
value = resolve(value, {
|
||||
format: VAL_COMP
|
||||
}) as string;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, value);
|
||||
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 {number} value - color value
|
||||
* @returns {string} - hex string: 00..ff
|
||||
* @param value - numeric value
|
||||
* @returns hex string: 00..ff
|
||||
*/
|
||||
export const numberToHex = (value: number): string => {
|
||||
const cacheKey = typeof value === 'number' && `{numberToHex:${value}}`;
|
||||
if (cacheKey && cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string;
|
||||
}
|
||||
const hex = numberToHexString(value);
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, hex);
|
||||
}
|
||||
return hex;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert color to hex
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {boolean} [opt.alpha] - return in #rrggbbaa notation
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {?string} - #rrggbb | #rrggbbaa | null
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @param [opt.alpha] - enable alpha channel
|
||||
* @returns #rrggbb | #rrggbbaa | null
|
||||
*/
|
||||
export const colorToHex = (
|
||||
value: string,
|
||||
opt: {
|
||||
alpha?: boolean;
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null => {
|
||||
export const colorToHex = (value: string, opt: Options = {}): string | null => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
return null!;
|
||||
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, customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToHex:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
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 = resolve(value, opt) as string | null;
|
||||
hex = resolveColor(value, opt);
|
||||
} else {
|
||||
opt.format = 'hex';
|
||||
hex = resolve(value, opt) as string | null;
|
||||
hex = resolveColor(value, opt);
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, hex!);
|
||||
if (isString(hex)) {
|
||||
setCache(cacheKey, hex);
|
||||
return hex;
|
||||
}
|
||||
return hex;
|
||||
setCache(cacheKey, null);
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert color to hsl
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [h, s, l, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [h, s, l, alpha]
|
||||
*/
|
||||
export const colorToHsl = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
export const colorToHsl = (value: string, opt: Options = {}): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToHsl:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
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 Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, hsl);
|
||||
}
|
||||
const hsl = convertColorToHsl(value, opt) as ColorChannels;
|
||||
setCache(cacheKey, hsl);
|
||||
return hsl;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert color to hwb
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [h, w, b, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [h, w, b, alpha]
|
||||
*/
|
||||
export const colorToHwb = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
export const colorToHwb = (value: string, opt: Options = {}): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToHwb:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
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 Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, hwb);
|
||||
}
|
||||
const hwb = convertColorToHwb(value, opt) as ColorChannels;
|
||||
setCache(cacheKey, hwb);
|
||||
return hwb;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert color to lab
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [l, a, b, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [l, a, b, alpha]
|
||||
*/
|
||||
export const colorToLab = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
export const colorToLab = (value: string, opt: Options = {}): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToLab:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
}
|
||||
const lab = convertColorToLab(value, opt) as Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, lab);
|
||||
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 {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [l, c, h, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [l, c, h, alpha]
|
||||
*/
|
||||
export const colorToLch = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
export const colorToLch = (value: string, opt: Options = {}): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToLch:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
}
|
||||
const lch = convertColorToLch(value, opt) as Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, lch);
|
||||
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 {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [l, a, b, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [l, a, b, alpha]
|
||||
*/
|
||||
export const colorToOklab = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
opt: Options = {}
|
||||
): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToOklab:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
}
|
||||
const lab = convertColorToOklab(value, opt) as Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, lab);
|
||||
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 {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [l, c, h, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [l, c, h, alpha]
|
||||
*/
|
||||
export const colorToOklch = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
opt: Options = {}
|
||||
): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToOklch:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
}
|
||||
const lch = convertColorToOklch(value, opt) as Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, lch);
|
||||
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 {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [r, g, b, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [r, g, b, alpha]
|
||||
*/
|
||||
export const colorToRgb = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
export const colorToRgb = (value: string, opt: Options = {}): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToRgb:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
}
|
||||
const rgb = convertColorToRgb(value, opt) as Array<number>;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, rgb);
|
||||
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 {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.d50] - white poin in d50
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [x, y, z, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [x, y, z, alpha]
|
||||
*/
|
||||
export const colorToXyz = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
d50?: boolean;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
export const colorToXyz = (value: string, opt: Options = {}): ColorChannels => {
|
||||
if (isString(value)) {
|
||||
const resolvedValue = preProcess(value, opt) as string | null;
|
||||
if (resolvedValue) {
|
||||
value = resolvedValue.toLowerCase() as string;
|
||||
} else {
|
||||
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 { customProperty } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (item: string) => string }
|
||||
)?.callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{colorToXyz:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as Array<number>;
|
||||
}
|
||||
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 [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
[, ...xyz] = parseColorFunc(value, opt) as ComputedColorChannels;
|
||||
} else {
|
||||
[, ...xyz] = parseColorValue(value, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
[, ...xyz] = parseColorValue(value, opt) as ComputedColorChannels;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, xyz as Array<number>);
|
||||
}
|
||||
return xyz as Array<number>;
|
||||
setCache(cacheKey, xyz);
|
||||
return xyz as ColorChannels;
|
||||
};
|
||||
|
||||
/**
|
||||
* convert color to xyz-d50
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {Array.<number>} - [x, y, z, alpha]
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns ColorChannels - [x, y, z, alpha]
|
||||
*/
|
||||
export const colorToXyzD50 = (
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
d50?: boolean;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<number> => {
|
||||
opt: Options = {}
|
||||
): ColorChannels => {
|
||||
opt.d50 = true;
|
||||
return colorToXyz(value, opt) as Array<number>;
|
||||
return colorToXyz(value, opt);
|
||||
};
|
||||
|
||||
/* convert */
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
/**
|
||||
* css-calc.js
|
||||
* css-calc
|
||||
*/
|
||||
|
||||
import { calc } from '@csstools/css-calc';
|
||||
import { TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import { isString } from './common';
|
||||
import { roundToPrecision, valueToJsonString } from './util';
|
||||
import { CSSToken, TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||
import {
|
||||
CacheItem,
|
||||
NullObject,
|
||||
createCacheKey,
|
||||
getCache,
|
||||
setCache
|
||||
} from './cache';
|
||||
import { isString, isStringOrNumber } from './common';
|
||||
import { resolveVar } from './css-var';
|
||||
import { roundToPrecision } from './util';
|
||||
import { MatchedRegExp, Options } from './typedef';
|
||||
|
||||
/* constants */
|
||||
import {
|
||||
FN_VAR,
|
||||
ANGLE,
|
||||
LENGTH,
|
||||
NUM,
|
||||
SYN_FN_MATH,
|
||||
SYN_FN_MATH_CALC,
|
||||
SYN_FN_MATH_VAR,
|
||||
SYN_FN_CALC,
|
||||
SYN_FN_MATH_START,
|
||||
SYN_FN_VAR,
|
||||
SYN_FN_VAR_START,
|
||||
VAL_SPEC
|
||||
} from './constant.js';
|
||||
} from './constant';
|
||||
const {
|
||||
CloseParen: PAREN_CLOSE,
|
||||
Comment: COMMENT,
|
||||
|
@ -27,49 +36,48 @@ const {
|
|||
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_MATH_CALC = new RegExp(SYN_FN_MATH_CALC);
|
||||
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
|
||||
const REG_FN_MATH_START = new RegExp(SYN_FN_MATH_START);
|
||||
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
|
||||
const REG_FN_VAR_START = new RegExp(SYN_FN_VAR_START);
|
||||
const REG_OPERATOR = /\s[*+/-]\s/;
|
||||
const REG_START_MATH = new RegExp(SYN_FN_MATH);
|
||||
const REG_START_MATH_VAR = new RegExp(SYN_FN_MATH_VAR);
|
||||
const REG_TYPE_DIM = new RegExp(`^(${NUM})([a-z]+)$`);
|
||||
const REG_TYPE_DIM_PCT = new RegExp(`^(${NUM})([a-z]+|%)$`);
|
||||
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})%$`);
|
||||
|
||||
/* cached results */
|
||||
export const cachedResults = new LRUCache({
|
||||
max: 4096
|
||||
});
|
||||
|
||||
/**
|
||||
* calclator
|
||||
* Calclator
|
||||
*/
|
||||
export class Calculator {
|
||||
/* private */
|
||||
// number
|
||||
#hasNum: boolean;
|
||||
#numSum: Array<any>;
|
||||
#numMul: Array<any>;
|
||||
#numSum: number[];
|
||||
#numMul: number[];
|
||||
// percentage
|
||||
#hasPct: boolean;
|
||||
#pctSum: Array<any>;
|
||||
#pctMul: Array<any>;
|
||||
#pctSum: number[];
|
||||
#pctMul: number[];
|
||||
// dimension
|
||||
#hasDim: boolean;
|
||||
#dimSum: Array<any>;
|
||||
#dimSub: Array<any>;
|
||||
#dimMul: Array<any>;
|
||||
#dimDiv: Array<any>;
|
||||
#dimSum: string[];
|
||||
#dimSub: string[];
|
||||
#dimMul: string[];
|
||||
#dimDiv: string[];
|
||||
// et cetra
|
||||
#hasEtc: boolean;
|
||||
#etcSum: Array<any>;
|
||||
#etcSub: Array<any>;
|
||||
#etcMul: Array<any>;
|
||||
#etcDiv: Array<any>;
|
||||
#etcSum: string[];
|
||||
#etcSub: string[];
|
||||
#etcMul: string[];
|
||||
#etcDiv: string[];
|
||||
|
||||
/**
|
||||
* constructor
|
||||
|
@ -179,7 +187,7 @@ export class Calculator {
|
|||
|
||||
/**
|
||||
* clear values
|
||||
* @returns {void}
|
||||
* @returns void
|
||||
*/
|
||||
clear() {
|
||||
// number
|
||||
|
@ -206,25 +214,17 @@ export class Calculator {
|
|||
|
||||
/**
|
||||
* sort values
|
||||
* @param {Array} values - values
|
||||
* @returns {Array} - sorted values
|
||||
* @param values - values
|
||||
* @returns sorted values
|
||||
*/
|
||||
sort(values: Array<any> = []): Array<any> {
|
||||
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 [
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
const [, valB, unitB] = b.match(REG_TYPE_DIM_PCT) as [
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
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;
|
||||
|
@ -255,11 +255,11 @@ export class Calculator {
|
|||
|
||||
/**
|
||||
* multiply values
|
||||
* @returns {?string} - resolved value
|
||||
* @returns resolved value
|
||||
*/
|
||||
multiply(): string | null {
|
||||
multiply(): string {
|
||||
const value = [];
|
||||
let num!: number | string;
|
||||
let num;
|
||||
if (this.#hasNum) {
|
||||
num = 1;
|
||||
for (const i of this.#numMul) {
|
||||
|
@ -269,38 +269,43 @@ export class Calculator {
|
|||
}
|
||||
}
|
||||
if (!this.#hasPct && !this.#hasDim && !this.hasEtc) {
|
||||
if (Number.isFinite(num)) {
|
||||
num = roundToPrecision(num, HEX);
|
||||
}
|
||||
value.push(num);
|
||||
}
|
||||
}
|
||||
if (this.#hasPct) {
|
||||
if (!this.#hasNum) {
|
||||
if (typeof num !== 'number') {
|
||||
num = 1;
|
||||
}
|
||||
for (const i of this.#pctMul) {
|
||||
(num as number) *= i;
|
||||
num *= i;
|
||||
if (num === 0 || !Number.isFinite(num) || Number.isNaN(num)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Number.isFinite(num)) {
|
||||
num = `${num}%`;
|
||||
num = `${roundToPrecision(num, HEX)}%`;
|
||||
}
|
||||
if (!this.#hasDim && !this.hasEtc) {
|
||||
value.push(num);
|
||||
}
|
||||
}
|
||||
if (this.#hasDim) {
|
||||
let dim, mul, div;
|
||||
let dim = '';
|
||||
let mul = '';
|
||||
let div = '';
|
||||
if (this.#dimMul.length) {
|
||||
if (this.#dimMul.length === 1) {
|
||||
[mul] = this.#dimMul;
|
||||
[mul] = this.#dimMul as [string];
|
||||
} else {
|
||||
mul = `${this.sort(this.#dimMul).join(' * ')}`;
|
||||
}
|
||||
}
|
||||
if (this.#dimDiv.length) {
|
||||
if (this.#dimDiv.length === 1) {
|
||||
[div] = this.#dimDiv;
|
||||
[div] = this.#dimDiv as [string];
|
||||
} else {
|
||||
div = `${this.sort(this.#dimDiv).join(' * ')}`;
|
||||
}
|
||||
|
@ -322,16 +327,14 @@ export class Calculator {
|
|||
toCanonicalUnits: true
|
||||
});
|
||||
}
|
||||
} else if (div.includes('*')) {
|
||||
dim = calc(`calc(${num} / (${div}))`, {
|
||||
toCanonicalUnits: true
|
||||
});
|
||||
} else {
|
||||
if (div.includes('*')) {
|
||||
dim = calc(`calc(${num} / (${div}))`, {
|
||||
toCanonicalUnits: true
|
||||
});
|
||||
} else {
|
||||
dim = calc(`calc(${num} / ${div})`, {
|
||||
toCanonicalUnits: true
|
||||
});
|
||||
}
|
||||
dim = calc(`calc(${num} / ${div})`, {
|
||||
toCanonicalUnits: true
|
||||
});
|
||||
}
|
||||
value.push(dim.replace(/^calc/, ''));
|
||||
} else {
|
||||
|
@ -398,14 +401,17 @@ export class Calculator {
|
|||
}
|
||||
}
|
||||
}
|
||||
return value.join(' ') || null;
|
||||
if (value.length) {
|
||||
return value.join(' ');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* sum values
|
||||
* @returns {?string} - resolved value
|
||||
* @returns resolved value
|
||||
*/
|
||||
sum(): string | null {
|
||||
sum(): string {
|
||||
const value = [];
|
||||
if (this.#hasNum) {
|
||||
let num = 0;
|
||||
|
@ -418,10 +424,10 @@ export class Calculator {
|
|||
value.push(num);
|
||||
}
|
||||
if (this.#hasPct) {
|
||||
let num = 0 as number | string;
|
||||
let num: number | string = 0;
|
||||
for (const i of this.#pctSum) {
|
||||
num += i;
|
||||
if (!Number.isFinite(num) || Number.isNaN(num)) {
|
||||
if (!Number.isFinite(num)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +478,7 @@ export class Calculator {
|
|||
if (this.#hasEtc) {
|
||||
if (this.#etcSum.length) {
|
||||
const sum = this.sort(this.#etcSum)
|
||||
.map((item) => {
|
||||
.map(item => {
|
||||
let res;
|
||||
if (
|
||||
REG_OPERATOR.test(item) &&
|
||||
|
@ -498,7 +504,7 @@ export class Calculator {
|
|||
}
|
||||
if (this.#etcSub.length) {
|
||||
const sub = this.sort(this.#etcSub)
|
||||
.map((item) => {
|
||||
.map(item => {
|
||||
let res;
|
||||
if (
|
||||
REG_OPERATOR.test(item) &&
|
||||
|
@ -525,154 +531,167 @@ export class Calculator {
|
|||
}
|
||||
}
|
||||
}
|
||||
return value.join(' ') || null;
|
||||
if (value.length) {
|
||||
return value.join(' ');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sort calc values
|
||||
* @param {Array} values - values
|
||||
* @param {boolean} finalize - finalize
|
||||
* @returns {?string} - sorted value
|
||||
* @param values - values to sort
|
||||
* @param [finalize] - finalize values
|
||||
* @returns sorted values
|
||||
*/
|
||||
export const sortCalcValues = (
|
||||
values: string[] = [],
|
||||
values: (number | string)[] = [],
|
||||
finalize: boolean = false
|
||||
): string | null => {
|
||||
if (values.length < 3) {
|
||||
return null;
|
||||
): 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 | null;
|
||||
for (let i = 0, l = values.length; i < l; i++) {
|
||||
const value = values[i]! as number | string;
|
||||
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();
|
||||
sortedValues.push(sortedValue, value);
|
||||
if (sortedValue) {
|
||||
sortedValues.push(sortedValue, value);
|
||||
}
|
||||
cal.clear();
|
||||
operator = null;
|
||||
operator = '';
|
||||
} else {
|
||||
const numValue = Number(value);
|
||||
const strValue = `${value}`;
|
||||
switch (operator) {
|
||||
case '/': {
|
||||
const numValue = Number(value) as number;
|
||||
if (Number.isFinite(numValue)) {
|
||||
cal.hasNum = true;
|
||||
cal.numMul.push(1 / numValue);
|
||||
} else if (REG_TYPE_PCT.test(value as string)) {
|
||||
const [, val] = (value as string).match(REG_TYPE_PCT) as [
|
||||
string,
|
||||
string
|
||||
];
|
||||
} 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(value as string)) {
|
||||
} else if (REG_TYPE_DIM.test(strValue)) {
|
||||
cal.hasDim = true;
|
||||
cal.dimDiv.push(value);
|
||||
cal.dimDiv.push(strValue);
|
||||
} else {
|
||||
cal.hasEtc = true;
|
||||
cal.etcDiv.push(value);
|
||||
cal.etcDiv.push(strValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '*':
|
||||
default: {
|
||||
const numValue = Number(value);
|
||||
if (Number.isFinite(numValue)) {
|
||||
cal.hasNum = true;
|
||||
cal.numMul.push(numValue);
|
||||
} else if (REG_TYPE_PCT.test(value as string)) {
|
||||
const [, val] = (value as string).match(REG_TYPE_PCT) as [
|
||||
string,
|
||||
string
|
||||
];
|
||||
} 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(value as string)) {
|
||||
} else if (REG_TYPE_DIM.test(strValue)) {
|
||||
cal.hasDim = true;
|
||||
cal.dimMul.push(value);
|
||||
cal.dimMul.push(strValue);
|
||||
} else {
|
||||
cal.hasEtc = true;
|
||||
cal.etcMul.push(value);
|
||||
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.multiply();
|
||||
sortedValues.push(sortedValue);
|
||||
cal.clear();
|
||||
operator = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
let resolvedValue;
|
||||
if (finalize && (sortedValues.includes('+') || sortedValues.includes('-'))) {
|
||||
const finalizedValues = [];
|
||||
cal.clear();
|
||||
operator = null;
|
||||
for (let i = 0, l = sortedValues.length; i < l; i++) {
|
||||
const value = sortedValues[i] as number | string;
|
||||
if (value === '+' || value === '-') {
|
||||
operator = value;
|
||||
} else {
|
||||
switch (operator) {
|
||||
case '-': {
|
||||
const numValue = Number(value) as number;
|
||||
if (Number.isFinite(numValue)) {
|
||||
cal.hasNum = true;
|
||||
cal.numSum.push(-1 * numValue);
|
||||
} else if (REG_TYPE_PCT.test(value as string)) {
|
||||
const [, val] = (value as string).match(REG_TYPE_PCT) as [
|
||||
string,
|
||||
string
|
||||
];
|
||||
cal.hasPct = true;
|
||||
cal.pctSum.push(-1 * Number(val));
|
||||
} else if (REG_TYPE_DIM.test(value as string)) {
|
||||
cal.hasDim = true;
|
||||
cal.dimSub.push(value);
|
||||
} else {
|
||||
cal.hasEtc = true;
|
||||
cal.etcSub.push(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '+':
|
||||
default: {
|
||||
const numValue = Number(value) as number;
|
||||
if (Number.isFinite(numValue)) {
|
||||
cal.hasNum = true;
|
||||
cal.numSum.push(numValue);
|
||||
} else if (REG_TYPE_PCT.test(value as string)) {
|
||||
const [, val] = (value as string).match(REG_TYPE_PCT) as [
|
||||
string,
|
||||
string
|
||||
];
|
||||
cal.hasPct = true;
|
||||
cal.pctSum.push(Number(val));
|
||||
} else if (REG_TYPE_DIM.test(value as string)) {
|
||||
cal.hasDim = true;
|
||||
cal.dimSum.push(value);
|
||||
} else {
|
||||
cal.hasEtc = true;
|
||||
cal.etcSum.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i === l - 1) {
|
||||
const sortedValue = cal.sum();
|
||||
const sortedValue = cal.sum();
|
||||
if (sortedValue) {
|
||||
finalizedValues.push(sortedValue);
|
||||
cal.clear();
|
||||
operator = null;
|
||||
}
|
||||
cal.clear();
|
||||
operator = '';
|
||||
}
|
||||
}
|
||||
resolvedValue = finalizedValues.join(' ');
|
||||
|
@ -684,164 +703,149 @@ export const sortCalcValues = (
|
|||
|
||||
/**
|
||||
* serialize calc
|
||||
* @param {string} value - value
|
||||
* @param {object} [opt] - options
|
||||
* @param {string} [opt.format] - output format
|
||||
* @returns {?string} - resolved value
|
||||
* @param value - CSS value
|
||||
* @param [opt] - options
|
||||
* @returns serialized value
|
||||
*/
|
||||
export const serializeCalc = (
|
||||
value: string,
|
||||
opt: {
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null => {
|
||||
const { format } = opt;
|
||||
export const serializeCalc = (value: string, opt: Options = {}): string => {
|
||||
const { format = '' } = opt;
|
||||
if (isString(value)) {
|
||||
if (!REG_START_MATH_VAR.test(value) || format !== VAL_SPEC) {
|
||||
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`);
|
||||
throw new TypeError(`${value} is not a string.`);
|
||||
}
|
||||
const cacheKey = `{serializeCalc:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
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 = tokenize({ css: value })
|
||||
.map((token) => {
|
||||
const [type, value] = token as [string, string];
|
||||
let res;
|
||||
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: any) => v) as Array<string>;
|
||||
.filter(v => v);
|
||||
let startIndex = items.findLastIndex((item: string) => /\($/.test(item));
|
||||
while (startIndex) {
|
||||
const endIndex = items.findIndex((item: any, index: number) => {
|
||||
const endIndex = items.findIndex((item: unknown, index: number) => {
|
||||
return item === ')' && index > startIndex;
|
||||
});
|
||||
const slicedValues = items.slice(startIndex, endIndex + 1);
|
||||
let serializedValue =
|
||||
sortCalcValues(slicedValues as Array<string>) as string;
|
||||
if (REG_START_MATH_VAR.test(serializedValue)) {
|
||||
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
|
||||
}) as string;
|
||||
});
|
||||
}
|
||||
items.splice(startIndex, endIndex - startIndex + 1, serializedValue);
|
||||
startIndex = items.findLastIndex((item: string) => /\($/.test(item));
|
||||
}
|
||||
const serializedCalc =
|
||||
sortCalcValues(items as Array<string>, true) as string | null;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, serializedCalc!);
|
||||
}
|
||||
const serializedCalc = sortCalcValues(items, true);
|
||||
setCache(cacheKey, serializedCalc);
|
||||
return serializedCalc;
|
||||
};
|
||||
|
||||
/**
|
||||
* resolve dimension
|
||||
* @param {Array} token - token
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @returns {?string} - resolved value
|
||||
* @param token - CSS token
|
||||
* @param [opt] - options
|
||||
* @returns resolved value
|
||||
*/
|
||||
export const resolveDimension = (
|
||||
token: Array<any>,
|
||||
opt: {
|
||||
dimension?: object;
|
||||
} = {}
|
||||
): string | null => {
|
||||
token: CSSToken,
|
||||
opt: Options = {}
|
||||
): string | NullObject => {
|
||||
if (!Array.isArray(token)) {
|
||||
throw new TypeError(`${token} is not an array.`);
|
||||
}
|
||||
const [, value, , , detail = {}] = token;
|
||||
const { unit, value: relativeValue } = detail;
|
||||
const [, , , , detail = {}] = token;
|
||||
const { unit, value } = detail as {
|
||||
unit: string;
|
||||
value: number;
|
||||
};
|
||||
const { dimension = {} } = opt;
|
||||
if (unit === 'px') {
|
||||
return value;
|
||||
return `${value}${unit}`;
|
||||
}
|
||||
let res;
|
||||
if (unit && Number.isFinite(relativeValue as number)) {
|
||||
let pixelValue!: number | undefined;
|
||||
const relativeValue = Number(value);
|
||||
if (unit && Number.isFinite(relativeValue)) {
|
||||
let pixelValue;
|
||||
if (Object.hasOwnProperty.call(dimension, unit)) {
|
||||
pixelValue = dimension[unit as never];
|
||||
} else if (
|
||||
typeof (
|
||||
dimension as {
|
||||
callback?: (unit: string) => number;
|
||||
}
|
||||
).callback === 'function'
|
||||
) {
|
||||
pixelValue = (
|
||||
dimension as {
|
||||
callback: (unit: string) => number;
|
||||
}
|
||||
).callback(unit);
|
||||
pixelValue = dimension[unit];
|
||||
} else if (typeof dimension.callback === 'function') {
|
||||
pixelValue = dimension.callback(unit);
|
||||
}
|
||||
pixelValue = Number(pixelValue);
|
||||
if (Number.isFinite(pixelValue)) {
|
||||
res = `${relativeValue as number * pixelValue as number}px`;
|
||||
return `${relativeValue * pixelValue}px`;
|
||||
}
|
||||
}
|
||||
return res ?? null;
|
||||
return new NullObject();
|
||||
};
|
||||
|
||||
/**
|
||||
* parse tokens
|
||||
* @param {Array.<Array>} tokens - tokens
|
||||
* @param {object} [opt] - options
|
||||
* @returns {Array.<string>} - parsed tokens
|
||||
* @param tokens - CSS tokens
|
||||
* @param [opt] - options
|
||||
* @returns parsed tokens
|
||||
*/
|
||||
export const parseTokens = (
|
||||
tokens: Array<Array<any>>,
|
||||
opt: {
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<string> => {
|
||||
tokens: CSSToken[],
|
||||
opt: Options = {}
|
||||
): string[] => {
|
||||
if (!Array.isArray(tokens)) {
|
||||
throw new TypeError(`${tokens} is not an array.`);
|
||||
}
|
||||
const { format } = opt;
|
||||
const { format = '' } = opt;
|
||||
const mathFunc = new Set();
|
||||
let nest = 0 as number;
|
||||
const res = [] as string[];
|
||||
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 [string, string];
|
||||
const [type = '', value = ''] = token as [TokenType, string];
|
||||
switch (type) {
|
||||
case DIM: {
|
||||
let resolvedValue;
|
||||
if (format === VAL_SPEC && !mathFunc.has(nest)) {
|
||||
resolvedValue = value as string;
|
||||
res.push(value);
|
||||
} else {
|
||||
resolvedValue = resolveDimension(token, opt) as string | null;
|
||||
if (!resolvedValue) {
|
||||
resolvedValue = value as string;
|
||||
const resolvedValue = resolveDimension(token, opt);
|
||||
if (isString(resolvedValue)) {
|
||||
res.push(resolvedValue);
|
||||
} else {
|
||||
res.push(value);
|
||||
}
|
||||
}
|
||||
res.push(resolvedValue as string);
|
||||
break;
|
||||
}
|
||||
case FUNC:
|
||||
case PAREN_OPEN: {
|
||||
res.push(value);
|
||||
nest++;
|
||||
if (REG_START_MATH.test(value)) {
|
||||
if (REG_FN_MATH_START.test(value)) {
|
||||
mathFunc.add(nest);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAREN_CLOSE: {
|
||||
if (res.length) {
|
||||
const lastValue = res[res.length - 1] as string;
|
||||
const lastValue = res[res.length - 1];
|
||||
if (lastValue === ' ') {
|
||||
res.splice(-1, 1, value);
|
||||
} else {
|
||||
|
@ -858,8 +862,12 @@ export const parseTokens = (
|
|||
}
|
||||
case W_SPACE: {
|
||||
if (res.length) {
|
||||
const lastValue = res[res.length - 1] as string;
|
||||
if (!lastValue.endsWith('(') && lastValue !== ' ') {
|
||||
const lastValue = res[res.length - 1];
|
||||
if (
|
||||
isString(lastValue) &&
|
||||
!lastValue.endsWith('(') &&
|
||||
lastValue !== ' '
|
||||
) {
|
||||
res.push(value);
|
||||
}
|
||||
}
|
||||
|
@ -876,81 +884,65 @@ export const parseTokens = (
|
|||
};
|
||||
|
||||
/**
|
||||
* resolve CSS calc()
|
||||
* @param {string} value - color value including calc()
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.dimension] - dimension
|
||||
* @param {string} [opt.format] - output format
|
||||
* @returns {?string} - value
|
||||
* CSS calc()
|
||||
* @param value - CSS value including calc()
|
||||
* @param [opt] - options
|
||||
* @returns resolved value
|
||||
*/
|
||||
export const cssCalc = (
|
||||
value: string,
|
||||
opt: {
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null => {
|
||||
const { format, dimension = {} } = opt;
|
||||
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;
|
||||
// var() must be resolved before cssCalc()
|
||||
} else {
|
||||
throw new SyntaxError(`Unexpected token ${FN_VAR} found.`);
|
||||
const resolvedValue = resolveVar(value, opt);
|
||||
if (isString(resolvedValue)) {
|
||||
return resolvedValue;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
} else if (!REG_FN_MATH_CALC.test(value)) {
|
||||
} else if (!REG_FN_CALC.test(value)) {
|
||||
return value;
|
||||
}
|
||||
value = value.toLowerCase().trim();
|
||||
} else {
|
||||
throw new TypeError(`${value} is not a string`);
|
||||
throw new TypeError(`${value} is not a string.`);
|
||||
}
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
dimension as {
|
||||
callback?: (unit: string) => number;
|
||||
}
|
||||
).callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{cssCalc:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
}
|
||||
const cacheKey: string = createCacheKey(
|
||||
{
|
||||
namespace: NAMESPACE,
|
||||
name: 'cssCalc',
|
||||
value
|
||||
},
|
||||
opt
|
||||
);
|
||||
const cachedResult = getCache(cacheKey);
|
||||
if (cachedResult instanceof CacheItem) {
|
||||
return cachedResult.item as string;
|
||||
}
|
||||
let resolvedValue;
|
||||
if (dimension) {
|
||||
const tokens = tokenize({ css: value });
|
||||
const values = parseTokens(tokens, opt);
|
||||
resolvedValue = calc(values.join(''), {
|
||||
toCanonicalUnits: true
|
||||
}) as string;
|
||||
} else {
|
||||
resolvedValue = calc(value, {
|
||||
toCanonicalUnits: true
|
||||
}) as string;
|
||||
}
|
||||
if (REG_START_MATH_VAR.test(value)) {
|
||||
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 [
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
const [, val, unit] = resolvedValue.match(
|
||||
REG_TYPE_DIM_PCT
|
||||
) as MatchedRegExp;
|
||||
resolvedValue = `${roundToPrecision(Number(val), HEX)}${unit}`;
|
||||
}
|
||||
// wrap with `calc()`
|
||||
if (
|
||||
resolvedValue &&
|
||||
!REG_START_MATH_VAR.test(resolvedValue as string) &&
|
||||
!REG_FN_VAR_START.test(resolvedValue) &&
|
||||
format === VAL_SPEC
|
||||
) {
|
||||
resolvedValue = `calc(${resolvedValue})`;
|
||||
}
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, resolvedValue);
|
||||
}
|
||||
setCache(cacheKey, resolvedValue);
|
||||
return resolvedValue;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
/**
|
||||
* css-gradient
|
||||
*/
|
||||
|
||||
import { CacheItem, createCacheKey, getCache, setCache } from './cache';
|
||||
import { isString } from './common';
|
||||
import { MatchedRegExp, Options } from './typedef';
|
||||
import { isColor, splitValue } from './util';
|
||||
|
||||
/* constants */
|
||||
import {
|
||||
ANGLE,
|
||||
CS_HUE,
|
||||
CS_RECT,
|
||||
LENGTH,
|
||||
NUM,
|
||||
NUM_POSITIVE,
|
||||
PCT
|
||||
} from './constant';
|
||||
const NAMESPACE = 'css-gradient';
|
||||
const DIM_ANGLE = `${NUM}(?:${ANGLE})`;
|
||||
const DIM_ANGLE_PCT = `${DIM_ANGLE}|${PCT}`;
|
||||
const DIM_LEN = `${NUM}(?:${LENGTH})|0`;
|
||||
const DIM_LEN_PCT = `${DIM_LEN}|${PCT}`;
|
||||
const DIM_LEN_PCT_POSI = `${NUM_POSITIVE}(?:${LENGTH}|%)|0`;
|
||||
const DIM_LEN_POSI = `${NUM_POSITIVE}(?:${LENGTH})|0`;
|
||||
const CTR = 'center';
|
||||
const L_R = 'left|right';
|
||||
const T_B = 'top|bottom';
|
||||
const S_E = 'start|end';
|
||||
const AXIS_X = `${L_R}|x-(?:${S_E})`;
|
||||
const AXIS_Y = `${T_B}|y-(?:${S_E})`;
|
||||
const BLOCK = `block-(?:${S_E})`;
|
||||
const INLINE = `inline-(?:${S_E})`;
|
||||
const POS_1 = `${CTR}|${AXIS_X}|${AXIS_Y}|${BLOCK}|${INLINE}|${DIM_LEN_PCT}`;
|
||||
const POS_2 = [
|
||||
`(?:${CTR}|${AXIS_X})\\s+(?:${CTR}|${AXIS_Y})`,
|
||||
`(?:${CTR}|${AXIS_Y})\\s+(?:${CTR}|${AXIS_X})`,
|
||||
`(?:${CTR}|${AXIS_X}|${DIM_LEN_PCT})\\s+(?:${CTR}|${AXIS_Y}|${DIM_LEN_PCT})`,
|
||||
`(?:${CTR}|${BLOCK})\\s+(?:${CTR}|${INLINE})`,
|
||||
`(?:${CTR}|${INLINE})\\s+(?:${CTR}|${BLOCK})`,
|
||||
`(?:${CTR}|${S_E})\\s+(?:${CTR}|${S_E})`
|
||||
].join('|');
|
||||
const POS_4 = [
|
||||
`(?:${AXIS_X})\\s+(?:${DIM_LEN_PCT})\\s+(?:${AXIS_Y})\\s+(?:${DIM_LEN_PCT})`,
|
||||
`(?:${AXIS_Y})\\s+(?:${DIM_LEN_PCT})\\s+(?:${AXIS_X})\\s+(?:${DIM_LEN_PCT})`,
|
||||
`(?:${BLOCK})\\s+(?:${DIM_LEN_PCT})\\s+(?:${INLINE})\\s+(?:${DIM_LEN_PCT})`,
|
||||
`(?:${INLINE})\\s+(?:${DIM_LEN_PCT})\\s+(?:${BLOCK})\\s+(?:${DIM_LEN_PCT})`,
|
||||
`(?:${S_E})\\s+(?:${DIM_LEN_PCT})\\s+(?:${S_E})\\s+(?:${DIM_LEN_PCT})`
|
||||
].join('|');
|
||||
const RAD_EXTENT = '(?:clos|farth)est-(?:corner|side)';
|
||||
const RAD_SIZE = [
|
||||
`${RAD_EXTENT}(?:\\s+${RAD_EXTENT})?`,
|
||||
`${DIM_LEN_POSI}`,
|
||||
`(?:${DIM_LEN_PCT_POSI})\\s+(?:${DIM_LEN_PCT_POSI})`
|
||||
].join('|');
|
||||
const RAD_SHAPE = 'circle|ellipse';
|
||||
const FROM_ANGLE = `from\\s+${DIM_ANGLE}`;
|
||||
const AT_POSITION = `at\\s+(?:${POS_1}|${POS_2}|${POS_4})`;
|
||||
const TO_SIDE_CORNER = `to\\s+(?:(?:${L_R})(?:\\s(?:${T_B}))?|(?:${T_B})(?:\\s(?:${L_R}))?)`;
|
||||
const IN_COLOR_SPACE = `in\\s+(?:${CS_RECT}|${CS_HUE})`;
|
||||
|
||||
/* type definitions */
|
||||
/**
|
||||
* @type ColorStopList - list of color stops
|
||||
*/
|
||||
type ColorStopList = [string, string, ...string[]];
|
||||
|
||||
/**
|
||||
* @typedef Gradient - parsed CSS gradient
|
||||
* @property value - input value
|
||||
* @property type - gradient type
|
||||
* @property [gradientLine] - gradient line
|
||||
* @property colorStopList - list of color stops
|
||||
*/
|
||||
interface Gradient {
|
||||
value: string;
|
||||
type: string;
|
||||
gradientLine?: string;
|
||||
colorStopList: ColorStopList;
|
||||
}
|
||||
|
||||
/* regexp */
|
||||
const REG_GRAD = /^(?:repeating-)?(?:conic|linear|radial)-gradient\(/;
|
||||
const REG_GRAD_CAPT = /^((?:repeating-)?(?:conic|linear|radial)-gradient)\(/;
|
||||
|
||||
/**
|
||||
* get gradient type
|
||||
* @param value - gradient value
|
||||
* @returns gradient type
|
||||
*/
|
||||
export const getGradientType = (value: string): string => {
|
||||
if (isString(value)) {
|
||||
value = value.trim();
|
||||
if (REG_GRAD.test(value)) {
|
||||
const [, type] = value.match(REG_GRAD_CAPT) as MatchedRegExp;
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* validate gradient line
|
||||
* @param value - gradient line value
|
||||
* @param type - gradient type
|
||||
* @returns result
|
||||
*/
|
||||
export const validateGradientLine = (value: string, type: string): boolean => {
|
||||
if (isString(value) && isString(type)) {
|
||||
value = value.trim();
|
||||
type = type.trim();
|
||||
let lineSyntax = '';
|
||||
if (/^(?:repeating-)?linear-gradient$/.test(type)) {
|
||||
/*
|
||||
* <linear-gradient-line> = [
|
||||
* [ <angle> | to <side-or-corner> ] ||
|
||||
* <color-interpolation-method>
|
||||
* ]
|
||||
*/
|
||||
lineSyntax = [
|
||||
`(?:${DIM_ANGLE}|${TO_SIDE_CORNER})(?:\\s+${IN_COLOR_SPACE})?`,
|
||||
`${IN_COLOR_SPACE}(?:\\s+(?:${DIM_ANGLE}|${TO_SIDE_CORNER}))?`
|
||||
].join('|');
|
||||
} else if (/^(?:repeating-)?radial-gradient$/.test(type)) {
|
||||
/*
|
||||
* <radial-gradient-line> = [
|
||||
* [ [ <radial-shape> || <radial-size> ]? [ at <position> ]? ] ||
|
||||
* <color-interpolation-method>]?
|
||||
*/
|
||||
lineSyntax = [
|
||||
`(?:${RAD_SHAPE})(?:\\s+(?:${RAD_SIZE}))?(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
|
||||
`(?:${RAD_SIZE})(?:\\s+(?:${RAD_SHAPE}))?(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
|
||||
`${AT_POSITION}(?:\\s+${IN_COLOR_SPACE})?`,
|
||||
`${IN_COLOR_SPACE}(?:\\s+${RAD_SHAPE})(?:\\s+(?:${RAD_SIZE}))?(?:\\s+${AT_POSITION})?`,
|
||||
`${IN_COLOR_SPACE}(?:\\s+${RAD_SIZE})(?:\\s+(?:${RAD_SHAPE}))?(?:\\s+${AT_POSITION})?`,
|
||||
`${IN_COLOR_SPACE}(?:\\s+${AT_POSITION})?`
|
||||
].join('|');
|
||||
} else if (/^(?:repeating-)?conic-gradient$/.test(type)) {
|
||||
/*
|
||||
* <conic-gradient-line> = [
|
||||
* [ [ from <angle> ]? [ at <position> ]? ] ||
|
||||
* <color-interpolation-method>
|
||||
* ]
|
||||
*/
|
||||
lineSyntax = [
|
||||
`${FROM_ANGLE}(?:\\s+${AT_POSITION})?(?:\\s+${IN_COLOR_SPACE})?`,
|
||||
`${AT_POSITION}(?:\\s+${IN_COLOR_SPACE})?`,
|
||||
`${IN_COLOR_SPACE}(?:\\s+${FROM_ANGLE})?(?:\\s+${AT_POSITION})?`
|
||||
].join('|');
|
||||
}
|
||||
if (lineSyntax) {
|
||||
const reg = new RegExp(`^(?:${lineSyntax})$`);
|
||||
return reg.test(value);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* validate color stop list
|
||||
* @param list
|
||||
* @param type
|
||||
* @param [opt]
|
||||
* @returns result
|
||||
*/
|
||||
export const validateColorStopList = (
|
||||
list: string[],
|
||||
type: string,
|
||||
opt: Options = {}
|
||||
): boolean => {
|
||||
if (Array.isArray(list) && list.length > 1) {
|
||||
const dimension = /^(?:repeating-)?conic-gradient$/.test(type)
|
||||
? DIM_ANGLE_PCT
|
||||
: DIM_LEN_PCT;
|
||||
const regColorHint = new RegExp(`^(?:${dimension})$`);
|
||||
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
|
||||
const arr = [];
|
||||
for (const item of list) {
|
||||
if (isString(item)) {
|
||||
if (regColorHint.test(item)) {
|
||||
arr.push('hint');
|
||||
} else {
|
||||
const color = item.replace(regDimension, '');
|
||||
if (isColor(color, opt)) {
|
||||
arr.push('color');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const value = arr.join(',');
|
||||
return /^color(?:,(?:hint,)?color)+$/.test(value);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* parse CSS gradient
|
||||
* @param value - gradient value
|
||||
* @param [opt] - options
|
||||
* @returns parsed result
|
||||
*/
|
||||
export const parseGradient = (
|
||||
value: string,
|
||||
opt: Options = {}
|
||||
): Gradient | null => {
|
||||
if (isString(value)) {
|
||||
value = value.trim();
|
||||
const cacheKey: string = createCacheKey(
|
||||
{
|
||||
namespace: NAMESPACE,
|
||||
name: 'parseGradient',
|
||||
value
|
||||
},
|
||||
opt
|
||||
);
|
||||
const cachedResult = getCache(cacheKey);
|
||||
if (cachedResult instanceof CacheItem) {
|
||||
if (cachedResult.isNull) {
|
||||
return null;
|
||||
}
|
||||
return cachedResult.item as Gradient;
|
||||
}
|
||||
const type = getGradientType(value);
|
||||
const gradValue = value.replace(REG_GRAD, '').replace(/\)$/, '');
|
||||
if (type && gradValue) {
|
||||
const [lineOrColorStop = '', ...colorStops] = splitValue(gradValue, ',');
|
||||
const dimension = /^(?:repeating-)?conic-gradient$/.test(type)
|
||||
? DIM_ANGLE_PCT
|
||||
: DIM_LEN_PCT;
|
||||
const regDimension = new RegExp(`(?:\\s+(?:${dimension})){1,2}$`);
|
||||
let isColorStop = false;
|
||||
if (regDimension.test(lineOrColorStop)) {
|
||||
const colorStop = lineOrColorStop.replace(regDimension, '');
|
||||
if (isColor(colorStop, opt)) {
|
||||
isColorStop = true;
|
||||
}
|
||||
} else if (isColor(lineOrColorStop, opt)) {
|
||||
isColorStop = true;
|
||||
}
|
||||
if (isColorStop) {
|
||||
colorStops.unshift(lineOrColorStop);
|
||||
const valid = validateColorStopList(colorStops, type, opt);
|
||||
if (valid) {
|
||||
const res: Gradient = {
|
||||
value,
|
||||
type,
|
||||
colorStopList: colorStops as ColorStopList
|
||||
};
|
||||
setCache(cacheKey, res);
|
||||
return res;
|
||||
}
|
||||
} else if (colorStops.length > 1) {
|
||||
const gradientLine = lineOrColorStop;
|
||||
const valid =
|
||||
validateGradientLine(gradientLine, type) &&
|
||||
validateColorStopList(colorStops, type, opt);
|
||||
if (valid) {
|
||||
const res: Gradient = {
|
||||
value,
|
||||
type,
|
||||
gradientLine,
|
||||
colorStopList: colorStops as ColorStopList
|
||||
};
|
||||
setCache(cacheKey, res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
setCache(cacheKey, null);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* is CSS gradient
|
||||
* @param value - CSS value
|
||||
* @param [opt] - options
|
||||
* @returns result
|
||||
*/
|
||||
export const isGradient = (value: string, opt: Options = {}): boolean => {
|
||||
const gradient = parseGradient(value, opt);
|
||||
return gradient !== null;
|
||||
};
|
|
@ -1,18 +1,22 @@
|
|||
/**
|
||||
* css-var.js
|
||||
* css-var
|
||||
*/
|
||||
|
||||
import { TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
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, valueToJsonString } from './util';
|
||||
|
||||
/* types */
|
||||
import type { CSSToken } from '@csstools/css-tokenizer';
|
||||
import { isColor } from './util';
|
||||
import { Options } from './typedef';
|
||||
|
||||
/* constants */
|
||||
import { FN_VAR, SYN_FN_MATH_CALC, SYN_FN_VAR, VAL_SPEC } from './constant';
|
||||
import { FN_VAR, SYN_FN_CALC, SYN_FN_VAR, VAL_SPEC } from './constant';
|
||||
const {
|
||||
CloseParen: PAREN_CLOSE,
|
||||
Comment: COMMENT,
|
||||
|
@ -20,99 +24,82 @@ const {
|
|||
Ident: IDENT,
|
||||
Whitespace: W_SPACE
|
||||
} = TokenType;
|
||||
const NAMESPACE = 'css-var';
|
||||
|
||||
/* regexp */
|
||||
const REG_FN_MATH_CALC = new RegExp(SYN_FN_MATH_CALC);
|
||||
const REG_FN_CALC = new RegExp(SYN_FN_CALC);
|
||||
const REG_FN_VAR = new RegExp(SYN_FN_VAR);
|
||||
|
||||
/* cached results */
|
||||
export const cachedResults = new LRUCache({
|
||||
max: 4096
|
||||
});
|
||||
|
||||
/**
|
||||
* resolve custom property
|
||||
* @param {Array.<Array>} tokens - tokens
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @returns {Array.<string|Array|undefined>} - [tokens, resolvedValue]
|
||||
* @param tokens - CSS tokens
|
||||
* @param [opt] - options
|
||||
* @returns result - [tokens, resolvedValue]
|
||||
*/
|
||||
export function resolveCustomProperty(
|
||||
tokens: Array<CSSToken>,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<string | Array<CSSToken> | undefined> {
|
||||
tokens: CSSToken[],
|
||||
opt: Options = {}
|
||||
): [CSSToken[], string] {
|
||||
if (!Array.isArray(tokens)) {
|
||||
throw new TypeError(`${tokens} is not an array.`);
|
||||
}
|
||||
const { customProperty = {} } = opt;
|
||||
const items = [];
|
||||
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 [string, string];
|
||||
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) as [
|
||||
Array<CSSToken>,
|
||||
string
|
||||
];
|
||||
const [restTokens, item] = resolveCustomProperty(tokens, opt);
|
||||
tokens = restTokens;
|
||||
if (item) {
|
||||
items.push(item);
|
||||
}
|
||||
} else if (type === IDENT) {
|
||||
if (value.startsWith('--')) {
|
||||
let item;
|
||||
if (Object.hasOwnProperty.call(customProperty, value)) {
|
||||
items.push(customProperty[value as never]);
|
||||
} else if (
|
||||
typeof (
|
||||
customProperty as { callback?: (value: string) => string }
|
||||
).callback === 'function'
|
||||
) {
|
||||
const item = (
|
||||
customProperty as { callback: (value: string) => string }
|
||||
).callback(value);
|
||||
if (item) {
|
||||
items.push(item);
|
||||
}
|
||||
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;
|
||||
let resolveAsColor = false;
|
||||
if (items.length > 1) {
|
||||
const lastValue = items[items.length - 1];
|
||||
resolveAsColor = isColor(lastValue as string) as boolean;
|
||||
resolveAsColor = isColor(lastValue);
|
||||
}
|
||||
let resolvedValue;
|
||||
let resolvedValue = '';
|
||||
for (let item of items) {
|
||||
item = item.trim() as string;
|
||||
item = item.trim();
|
||||
if (REG_FN_VAR.test(item)) {
|
||||
// recurse cssVar()
|
||||
item = cssVar(item, opt) as string;
|
||||
if (item) {
|
||||
// recurse resolveVar()
|
||||
const resolvedItem = resolveVar(item, opt);
|
||||
if (isString(resolvedItem)) {
|
||||
if (resolveAsColor) {
|
||||
if (isColor(item)) {
|
||||
resolvedValue = item;
|
||||
if (isColor(resolvedItem)) {
|
||||
resolvedValue = resolvedItem;
|
||||
}
|
||||
} else {
|
||||
resolvedValue = item;
|
||||
resolvedValue = resolvedItem;
|
||||
}
|
||||
}
|
||||
} else if (REG_FN_MATH_CALC.test(item)) {
|
||||
item = cssCalc(item as string, opt) as string;
|
||||
} else if (REG_FN_CALC.test(item)) {
|
||||
item = cssCalc(item, opt);
|
||||
if (resolveAsColor) {
|
||||
if (isColor(item)) {
|
||||
resolvedValue = item;
|
||||
|
@ -141,25 +128,25 @@ export function resolveCustomProperty(
|
|||
|
||||
/**
|
||||
* parse tokens
|
||||
* @param {Array.<Array>} tokens - tokens
|
||||
* @param {object} [opt] - options
|
||||
* @returns {?Array.<string>} - parsed tokens
|
||||
* @param tokens - CSS tokens
|
||||
* @param [opt] - options
|
||||
* @returns parsed tokens
|
||||
*/
|
||||
export function parseTokens(
|
||||
tokens: Array<CSSToken>,
|
||||
opt: object = {}
|
||||
): Array<string> | null {
|
||||
const res = [] as string[];
|
||||
tokens: CSSToken[],
|
||||
opt: Options = {}
|
||||
): string[] | NullObject {
|
||||
const res: string[] = [];
|
||||
while (tokens.length) {
|
||||
const token = tokens.shift();
|
||||
const [type, value] = token as [string, string];
|
||||
const [type = '', value = ''] = token as [TokenType, string];
|
||||
if (value === FN_VAR) {
|
||||
const [restTokens, resolvedValue] = resolveCustomProperty(tokens, opt);
|
||||
if (!resolvedValue) {
|
||||
return null;
|
||||
return new NullObject();
|
||||
}
|
||||
tokens = restTokens as Array<CSSToken>;
|
||||
res.push(resolvedValue as string);
|
||||
tokens = restTokens;
|
||||
res.push(resolvedValue);
|
||||
} else {
|
||||
switch (type) {
|
||||
case PAREN_CLOSE: {
|
||||
|
@ -177,8 +164,12 @@ export function parseTokens(
|
|||
}
|
||||
case W_SPACE: {
|
||||
if (res.length) {
|
||||
const lastValue = res[res.length - 1] as string;
|
||||
if (!lastValue.endsWith('(') && lastValue !== ' ') {
|
||||
const lastValue = res[res.length - 1];
|
||||
if (
|
||||
isString(lastValue) &&
|
||||
!lastValue.endsWith('(') &&
|
||||
lastValue !== ' '
|
||||
) {
|
||||
res.push(value);
|
||||
}
|
||||
}
|
||||
|
@ -197,19 +188,15 @@ export function parseTokens(
|
|||
|
||||
/**
|
||||
* resolve CSS var()
|
||||
* @param {string} value - color value including var()
|
||||
* @param {object} [opt] - options
|
||||
* @param {object} [opt.customProperty] - custom properties
|
||||
* @returns {?string} - value
|
||||
* @param value - CSS value including var()
|
||||
* @param [opt] - options
|
||||
* @returns resolved value
|
||||
*/
|
||||
export function cssVar(
|
||||
export function resolveVar(
|
||||
value: string,
|
||||
opt: {
|
||||
customProperty?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null {
|
||||
const { customProperty = {}, format } = opt;
|
||||
opt: Options = {}
|
||||
): string | NullObject {
|
||||
const { format = '' } = opt;
|
||||
if (isString(value)) {
|
||||
if (!REG_FN_VAR.test(value) || format === VAL_SPEC) {
|
||||
return value;
|
||||
|
@ -218,32 +205,46 @@ export function cssVar(
|
|||
} else {
|
||||
throw new TypeError(`${value} is not a string.`);
|
||||
}
|
||||
let cacheKey;
|
||||
if (
|
||||
typeof (
|
||||
customProperty as { callback?: (value: string) => string }
|
||||
).callback !== 'function'
|
||||
) {
|
||||
cacheKey = `{cssVar:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
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('') as string | null;
|
||||
if (REG_FN_MATH_CALC.test(color as string)) {
|
||||
color = cssCalc(color as string, opt) as string | null;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey as string, color!);
|
||||
let color = values.join('');
|
||||
if (REG_FN_CALC.test(color)) {
|
||||
color = cssCalc(color, opt);
|
||||
}
|
||||
setCache(cacheKey, color);
|
||||
return color;
|
||||
} else {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
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 '';
|
||||
};
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
/**
|
||||
* relative-color.js
|
||||
* relative-color
|
||||
*/
|
||||
|
||||
import { SyntaxFlag, color as colorParser } from '@csstools/css-color-parser';
|
||||
import { parseComponentValue } from '@csstools/css-parser-algorithms';
|
||||
import { TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import { isString } from './common';
|
||||
import { colorToRgb } from './convert';
|
||||
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 { resolve } from './resolve';
|
||||
import { roundToPrecision, valueToJsonString } from './util';
|
||||
|
||||
/* types */
|
||||
import type { ComponentValue } from '@csstools/css-parser-algorithms';
|
||||
import type { CSSToken } from '@csstools/css-tokenizer';
|
||||
import { resolveColor } from './resolve';
|
||||
import { roundToPrecision } from './util';
|
||||
import {
|
||||
ColorChannels,
|
||||
MatchedRegExp,
|
||||
Options,
|
||||
StringColorChannels
|
||||
} from './typedef';
|
||||
|
||||
/* constants */
|
||||
import {
|
||||
|
@ -25,12 +36,11 @@ import {
|
|||
FN_VAR,
|
||||
NONE,
|
||||
SYN_COLOR_TYPE,
|
||||
SYN_FN_MATH,
|
||||
SYN_FN_MATH_START,
|
||||
SYN_FN_VAR,
|
||||
SYN_MIX,
|
||||
VAL_SPEC
|
||||
} from './constant';
|
||||
import { NAMED_COLORS } from './color';
|
||||
const {
|
||||
CloseParen: PAREN_CLOSE,
|
||||
Comment: COMMENT,
|
||||
|
@ -43,52 +53,48 @@ const {
|
|||
Percentage: PCT,
|
||||
Whitespace: W_SPACE
|
||||
} = TokenType;
|
||||
const {
|
||||
HasNoneKeywords: NONE_KEY
|
||||
} = SyntaxFlag;
|
||||
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_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);
|
||||
const REG_REL = new RegExp(FN_REL);
|
||||
const REG_REL_CAPT = new RegExp(`^${FN_REL_CAPT}`);
|
||||
const REG_START_MATH = new RegExp(SYN_FN_MATH);
|
||||
const REG_START_REL = new RegExp(`^${FN_REL}`);
|
||||
|
||||
/* cached results */
|
||||
export const cachedResults = new LRUCache({
|
||||
max: 4096
|
||||
});
|
||||
|
||||
/**
|
||||
* resolve relative color channels
|
||||
* @param {Array.<Array>} tokens - tokens
|
||||
* @param {object} [opt] - options
|
||||
* @param {string} [opt.colorSpace] - color space
|
||||
* @returns {?Array.<string>} - resolved channels
|
||||
* @param tokens - CSS tokens
|
||||
* @param [opt] - options
|
||||
* @returns resolved color channels
|
||||
*/
|
||||
export function resolveColorChannels(
|
||||
tokens: Array<CSSToken>,
|
||||
opt: {
|
||||
colorSpace?: string;
|
||||
currentColor?: string;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): Array<string> | null {
|
||||
tokens: CSSToken[],
|
||||
opt: Options = {}
|
||||
): NumberOrStringColorChannels | NullObject {
|
||||
if (!Array.isArray(tokens)) {
|
||||
throw new TypeError(`${tokens} is not an array.`);
|
||||
}
|
||||
const { colorSpace, format } = opt;
|
||||
const { colorSpace = '', format = '' } = opt;
|
||||
const colorChannels = new Map([
|
||||
['color', ['r', 'g', 'b', 'alpha']],
|
||||
['hsl', ['h', 's', 'l', 'alpha']],
|
||||
|
@ -101,9 +107,18 @@ export function resolveColorChannels(
|
|||
['rgb', ['r', 'g', 'b', 'alpha']],
|
||||
['rgba', ['r', 'g', 'b', 'alpha']]
|
||||
]);
|
||||
const colorChannel = colorChannels.get(colorSpace as string);
|
||||
const colorChannel = colorChannels.get(colorSpace);
|
||||
// invalid color channel
|
||||
if (!colorChannel) {
|
||||
return new NullObject();
|
||||
}
|
||||
const mathFunc = new Set();
|
||||
const channels = [[], [], [], []] as Array<Array<string | number>>;
|
||||
const channels: [
|
||||
(number | string)[],
|
||||
(number | string)[],
|
||||
(number | string)[],
|
||||
(number | string)[]
|
||||
] = [[], [], [], []];
|
||||
let i = 0;
|
||||
let nest = 0;
|
||||
let func = false;
|
||||
|
@ -112,99 +127,103 @@ export function resolveColorChannels(
|
|||
if (!Array.isArray(token)) {
|
||||
throw new TypeError(`${token} is not an array.`);
|
||||
}
|
||||
const [type, value, , , detail = {}] = token;
|
||||
const numValue = (detail as {
|
||||
value?: number;
|
||||
})?.value as number | undefined;
|
||||
const channel = channels[i]!;
|
||||
switch (type as string) {
|
||||
case DIM: {
|
||||
let resolvedValue = resolveDimension(token, opt) as string | null;
|
||||
if (!resolvedValue) {
|
||||
resolvedValue = value as string;
|
||||
}
|
||||
channel.push(resolvedValue as string);
|
||||
break;
|
||||
}
|
||||
case FUNC: {
|
||||
channel.push(value);
|
||||
func = true;
|
||||
nest++;
|
||||
if (REG_START_MATH.test(value)) {
|
||||
mathFunc.add(nest);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDENT: {
|
||||
// invalid channel key
|
||||
if (!colorChannel || !colorChannel.includes(value)) {
|
||||
return null;
|
||||
}
|
||||
channel.push(value);
|
||||
if (!func) {
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NUM: {
|
||||
const n = numValue ?? parseFloat(value);
|
||||
channel.push(n);
|
||||
if (!func) {
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAREN_OPEN: {
|
||||
channel.push(value);
|
||||
nest++;
|
||||
break;
|
||||
}
|
||||
case PAREN_CLOSE: {
|
||||
if (func) {
|
||||
const lastValue = channel[channel.length - 1] as string | number;
|
||||
if (lastValue === ' ') {
|
||||
channel.splice(-1, 1, value);
|
||||
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 DIM: {
|
||||
const resolvedValue = resolveDimension(token, opt);
|
||||
if (isString(resolvedValue)) {
|
||||
channel.push(resolvedValue);
|
||||
} else {
|
||||
channel.push(value);
|
||||
}
|
||||
if (mathFunc.has(nest)) {
|
||||
mathFunc.delete(nest);
|
||||
break;
|
||||
}
|
||||
case FUNC: {
|
||||
channel.push(value);
|
||||
func = true;
|
||||
nest++;
|
||||
if (REG_FN_MATH_START.test(value)) {
|
||||
mathFunc.add(nest);
|
||||
}
|
||||
nest--;
|
||||
if (nest === 0) {
|
||||
func = false;
|
||||
break;
|
||||
}
|
||||
case IDENT: {
|
||||
// invalid channel key
|
||||
if (!colorChannel.includes(value)) {
|
||||
return new NullObject();
|
||||
}
|
||||
channel.push(value);
|
||||
if (!func) {
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PCT: {
|
||||
const n = numValue ?? parseFloat(value);
|
||||
channel.push(n / MAX_PCT);
|
||||
if (!func) {
|
||||
i++;
|
||||
case NUM: {
|
||||
channel.push(Number(detail?.value));
|
||||
if (!func) {
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case W_SPACE: {
|
||||
if (channel.length && func) {
|
||||
const lastValue = channel[channel.length - 1] as string | number;
|
||||
if (typeof lastValue === 'number') {
|
||||
channel.push(value);
|
||||
} else if (
|
||||
isString(lastValue) &&
|
||||
!lastValue.endsWith('(') &&
|
||||
lastValue !== ' '
|
||||
) {
|
||||
case PAREN_OPEN: {
|
||||
channel.push(value);
|
||||
nest++;
|
||||
break;
|
||||
}
|
||||
case PAREN_CLOSE: {
|
||||
if (func) {
|
||||
const lastValue = channel[channel.length - 1];
|
||||
if (lastValue === ' ') {
|
||||
channel.splice(-1, 1, value);
|
||||
} else {
|
||||
channel.push(value);
|
||||
}
|
||||
if (mathFunc.has(nest)) {
|
||||
mathFunc.delete(nest);
|
||||
}
|
||||
nest--;
|
||||
if (nest === 0) {
|
||||
func = false;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PCT: {
|
||||
channel.push(Number(detail?.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);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (type !== COMMENT && type !== EOF && func) {
|
||||
channel.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,215 +231,187 @@ export function resolveColorChannels(
|
|||
for (const channel of channels) {
|
||||
if (channel.length === 1) {
|
||||
const [resolvedValue] = channel;
|
||||
channelValues.push(resolvedValue as string);
|
||||
if (isStringOrNumber(resolvedValue)) {
|
||||
channelValues.push(resolvedValue);
|
||||
}
|
||||
} else if (channel.length) {
|
||||
const resolvedValue = serializeCalc(channel.join(''), {
|
||||
format
|
||||
});
|
||||
if (resolvedValue) {
|
||||
channelValues.push(resolvedValue);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
channelValues.push(resolvedValue);
|
||||
}
|
||||
}
|
||||
return channelValues;
|
||||
return channelValues as NumberOrStringColorChannels;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract origin color
|
||||
* @param {string} value - color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {string} [opt.currentColor] - current color value
|
||||
* @returns {?string} - value
|
||||
* @param value - CSS color value
|
||||
* @param [opt] - options
|
||||
* @returns origin color value
|
||||
*/
|
||||
export function extractOriginColor(
|
||||
value: string,
|
||||
opt: {
|
||||
colorSpace?: string;
|
||||
currentColor?: string;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null {
|
||||
opt: Options = {}
|
||||
): string | NullObject {
|
||||
const { currentColor = '', format = '' } = opt;
|
||||
if (isString(value)) {
|
||||
value = value.toLowerCase().trim();
|
||||
if (!value) {
|
||||
return null;
|
||||
return new NullObject();
|
||||
}
|
||||
if (!REG_START_REL.test(value)) {
|
||||
if (!REG_FN_REL_START.test(value)) {
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
return new NullObject();
|
||||
}
|
||||
const { currentColor, format } = opt;
|
||||
const cacheKey = `{preProcess:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
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 {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
setCache(cacheKey, null);
|
||||
return new NullObject();
|
||||
}
|
||||
}
|
||||
const cs = value.match(REG_REL_CAPT);
|
||||
let colorSpace: string;
|
||||
if (cs) {
|
||||
[, colorSpace] = cs as [string, string];
|
||||
} else {
|
||||
return null;
|
||||
let colorSpace = '';
|
||||
if (REG_FN_REL_CAPT.test(value)) {
|
||||
[, colorSpace] = value.match(REG_FN_REL_CAPT) as MatchedRegExp;
|
||||
}
|
||||
opt.colorSpace = colorSpace;
|
||||
if (REG_COLOR_CAPT.test(value)) {
|
||||
const [, originColor] = value.match(REG_COLOR_CAPT) as [string, string];
|
||||
const [, restValue] = value.split(originColor);
|
||||
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.prototype.hasOwnProperty.call(NAMED_COLORS, originColor)
|
||||
) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
setCache(cacheKey, null);
|
||||
return new NullObject();
|
||||
}
|
||||
} else if (format === VAL_SPEC) {
|
||||
const resolvedOriginColor = resolve(originColor, opt) as string;
|
||||
value = value.replace(originColor, resolvedOriginColor);
|
||||
const resolvedOriginColor = resolveColor(originColor, opt);
|
||||
if (isString(resolvedOriginColor)) {
|
||||
value = value.replace(originColor, resolvedOriginColor);
|
||||
}
|
||||
}
|
||||
if (format === VAL_SPEC) {
|
||||
const tokens = tokenize({ css: restValue as string });
|
||||
const channelValues =
|
||||
resolveColorChannels(tokens, opt) as Array<string> | null;
|
||||
if (!Array.isArray(channelValues)) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
const tokens = tokenize({ css: restValue });
|
||||
const channelValues = resolveColorChannels(tokens, opt);
|
||||
if (channelValues instanceof NullObject) {
|
||||
setCache(cacheKey, null);
|
||||
return channelValues;
|
||||
}
|
||||
let channelValue;
|
||||
if (channelValues.length === 3) {
|
||||
channelValue = ` ${channelValues.join(' ')})`;
|
||||
} else {
|
||||
const [v1, v2, v3, v4] = channelValues as [
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
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);
|
||||
}
|
||||
value = value.replace(restValue!, channelValue);
|
||||
}
|
||||
// nested relative color
|
||||
} else {
|
||||
const [, restValue] = value.split(REG_START_REL) as [
|
||||
string,
|
||||
string
|
||||
];
|
||||
if (REG_START_REL.test(restValue)) {
|
||||
const tokens = tokenize({ css: restValue });
|
||||
const originColor = [] as Array<string>;
|
||||
let nest = 0;
|
||||
while (tokens.length) {
|
||||
const token = tokens.shift();
|
||||
const [type, tokenValue] = token as [TokenType, string];
|
||||
switch (type) {
|
||||
case FUNC:
|
||||
case PAREN_OPEN: {
|
||||
originColor.push(tokenValue);
|
||||
nest++;
|
||||
break;
|
||||
}
|
||||
case PAREN_CLOSE: {
|
||||
const lastValue = originColor[originColor.length - 1] as string;
|
||||
if (lastValue === ' ') {
|
||||
originColor.splice(-1, 1, tokenValue);
|
||||
} else {
|
||||
originColor.push(tokenValue);
|
||||
}
|
||||
nest--;
|
||||
break;
|
||||
}
|
||||
case W_SPACE: {
|
||||
const lastValue = originColor[originColor.length - 1] as string;
|
||||
if (!lastValue.endsWith('(') && lastValue !== ' ') {
|
||||
originColor.push(tokenValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (type !== COMMENT && type !== EOF) {
|
||||
originColor.push(tokenValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nest === 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
const resolvedOriginColor = resolveRelativeColor(
|
||||
originColor.join('').trim(),
|
||||
opt
|
||||
) as string | null;
|
||||
if (!resolvedOriginColor) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
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;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const channelValues =
|
||||
resolveColorChannels(tokens, opt) as Array<string> | null;
|
||||
if (!Array.isArray(channelValues)) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
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);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
let channelValue;
|
||||
if (channelValues.length === 3) {
|
||||
channelValue = ` ${channelValues.join(' ')})`;
|
||||
} else {
|
||||
const [v1, v2, v3, v4] = channelValues as [
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
channelValue = ` ${v1} ${v2} ${v3} / ${v4})`;
|
||||
if (nest === 0) {
|
||||
break;
|
||||
}
|
||||
value = value.replace(restValue, `${resolvedOriginColor}${channelValue}`);
|
||||
}
|
||||
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}`);
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, value);
|
||||
}
|
||||
setCache(cacheKey, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve relative color
|
||||
* @param {string} value - relative color value
|
||||
* @param {object} [opt] - options
|
||||
* @param {string} [opt.format] - output format
|
||||
* @returns {?string} - value
|
||||
* @param value - CSS relative color value
|
||||
* @param [opt] - options
|
||||
* @returns resolved value
|
||||
*/
|
||||
export function resolveRelativeColor(
|
||||
value: string,
|
||||
opt: {
|
||||
colorSpace?: string;
|
||||
currentColor?: string;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
} = {}
|
||||
): string | null {
|
||||
const { format } = opt;
|
||||
opt: Options = {}
|
||||
): string | NullObject {
|
||||
const { format = '' } = opt;
|
||||
if (isString(value)) {
|
||||
if (REG_FN_VAR.test(value)) {
|
||||
if (format === VAL_SPEC) {
|
||||
|
@ -429,26 +420,34 @@ export function resolveRelativeColor(
|
|||
} else {
|
||||
throw new SyntaxError(`Unexpected token ${FN_VAR} found.`);
|
||||
}
|
||||
} else if (!REG_REL.test(value)) {
|
||||
} else if (!REG_FN_REL.test(value)) {
|
||||
return value;
|
||||
}
|
||||
value = value.toLowerCase().trim();
|
||||
} else {
|
||||
throw new TypeError(`${value} is not a string`);
|
||||
throw new TypeError(`${value} is not a string.`);
|
||||
}
|
||||
const cacheKey = `{relativeColor:${value},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | null;
|
||||
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) {
|
||||
value = originColor;
|
||||
} else {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
if (originColor instanceof NullObject) {
|
||||
setCache(cacheKey, null);
|
||||
return originColor;
|
||||
}
|
||||
value = originColor;
|
||||
if (format === VAL_SPEC) {
|
||||
if (value.startsWith('rgba(')) {
|
||||
value = value.replace(/^rgba\(/, 'rgb(');
|
||||
|
@ -458,13 +457,11 @@ export function resolveRelativeColor(
|
|||
return value;
|
||||
}
|
||||
const tokens = tokenize({ css: value });
|
||||
const components = parseComponentValue(tokens);
|
||||
const parsedComponents = colorParser(components as ComponentValue);
|
||||
const components = parseComponentValue(tokens) as ComponentValue;
|
||||
const parsedComponents = colorParser(components);
|
||||
if (!parsedComponents) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
setCache(cacheKey, null);
|
||||
return new NullObject();
|
||||
}
|
||||
const {
|
||||
alpha: alphaComponent,
|
||||
|
@ -474,13 +471,13 @@ export function resolveRelativeColor(
|
|||
} = parsedComponents;
|
||||
let alpha: number | string;
|
||||
if (Number.isNaN(Number(alphaComponent))) {
|
||||
if ((syntaxFlags instanceof Set) && syntaxFlags.has(NONE_KEY)) {
|
||||
if (syntaxFlags instanceof Set && syntaxFlags.has(KEY_NONE)) {
|
||||
alpha = NONE;
|
||||
} else {
|
||||
alpha = 0;
|
||||
}
|
||||
} else {
|
||||
alpha = roundToPrecision(alphaComponent as number, OCT);
|
||||
alpha = roundToPrecision(Number(alphaComponent), OCT);
|
||||
}
|
||||
let v1: number | string;
|
||||
let v2: number | string;
|
||||
|
@ -488,7 +485,7 @@ export function resolveRelativeColor(
|
|||
[v1, v2, v3] = channelsComponent;
|
||||
let resolvedValue;
|
||||
if (REG_CS_CIE.test(colorNotation)) {
|
||||
const hasNone = (syntaxFlags instanceof Set) && syntaxFlags.has(NONE_KEY);
|
||||
const hasNone = syntaxFlags instanceof Set && syntaxFlags.has(KEY_NONE);
|
||||
if (Number.isNaN(v1)) {
|
||||
if (hasNone) {
|
||||
v1 = NONE;
|
||||
|
@ -531,9 +528,9 @@ export function resolveRelativeColor(
|
|||
if (Number.isNaN(v3)) {
|
||||
v3 = 0;
|
||||
}
|
||||
let [r, g, b] = colorToRgb(
|
||||
let [r, g, b] = convertColorToRgb(
|
||||
`${colorNotation}(${v1} ${v2} ${v3} / ${alpha})`
|
||||
) as [number, number, number];
|
||||
) as ColorChannels;
|
||||
r = roundToPrecision(r / MAX_RGB, DEC);
|
||||
g = roundToPrecision(g / MAX_RGB, DEC);
|
||||
b = roundToPrecision(b / MAX_RGB, DEC);
|
||||
|
@ -544,7 +541,7 @@ export function resolveRelativeColor(
|
|||
}
|
||||
} else {
|
||||
const cs = colorNotation === 'rgb' ? 'srgb' : colorNotation;
|
||||
const hasNone = (syntaxFlags instanceof Set) && syntaxFlags.has(NONE_KEY);
|
||||
const hasNone = syntaxFlags instanceof Set && syntaxFlags.has(KEY_NONE);
|
||||
if (Number.isNaN(v1)) {
|
||||
if (hasNone) {
|
||||
v1 = NONE;
|
||||
|
@ -578,8 +575,6 @@ export function resolveRelativeColor(
|
|||
resolvedValue = `color(${cs} ${v1} ${v2} ${v3} / ${alpha})`;
|
||||
}
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, resolvedValue);
|
||||
}
|
||||
setCache(cacheKey, resolvedValue);
|
||||
return resolvedValue;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
/**
|
||||
* resolve.js
|
||||
* resolve
|
||||
*/
|
||||
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import {
|
||||
CacheItem,
|
||||
NullObject,
|
||||
createCacheKey,
|
||||
getCache,
|
||||
setCache
|
||||
} from './cache';
|
||||
import {
|
||||
convertRgbToHex,
|
||||
resolveColorFunc,
|
||||
|
@ -11,66 +17,349 @@ import {
|
|||
} from './color';
|
||||
import { isString } from './common';
|
||||
import { cssCalc } from './css-calc';
|
||||
import { cssVar } from './css-var';
|
||||
import { resolveVar } from './css-var';
|
||||
import { resolveRelativeColor } from './relative-color';
|
||||
import { valueToJsonString } from './util';
|
||||
import {
|
||||
ComputedColorChannels,
|
||||
Options,
|
||||
SpecifiedColorChannels
|
||||
} from './typedef';
|
||||
|
||||
/* constants */
|
||||
import {
|
||||
FN_COLOR,
|
||||
FN_MIX,
|
||||
SYN_FN_MATH_CALC,
|
||||
SYN_FN_CALC,
|
||||
SYN_FN_REL,
|
||||
SYN_FN_VAR,
|
||||
VAL_COMP,
|
||||
VAL_SPEC
|
||||
} from './constant.js';
|
||||
|
||||
} from './constant';
|
||||
const NAMESPACE = 'resolve';
|
||||
const RGB_TRANSPARENT = 'rgba(0, 0, 0, 0)';
|
||||
|
||||
/* regexp */
|
||||
const REG_FN_MATH_CALC = new RegExp(SYN_FN_MATH_CALC);
|
||||
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);
|
||||
|
||||
/* cached results */
|
||||
export const cachedResults = new LRUCache({
|
||||
max: 4096
|
||||
});
|
||||
/**
|
||||
* 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 { 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_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 {string} color - color value
|
||||
* @param value
|
||||
* - CSS color value
|
||||
* - system colors are not supported
|
||||
* @param {object} [opt] - options
|
||||
* @param {string} [opt.currentColor]
|
||||
* @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 {object} [opt.customProperty]
|
||||
* @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 {object} [opt.dimension]
|
||||
* @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 {string} [opt.format]
|
||||
* @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`
|
||||
* @param {*} [opt.key] - key e.g. CSS property `background-color`
|
||||
* @returns {?string|Array}
|
||||
* @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 or [key, rgba?()] etc. if `key` is specified
|
||||
* 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
|
||||
|
@ -80,369 +369,11 @@ export const cachedResults = new LRUCache({
|
|||
* - in `hexAlpha`, returns `#00000000` for `transparent`,
|
||||
* however returns `null` if any of `r`, `g`, `b`, `alpha` is not a number
|
||||
*/
|
||||
export const resolve = (
|
||||
color: string,
|
||||
opt: {
|
||||
currentColor?: string;
|
||||
customProperty?: object;
|
||||
dimension?: object;
|
||||
format?: string;
|
||||
key?: any;
|
||||
} = {}
|
||||
): (string | Array<any>) | null => {
|
||||
if (isString(color)) {
|
||||
color = color.trim();
|
||||
} else {
|
||||
throw new TypeError(`${color} is not a string.`);
|
||||
export const resolve = (value: string, opt: Options = {}): string | null => {
|
||||
opt.nullable = false;
|
||||
const resolvedValue = resolveColor(value, opt);
|
||||
if (resolvedValue instanceof NullObject) {
|
||||
return null;
|
||||
}
|
||||
const { currentColor, customProperty = {}, format = VAL_COMP, key } = opt;
|
||||
let cacheKey;
|
||||
if (
|
||||
!REG_FN_VAR.test(color) ||
|
||||
typeof (
|
||||
customProperty as { callback?: (value: string) => string }
|
||||
).callback === 'function'
|
||||
) {
|
||||
cacheKey = `{resolve:${color},opt:${valueToJsonString(opt)}}`;
|
||||
if (cachedResults.has(cacheKey)) {
|
||||
return cachedResults.get(cacheKey) as string | Array<any>;
|
||||
}
|
||||
}
|
||||
let res, cs, r, g, b, alpha;
|
||||
if (REG_FN_VAR.test(color)) {
|
||||
if (format === VAL_SPEC) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, color);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
const resolvedColor = cssVar(color, opt);
|
||||
if (resolvedColor) {
|
||||
color = resolvedColor;
|
||||
} else {
|
||||
switch (format) {
|
||||
case 'hex':
|
||||
case 'hexAlpha': {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
default: {
|
||||
res = RGB_TRANSPARENT;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opt.format !== format) {
|
||||
opt.format = format;
|
||||
}
|
||||
color = color.toLowerCase();
|
||||
if (REG_FN_REL.test(color)) {
|
||||
const resolvedColor = resolveRelativeColor(color, opt) as string | null;
|
||||
if (format === VAL_COMP) {
|
||||
if (resolvedColor) {
|
||||
res = resolvedColor;
|
||||
} else {
|
||||
res = RGB_TRANSPARENT;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
if (format === VAL_SPEC) {
|
||||
if (resolvedColor) {
|
||||
res = resolvedColor;
|
||||
} else {
|
||||
res = '';
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
if (resolvedColor) {
|
||||
color = resolvedColor;
|
||||
} else {
|
||||
color = '';
|
||||
}
|
||||
}
|
||||
if (REG_FN_MATH_CALC.test(color)) {
|
||||
const resolvedColor = cssCalc(color, opt) as string | null;
|
||||
if (resolvedColor) {
|
||||
color = resolvedColor;
|
||||
} else {
|
||||
color = '';
|
||||
}
|
||||
}
|
||||
if (color === 'transparent') {
|
||||
switch (format) {
|
||||
case VAL_SPEC: {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, color);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
case 'hex': {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, null!);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
case 'hexAlpha': {
|
||||
res = '#00000000';
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
case VAL_COMP:
|
||||
default: {
|
||||
res = RGB_TRANSPARENT;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
} else if (color === 'currentcolor') {
|
||||
if (format === VAL_SPEC) {
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, color);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
if (currentColor) {
|
||||
if (currentColor.startsWith(FN_MIX)) {
|
||||
[cs, r, g, b, alpha] = resolveColorMix(currentColor, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
} else if (currentColor.startsWith(FN_COLOR)) {
|
||||
[cs, r, g, b, alpha] = resolveColorFunc(currentColor, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
} else {
|
||||
[cs, r, g, b, alpha] = resolveColorValue(currentColor, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
}
|
||||
} else if (format === VAL_COMP) {
|
||||
res = RGB_TRANSPARENT;
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else if (format === VAL_SPEC) {
|
||||
if (color.startsWith(FN_MIX)) {
|
||||
res = resolveColorMix(color, opt);
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res!);
|
||||
}
|
||||
return res;
|
||||
} else if (color.startsWith(FN_COLOR)) {
|
||||
[cs, r, g, b, alpha] = resolveColorFunc(color, opt) as [
|
||||
string,
|
||||
number | string,
|
||||
number | string,
|
||||
number | string,
|
||||
number | string
|
||||
];
|
||||
if (alpha === 1) {
|
||||
res = `color(${cs} ${r} ${g} ${b})`;
|
||||
} else {
|
||||
res = `color(${cs} ${r} ${g} ${b} / ${alpha})`;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
const rgb = resolveColorValue(color, opt);
|
||||
if (!rgb) {
|
||||
res = '';
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
[cs, r, g, b, alpha] = rgb;
|
||||
if (cs === 'rgb') {
|
||||
if (alpha === 1) {
|
||||
res = `${cs}(${r}, ${g}, ${b})`;
|
||||
} else {
|
||||
res = `${cs}a(${r}, ${g}, ${b}, ${alpha})`;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
if (alpha === 1) {
|
||||
res = `${cs}(${r} ${g} ${b})`;
|
||||
} else {
|
||||
res = `${cs}(${r} ${g} ${b} / ${alpha})`;
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else if (/currentcolor/.test(color)) {
|
||||
if (currentColor) {
|
||||
color = color.replace(/currentcolor/g, currentColor);
|
||||
}
|
||||
if (/transparent/.test(color)) {
|
||||
color = color.replace(/transparent/g, RGB_TRANSPARENT);
|
||||
}
|
||||
if (color.startsWith(FN_MIX)) {
|
||||
[cs, r, g, b, alpha] = resolveColorMix(color, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
}
|
||||
} else if (/transparent/.test(color)) {
|
||||
color = color.replace(/transparent/g, RGB_TRANSPARENT);
|
||||
if (color.startsWith(FN_MIX)) {
|
||||
[cs, r, g, b, alpha] = resolveColorMix(color, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
}
|
||||
} else if (color.startsWith(FN_MIX)) {
|
||||
[cs, r, g, b, alpha] = resolveColorMix(color, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
} else if (color.startsWith(FN_COLOR)) {
|
||||
[cs, r, g, b, alpha] = resolveColorFunc(color, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
} else if (color) {
|
||||
[cs, r, g, b, alpha] = resolveColorValue(color, opt) as [
|
||||
string,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number
|
||||
];
|
||||
}
|
||||
switch (format) {
|
||||
case 'hex': {
|
||||
let hex;
|
||||
if (
|
||||
isNaN(r as number) ||
|
||||
isNaN(g as number) ||
|
||||
isNaN(b as number) ||
|
||||
isNaN(alpha as number) ||
|
||||
alpha === 0
|
||||
) {
|
||||
hex = null;
|
||||
} else {
|
||||
hex = convertRgbToHex([r as number, g as number, b as number]);
|
||||
}
|
||||
if (key) {
|
||||
res = [key, hex];
|
||||
} else {
|
||||
res = hex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'hexAlpha': {
|
||||
let hex;
|
||||
if (
|
||||
isNaN(r as number) ||
|
||||
isNaN(g as number) ||
|
||||
isNaN(b as number) ||
|
||||
isNaN(alpha as number)
|
||||
) {
|
||||
hex = null;
|
||||
} else {
|
||||
hex = convertRgbToHex([
|
||||
r as number,
|
||||
g as number,
|
||||
b as number,
|
||||
alpha as number
|
||||
]);
|
||||
}
|
||||
if (key) {
|
||||
res = [key, hex];
|
||||
} else {
|
||||
res = hex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VAL_COMP:
|
||||
default: {
|
||||
let value;
|
||||
switch (cs) {
|
||||
case 'rgb': {
|
||||
if (alpha === 1) {
|
||||
value = `${cs}(${r}, ${g}, ${b})`;
|
||||
} else {
|
||||
value = `${cs}a(${r}, ${g}, ${b}, ${alpha})`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'lab':
|
||||
case 'lch':
|
||||
case 'oklab':
|
||||
case 'oklch': {
|
||||
if (alpha === 1) {
|
||||
value = `${cs}(${r} ${g} ${b})`;
|
||||
} else {
|
||||
value = `${cs}(${r} ${g} ${b} / ${alpha})`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// color()
|
||||
default: {
|
||||
if (alpha === 1) {
|
||||
value = `color(${cs} ${r} ${g} ${b})`;
|
||||
} else {
|
||||
value = `color(${cs} ${r} ${g} ${b} / ${alpha})`;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key) {
|
||||
res = [key, value];
|
||||
} else {
|
||||
res = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cacheKey) {
|
||||
cachedResults.set(cacheKey, res!);
|
||||
}
|
||||
return res;
|
||||
return resolvedValue as string;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* typedef
|
||||
*/
|
||||
|
||||
/* type definitions */
|
||||
/**
|
||||
* @typedef Options - options
|
||||
* @property [alpha] - enable alpha
|
||||
* @property [colorSpace] - color space
|
||||
* @property [currentColor] - color for currentcolor
|
||||
* @property [customPropeerty] - custom properties
|
||||
* @property [d50] - white point in d50
|
||||
* @property [dimension] - dimension
|
||||
* @property [format] - output format
|
||||
* @property [key] - key
|
||||
*/
|
||||
export interface Options {
|
||||
alpha?: boolean;
|
||||
colorSpace?: string;
|
||||
currentColor?: string;
|
||||
customProperty?: Record<string, string | ((K: string) => string)>;
|
||||
d50?: boolean;
|
||||
delimiter?: string | string[];
|
||||
dimension?: Record<string, number | ((K: string) => number)>;
|
||||
format?: string;
|
||||
nullable?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type ColorChannels - color channels
|
||||
*/
|
||||
export type ColorChannels = [x: number, y: number, z: number, alpha: number];
|
||||
|
||||
/**
|
||||
* @type StringColorChannels - color channels
|
||||
*/
|
||||
export type StringColorChannels = [
|
||||
x: string,
|
||||
y: string,
|
||||
z: string,
|
||||
alpha: string | undefined
|
||||
];
|
||||
|
||||
/**
|
||||
* @type StringColorSpacedChannels - specified value
|
||||
*/
|
||||
export type StringColorSpacedChannels = [
|
||||
cs: string,
|
||||
x: string,
|
||||
y: string,
|
||||
z: string,
|
||||
alpha: string | undefined
|
||||
];
|
||||
|
||||
/**
|
||||
* @type ComputedColorChannels - computed value
|
||||
*/
|
||||
export type ComputedColorChannels = [
|
||||
cs: string,
|
||||
x: number,
|
||||
y: number,
|
||||
z: number,
|
||||
alpha: number
|
||||
];
|
||||
|
||||
/**
|
||||
* @type SpecifiedColorChannels - specified value
|
||||
*/
|
||||
export type SpecifiedColorChannels = [
|
||||
cs: string,
|
||||
x: number | string,
|
||||
y: number | string,
|
||||
z: number | string,
|
||||
alpha: number | string
|
||||
];
|
||||
|
||||
/**
|
||||
* @type MatchedRegExp - matched regexp array
|
||||
*/
|
||||
export type MatchedRegExp = [
|
||||
match: string,
|
||||
gr1: string,
|
||||
gr2: string,
|
||||
gr3: string,
|
||||
gr4: string
|
||||
];
|
|
@ -1,13 +1,29 @@
|
|||
/**
|
||||
* util.js
|
||||
* util
|
||||
*/
|
||||
|
||||
import { TokenType, tokenize } from '@csstools/css-tokenizer';
|
||||
import { CacheItem, createCacheKey, getCache, setCache } from './cache';
|
||||
import { isString } from './common';
|
||||
import { resolve } from './resolve';
|
||||
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,
|
||||
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;
|
||||
|
@ -15,17 +31,141 @@ const DEG_HALF = 180;
|
|||
|
||||
/* regexp */
|
||||
const REG_COLOR = new RegExp(`^(?:${SYN_COLOR_TYPE})$`);
|
||||
const REG_MIX = new RegExp(`${SYN_MIX}`);
|
||||
const REG_MIX = new RegExp(SYN_MIX);
|
||||
|
||||
/**
|
||||
* split value
|
||||
* @param value - CSS value
|
||||
* @param [delimiter] - comma or space
|
||||
* @returns array of values, NOTE: comments are stripped
|
||||
*/
|
||||
export const splitValue = (value: string, delimiter: string = ''): string[] => {
|
||||
if (isString(value)) {
|
||||
value = value.trim();
|
||||
} else {
|
||||
throw new TypeError(`${value} is not a string.`);
|
||||
}
|
||||
const cacheKey: string = createCacheKey(
|
||||
{
|
||||
namespace: NAMESPACE,
|
||||
name: 'splitValue',
|
||||
value
|
||||
},
|
||||
{
|
||||
delimiter
|
||||
}
|
||||
);
|
||||
const cachedResult = getCache(cacheKey);
|
||||
if (cachedResult instanceof CacheItem) {
|
||||
return cachedResult.item as string[];
|
||||
}
|
||||
const regDelimiter = delimiter === ',' ? /^,$/ : /^\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 COMMENT: {
|
||||
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 {string} value - value
|
||||
* @returns {boolean} - result
|
||||
* @param value - CSS value
|
||||
* @param [opt] - options
|
||||
* @returns result
|
||||
*/
|
||||
export const isColor = (value: string): boolean => {
|
||||
export const isColor = (value: unknown, opt: Options = {}): boolean => {
|
||||
if (isString(value)) {
|
||||
value = value.toLowerCase().trim();
|
||||
if (value) {
|
||||
if (value && isString(value)) {
|
||||
if (/^[a-z]+$/.test(value)) {
|
||||
if (
|
||||
/^(?:currentcolor|transparent)$/.test(value) ||
|
||||
|
@ -36,13 +176,14 @@ export const isColor = (value: string): boolean => {
|
|||
} else if (REG_COLOR.test(value) || REG_MIX.test(value)) {
|
||||
return true;
|
||||
} else {
|
||||
const resolvedValue = resolve(value, {
|
||||
format: VAL_SPEC
|
||||
});
|
||||
opt.nullable = true;
|
||||
if (!opt.format) {
|
||||
opt.format = VAL_SPEC;
|
||||
}
|
||||
const resolvedValue = resolveColor(value, opt);
|
||||
if (resolvedValue) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +192,12 @@ export const isColor = (value: string): boolean => {
|
|||
|
||||
/**
|
||||
* value to JSON string
|
||||
* @param {*} value - value
|
||||
* @param {boolean} func - stringify function
|
||||
* @returns {string} - stringified value in JSON notation
|
||||
* @param value - CSS value
|
||||
* @param [func] - stringify function
|
||||
* @returns stringified value in JSON notation
|
||||
*/
|
||||
export const valueToJsonString = (
|
||||
value: any,
|
||||
value: unknown,
|
||||
func: boolean = false
|
||||
): string => {
|
||||
if (typeof value === 'undefined') {
|
||||
|
@ -68,7 +209,7 @@ export const valueToJsonString = (
|
|||
replacedValue = null;
|
||||
} else if (typeof val === 'function') {
|
||||
if (func) {
|
||||
replacedValue = val.toString();
|
||||
replacedValue = val.toString().replace(/\s/g, '').substring(0, HEX);
|
||||
} else {
|
||||
replacedValue = val.name;
|
||||
}
|
||||
|
@ -86,16 +227,16 @@ export const valueToJsonString = (
|
|||
|
||||
/**
|
||||
* round to specified precision
|
||||
* @param {number} value - value
|
||||
* @param {number} bit - minimum bits
|
||||
* @returns {number} - rounded value
|
||||
* @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 number.`);
|
||||
throw new TypeError(`${value} is not a finite number.`);
|
||||
}
|
||||
if (!Number.isFinite(bit)) {
|
||||
throw new TypeError(`${bit} is not a number.`);
|
||||
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}.`);
|
||||
}
|
||||
|
@ -115,21 +256,21 @@ export const roundToPrecision = (value: number, bit: number = 0): number => {
|
|||
|
||||
/**
|
||||
* interpolate hue
|
||||
* @param {number} hueA - hue
|
||||
* @param {number} hueB - hue
|
||||
* @param {string} arc - arc
|
||||
* @returns {Array} - [hueA, hueB]
|
||||
* @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'
|
||||
): Array<number> => {
|
||||
): [number, number] => {
|
||||
if (!Number.isFinite(hueA)) {
|
||||
throw new TypeError(`${hueA} is not a number.`);
|
||||
throw new TypeError(`${hueA} is not a finite number.`);
|
||||
}
|
||||
if (!Number.isFinite(hueB)) {
|
||||
throw new TypeError(`${hueB} is not a number.`);
|
||||
throw new TypeError(`${hueB} is not a finite number.`);
|
||||
}
|
||||
switch (arc) {
|
||||
case 'decreasing': {
|
||||
|
|
|
@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||
});
|
||||
exports.default = loadCodeDefault;
|
||||
exports.supportsESM = void 0;
|
||||
var _async3 = require("../../gensync-utils/async.js");
|
||||
var _async = require("../../gensync-utils/async.js");
|
||||
function _path() {
|
||||
const data = require("path");
|
||||
_path = function () {
|
||||
|
@ -89,7 +89,6 @@ const SUPPORTED_EXTENSIONS = {
|
|||
};
|
||||
const asyncModules = new Set();
|
||||
function* loadCodeDefault(filepath, loader, esmError, tlaError) {
|
||||
var _async2;
|
||||
let async;
|
||||
const ext = _path().extname(filepath);
|
||||
const isTS = ext === ".ts" || ext === ".cts" || ext === ".mts";
|
||||
|
@ -114,9 +113,8 @@ function* loadCodeDefault(filepath, loader, esmError, tlaError) {
|
|||
}
|
||||
} catch (e) {
|
||||
if (e.code === "ERR_REQUIRE_ASYNC_MODULE" || e.code === "ERR_REQUIRE_CYCLE_MODULE" && asyncModules.has(filepath)) {
|
||||
var _async;
|
||||
asyncModules.add(filepath);
|
||||
if (!((_async = async) != null ? _async : async = yield* (0, _async3.isAsync)())) {
|
||||
if (!(async != null ? async : async = yield* (0, _async.isAsync)())) {
|
||||
throw new _configError.default(tlaError, filepath);
|
||||
}
|
||||
} else if (e.code === "ERR_REQUIRE_ESM" || type === "esm") {} else {
|
||||
|
@ -124,9 +122,9 @@ function* loadCodeDefault(filepath, loader, esmError, tlaError) {
|
|||
}
|
||||
}
|
||||
case "auto esm":
|
||||
if ((_async2 = async) != null ? _async2 : async = yield* (0, _async3.isAsync)()) {
|
||||
if (async != null ? async : async = yield* (0, _async.isAsync)()) {
|
||||
const promise = isTS ? ensureTsSupport(filepath, ext, () => loadMjsFromPath(filepath)) : loadMjsFromPath(filepath);
|
||||
return (yield* (0, _async3.waitFor)(promise)).default;
|
||||
return (yield* (0, _async.waitFor)(promise)).default;
|
||||
}
|
||||
throw new _configError.default(esmError, filepath);
|
||||
default:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,7 +21,7 @@ var _options = require("./validation/options.js");
|
|||
var _index = require("./files/index.js");
|
||||
var _resolveTargets = require("./resolve-targets.js");
|
||||
const _excluded = ["showIgnoredFiles"];
|
||||
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
|
||||
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
||||
function resolveRootMode(rootDir, rootMode) {
|
||||
switch (rootMode) {
|
||||
case "root":
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -212,7 +212,7 @@ var _transformFile = require("./transform-file.js");
|
|||
var _transformAst = require("./transform-ast.js");
|
||||
var _parse = require("./parse.js");
|
||||
;
|
||||
const version = exports.version = "7.26.9";
|
||||
const version = exports.version = "7.26.10";
|
||||
const resolvePlugin = (name, dirname) => resolvers.resolvePlugin(name, dirname, false).filepath;
|
||||
exports.resolvePlugin = resolvePlugin;
|
||||
const resolvePreset = (name, dirname) => resolvers.resolvePreset(name, dirname, false).filepath;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4,32 +4,52 @@ Object.defineProperty(exports, "__esModule", {
|
|||
value: true
|
||||
});
|
||||
exports.default = _default;
|
||||
function deepClone(value, cache) {
|
||||
const circleSet = new Set();
|
||||
let depth = 0;
|
||||
function deepClone(value, cache, allowCircle) {
|
||||
if (value !== null) {
|
||||
if (cache.has(value)) return cache.get(value);
|
||||
if (allowCircle) {
|
||||
if (cache.has(value)) return cache.get(value);
|
||||
} else if (++depth > 250) {
|
||||
if (circleSet.has(value)) {
|
||||
depth = 0;
|
||||
circleSet.clear();
|
||||
throw new Error("Babel-deepClone: Cycles are not allowed in AST");
|
||||
}
|
||||
circleSet.add(value);
|
||||
}
|
||||
let cloned;
|
||||
if (Array.isArray(value)) {
|
||||
cloned = new Array(value.length);
|
||||
cache.set(value, cloned);
|
||||
if (allowCircle) cache.set(value, cloned);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
cloned[i] = typeof value[i] !== "object" ? value[i] : deepClone(value[i], cache);
|
||||
cloned[i] = typeof value[i] !== "object" ? value[i] : deepClone(value[i], cache, allowCircle);
|
||||
}
|
||||
} else {
|
||||
cloned = {};
|
||||
cache.set(value, cloned);
|
||||
if (allowCircle) cache.set(value, cloned);
|
||||
const keys = Object.keys(value);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
cloned[key] = typeof value[key] !== "object" ? value[key] : deepClone(value[key], cache);
|
||||
cloned[key] = typeof value[key] !== "object" ? value[key] : deepClone(value[key], cache, allowCircle || key === "leadingComments" || key === "innerComments" || key === "trailingComments" || key === "extra");
|
||||
}
|
||||
}
|
||||
if (!allowCircle) {
|
||||
if (depth-- > 250) circleSet.delete(value);
|
||||
}
|
||||
return cloned;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function _default(value) {
|
||||
if (typeof value !== "object") return value;
|
||||
return deepClone(value, new Map());
|
||||
{
|
||||
try {
|
||||
return deepClone(value, new Map(), true);
|
||||
} catch (_) {
|
||||
return structuredClone(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
0 && 0;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"names":["deepClone","value","cache","has","get","cloned","Array","isArray","length","set","i","keys","Object","key","_default","Map"],"sources":["../../../src/transformation/util/clone-deep.ts"],"sourcesContent":["//https://github.com/babel/babel/pull/14583#discussion_r882828856\nfunction deepClone(value: any, cache: Map<any, any>): any {\n if (value !== null) {\n if (cache.has(value)) return cache.get(value);\n let cloned: any;\n if (Array.isArray(value)) {\n cloned = new Array(value.length);\n cache.set(value, cloned);\n for (let i = 0; i < value.length; i++) {\n cloned[i] =\n typeof value[i] !== \"object\" ? value[i] : deepClone(value[i], cache);\n }\n } else {\n cloned = {};\n cache.set(value, cloned);\n const keys = Object.keys(value);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n cloned[key] =\n typeof value[key] !== \"object\"\n ? value[key]\n : deepClone(value[key], cache);\n }\n }\n return cloned;\n }\n return value;\n}\n\nexport default function <T>(value: T): T {\n if (typeof value !== \"object\") return value;\n return deepClone(value, new Map());\n}\n"],"mappings":";;;;;;AACA,SAASA,SAASA,CAACC,KAAU,EAAEC,KAAoB,EAAO;EACxD,IAAID,KAAK,KAAK,IAAI,EAAE;IAClB,IAAIC,KAAK,CAACC,GAAG,CAACF,KAAK,CAAC,EAAE,OAAOC,KAAK,CAACE,GAAG,CAACH,KAAK,CAAC;IAC7C,IAAII,MAAW;IACf,IAAIC,KAAK,CAACC,OAAO,CAACN,KAAK,CAAC,EAAE;MACxBI,MAAM,GAAG,IAAIC,KAAK,CAACL,KAAK,CAACO,MAAM,CAAC;MAChCN,KAAK,CAACO,GAAG,CAACR,KAAK,EAAEI,MAAM,CAAC;MACxB,KAAK,IAAIK,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGT,KAAK,CAACO,MAAM,EAAEE,CAAC,EAAE,EAAE;QACrCL,MAAM,CAACK,CAAC,CAAC,GACP,OAAOT,KAAK,CAACS,CAAC,CAAC,KAAK,QAAQ,GAAGT,KAAK,CAACS,CAAC,CAAC,GAAGV,SAAS,CAACC,KAAK,CAACS,CAAC,CAAC,EAAER,KAAK,CAAC;MACxE;IACF,CAAC,MAAM;MACLG,MAAM,GAAG,CAAC,CAAC;MACXH,KAAK,CAACO,GAAG,CAACR,KAAK,EAAEI,MAAM,CAAC;MACxB,MAAMM,IAAI,GAAGC,MAAM,CAACD,IAAI,CAACV,KAAK,CAAC;MAC/B,KAAK,IAAIS,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGC,IAAI,CAACH,MAAM,EAAEE,CAAC,EAAE,EAAE;QACpC,MAAMG,GAAG,GAAGF,IAAI,CAACD,CAAC,CAAC;QACnBL,MAAM,CAACQ,GAAG,CAAC,GACT,OAAOZ,KAAK,CAACY,GAAG,CAAC,KAAK,QAAQ,GAC1BZ,KAAK,CAACY,GAAG,CAAC,GACVb,SAAS,CAACC,KAAK,CAACY,GAAG,CAAC,EAAEX,KAAK,CAAC;MACpC;IACF;IACA,OAAOG,MAAM;EACf;EACA,OAAOJ,KAAK;AACd;AAEe,SAAAa,SAAab,KAAQ,EAAK;EACvC,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAC3C,OAAOD,SAAS,CAACC,KAAK,EAAE,IAAIc,GAAG,CAAC,CAAC,CAAC;AACpC;AAAC","ignoreList":[]}
|
||||
{"version":3,"names":["circleSet","Set","depth","deepClone","value","cache","allowCircle","has","get","clear","Error","add","cloned","Array","isArray","length","set","i","keys","Object","key","delete","_default","Map","_","structuredClone"],"sources":["../../../src/transformation/util/clone-deep.ts"],"sourcesContent":["const circleSet = new Set();\nlet depth = 0;\n// https://github.com/babel/babel/pull/14583#discussion_r882828856\nfunction deepClone(\n value: any,\n cache: Map<any, any>,\n allowCircle: boolean,\n): any {\n if (value !== null) {\n if (allowCircle) {\n if (cache.has(value)) return cache.get(value);\n } else if (++depth > 250) {\n if (circleSet.has(value)) {\n depth = 0;\n circleSet.clear();\n throw new Error(\"Babel-deepClone: Cycles are not allowed in AST\");\n }\n circleSet.add(value);\n }\n let cloned: any;\n if (Array.isArray(value)) {\n cloned = new Array(value.length);\n if (allowCircle) cache.set(value, cloned);\n for (let i = 0; i < value.length; i++) {\n cloned[i] =\n typeof value[i] !== \"object\"\n ? value[i]\n : deepClone(value[i], cache, allowCircle);\n }\n } else {\n cloned = {};\n if (allowCircle) cache.set(value, cloned);\n const keys = Object.keys(value);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n cloned[key] =\n typeof value[key] !== \"object\"\n ? value[key]\n : deepClone(\n value[key],\n cache,\n allowCircle ||\n key === \"leadingComments\" ||\n key === \"innerComments\" ||\n key === \"trailingComments\" ||\n key === \"extra\",\n );\n }\n }\n if (!allowCircle) {\n if (depth-- > 250) circleSet.delete(value);\n }\n return cloned;\n }\n return value;\n}\n\nexport default function <T>(value: T): T {\n if (typeof value !== \"object\") return value;\n\n if (process.env.BABEL_8_BREAKING) {\n if (!process.env.IS_PUBLISH && depth > 0) {\n throw new Error(\"depth > 0\");\n }\n return deepClone(value, new Map(), false);\n } else {\n try {\n return deepClone(value, new Map(), true);\n } catch (_) {\n return structuredClone(value);\n }\n }\n}\n"],"mappings":";;;;;;AAAA,MAAMA,SAAS,GAAG,IAAIC,GAAG,CAAC,CAAC;AAC3B,IAAIC,KAAK,GAAG,CAAC;AAEb,SAASC,SAASA,CAChBC,KAAU,EACVC,KAAoB,EACpBC,WAAoB,EACf;EACL,IAAIF,KAAK,KAAK,IAAI,EAAE;IAClB,IAAIE,WAAW,EAAE;MACf,IAAID,KAAK,CAACE,GAAG,CAACH,KAAK,CAAC,EAAE,OAAOC,KAAK,CAACG,GAAG,CAACJ,KAAK,CAAC;IAC/C,CAAC,MAAM,IAAI,EAAEF,KAAK,GAAG,GAAG,EAAE;MACxB,IAAIF,SAAS,CAACO,GAAG,CAACH,KAAK,CAAC,EAAE;QACxBF,KAAK,GAAG,CAAC;QACTF,SAAS,CAACS,KAAK,CAAC,CAAC;QACjB,MAAM,IAAIC,KAAK,CAAC,gDAAgD,CAAC;MACnE;MACAV,SAAS,CAACW,GAAG,CAACP,KAAK,CAAC;IACtB;IACA,IAAIQ,MAAW;IACf,IAAIC,KAAK,CAACC,OAAO,CAACV,KAAK,CAAC,EAAE;MACxBQ,MAAM,GAAG,IAAIC,KAAK,CAACT,KAAK,CAACW,MAAM,CAAC;MAChC,IAAIT,WAAW,EAAED,KAAK,CAACW,GAAG,CAACZ,KAAK,EAAEQ,MAAM,CAAC;MACzC,KAAK,IAAIK,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGb,KAAK,CAACW,MAAM,EAAEE,CAAC,EAAE,EAAE;QACrCL,MAAM,CAACK,CAAC,CAAC,GACP,OAAOb,KAAK,CAACa,CAAC,CAAC,KAAK,QAAQ,GACxBb,KAAK,CAACa,CAAC,CAAC,GACRd,SAAS,CAACC,KAAK,CAACa,CAAC,CAAC,EAAEZ,KAAK,EAAEC,WAAW,CAAC;MAC/C;IACF,CAAC,MAAM;MACLM,MAAM,GAAG,CAAC,CAAC;MACX,IAAIN,WAAW,EAAED,KAAK,CAACW,GAAG,CAACZ,KAAK,EAAEQ,MAAM,CAAC;MACzC,MAAMM,IAAI,GAAGC,MAAM,CAACD,IAAI,CAACd,KAAK,CAAC;MAC/B,KAAK,IAAIa,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGC,IAAI,CAACH,MAAM,EAAEE,CAAC,EAAE,EAAE;QACpC,MAAMG,GAAG,GAAGF,IAAI,CAACD,CAAC,CAAC;QACnBL,MAAM,CAACQ,GAAG,CAAC,GACT,OAAOhB,KAAK,CAACgB,GAAG,CAAC,KAAK,QAAQ,GAC1BhB,KAAK,CAACgB,GAAG,CAAC,GACVjB,SAAS,CACPC,KAAK,CAACgB,GAAG,CAAC,EACVf,KAAK,EACLC,WAAW,IACTc,GAAG,KAAK,iBAAiB,IACzBA,GAAG,KAAK,eAAe,IACvBA,GAAG,KAAK,kBAAkB,IAC1BA,GAAG,KAAK,OACZ,CAAC;MACT;IACF;IACA,IAAI,CAACd,WAAW,EAAE;MAChB,IAAIJ,KAAK,EAAE,GAAG,GAAG,EAAEF,SAAS,CAACqB,MAAM,CAACjB,KAAK,CAAC;IAC5C;IACA,OAAOQ,MAAM;EACf;EACA,OAAOR,KAAK;AACd;AAEe,SAAAkB,SAAalB,KAAQ,EAAK;EACvC,IAAI,OAAOA,KAAK,KAAK,QAAQ,EAAE,OAAOA,KAAK;EAOpC;IACL,IAAI;MACF,OAAOD,SAAS,CAACC,KAAK,EAAE,IAAImB,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;IAC1C,CAAC,CAAC,OAAOC,CAAC,EAAE;MACV,OAAOC,eAAe,CAACrB,KAAK,CAAC;IAC/B;EACF;AACF;AAAC","ignoreList":[]}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@babel/core",
|
||||
"version": "7.26.9",
|
||||
"version": "7.26.10",
|
||||
"description": "Babel compiler core.",
|
||||
"main": "./lib/index.js",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
|
@ -48,14 +48,14 @@
|
|||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/generator": "^7.26.9",
|
||||
"@babel/generator": "^7.26.10",
|
||||
"@babel/helper-compilation-targets": "^7.26.5",
|
||||
"@babel/helper-module-transforms": "^7.26.0",
|
||||
"@babel/helpers": "^7.26.9",
|
||||
"@babel/parser": "^7.26.9",
|
||||
"@babel/helpers": "^7.26.10",
|
||||
"@babel/parser": "^7.26.10",
|
||||
"@babel/template": "^7.26.9",
|
||||
"@babel/traverse": "^7.26.9",
|
||||
"@babel/types": "^7.26.9",
|
||||
"@babel/traverse": "^7.26.10",
|
||||
"@babel/types": "^7.26.10",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
|
|
|
@ -67,6 +67,7 @@ function ExportNamespaceSpecifier(node) {
|
|||
}
|
||||
let warningShown = false;
|
||||
function _printAttributes(node, hasPreviousBrace) {
|
||||
var _node$extra;
|
||||
const {
|
||||
importAttributesKeyword
|
||||
} = this.format;
|
||||
|
@ -74,7 +75,7 @@ function _printAttributes(node, hasPreviousBrace) {
|
|||
attributes,
|
||||
assertions
|
||||
} = node;
|
||||
if (attributes && !importAttributesKeyword && !warningShown) {
|
||||
if (attributes && !importAttributesKeyword && node.extra && (node.extra.deprecatedAssertSyntax || node.extra.deprecatedWithLegacySyntax) && !warningShown) {
|
||||
warningShown = true;
|
||||
console.warn(`\
|
||||
You are using import attributes, without specifying the desired output syntax.
|
||||
|
@ -87,7 +88,7 @@ Please specify the "importAttributesKeyword" generator option, whose value can b
|
|||
const useAssertKeyword = importAttributesKeyword === "assert" || !importAttributesKeyword && assertions;
|
||||
this.word(useAssertKeyword ? "assert" : "with");
|
||||
this.space();
|
||||
if (!useAssertKeyword && importAttributesKeyword !== "with") {
|
||||
if (!useAssertKeyword && (importAttributesKeyword === "with-legacy" || !importAttributesKeyword && (_node$extra = node.extra) != null && _node$extra.deprecatedWithLegacySyntax)) {
|
||||
this.printList(attributes || assertions);
|
||||
return;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -688,7 +688,7 @@ function tsPrintClassMemberModifiers(node) {
|
|||
this.word("static");
|
||||
this.space();
|
||||
}
|
||||
printModifiersList(this, node, [!isPrivateField && node.override && "override", !isPrivateField && node.abstract && "abstract", (isPublicField || isPrivateField) && node.readonly && "readonly"]);
|
||||
printModifiersList(this, node, [!isPrivateField && node.abstract && "abstract", !isPrivateField && node.override && "override", (isPublicField || isPrivateField) && node.readonly && "readonly"]);
|
||||
}
|
||||
function printBraced(printer, node, cb) {
|
||||
printer.token("{");
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,8 @@
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = generate;
|
||||
exports.default = void 0;
|
||||
exports.generate = generate;
|
||||
var _sourceMap = require("./source-map.js");
|
||||
var _printer = require("./printer.js");
|
||||
function normalizeOptions(code, opts, ast) {
|
||||
|
@ -106,5 +107,6 @@ function generate(ast, opts = {}, code) {
|
|||
const printer = new _printer.default(format, map, ast.tokens, typeof code === "string" ? code : null);
|
||||
return printer.generate(ast);
|
||||
}
|
||||
var _default = exports.default = generate;
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@babel/generator",
|
||||
"version": "7.26.9",
|
||||
"version": "7.27.0",
|
||||
"description": "Turns an AST into code.",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"license": "MIT",
|
||||
|
@ -19,16 +19,16 @@
|
|||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.26.9",
|
||||
"@babel/types": "^7.26.9",
|
||||
"@babel/parser": "^7.27.0",
|
||||
"@babel/types": "^7.27.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jsesc": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.9",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/helper-fixtures": "^7.26.0",
|
||||
"@babel/plugin-transform-typescript": "^7.26.8",
|
||||
"@babel/plugin-transform-typescript": "^7.27.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||
"@types/jsesc": "^2.5.0",
|
||||
"charcodes": "^0.2.0"
|
||||
|
|
|
@ -186,6 +186,7 @@ function getTargets(inputTargets = {}, options = {}) {
|
|||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
if (esmodules && (esmodules !== "intersect" || !((_browsers = browsers) != null && _browsers.length))) {
|
||||
browsers = Object.keys(ESM_SUPPORT).map(browser => `${browser} >= ${ESM_SUPPORT[browser]}`).join(", ");
|
||||
esmodules = false;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@babel/helper-compilation-targets",
|
||||
"version": "7.26.5",
|
||||
"version": "7.27.0",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"license": "MIT",
|
||||
"description": "Helper functions on Babel compilation targets",
|
||||
|
@ -25,7 +25,7 @@
|
|||
"babel-plugin"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.26.5",
|
||||
"@babel/compat-data": "^7.26.8",
|
||||
"@babel/helper-validator-option": "^7.25.9",
|
||||
"browserslist": "^4.24.0",
|
||||
"lru-cache": "^5.1.1",
|
||||
|
|
|
@ -369,15 +369,17 @@ function createPrivateBrandCheckClosure(brandName) {
|
|||
return _core.types.arrowFunctionExpression([_core.types.identifier("_")], _core.types.binaryExpression("in", _core.types.cloneNode(brandName), _core.types.identifier("_")));
|
||||
}
|
||||
function usesPrivateField(expression) {
|
||||
try {
|
||||
_core.types.traverseFast(expression, node => {
|
||||
if (_core.types.isPrivateName(node)) {
|
||||
throw null;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
} catch (_unused) {
|
||||
return true;
|
||||
{
|
||||
try {
|
||||
_core.types.traverseFast(expression, node => {
|
||||
if (_core.types.isPrivateName(node)) {
|
||||
throw null;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
} catch (_unused) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
function convertToComputedKey(path) {
|
||||
|
@ -430,7 +432,7 @@ function checkPrivateMethodUpdateError(path, decoratedPrivateMethods) {
|
|||
});
|
||||
}
|
||||
function transformClass(path, state, constantSuper, ignoreFunctionLength, className, propertyVisitor, version) {
|
||||
var _path$node$id, _classDecorationsId;
|
||||
var _path$node$id;
|
||||
const body = path.get("body.body");
|
||||
const classDecorators = path.node.decorators;
|
||||
let hasElementDecorators = false;
|
||||
|
@ -449,19 +451,21 @@ function transformClass(path, state, constantSuper, ignoreFunctionLength, classN
|
|||
const classIdName = (_path$node$id = path.node.id) == null ? void 0 : _path$node$id.name;
|
||||
const setClassName = typeof className === "object" ? className : undefined;
|
||||
const usesFunctionContextOrYieldAwait = decorator => {
|
||||
try {
|
||||
_core.types.traverseFast(decorator, node => {
|
||||
if (_core.types.isThisExpression(node) || _core.types.isSuper(node) || _core.types.isYieldExpression(node) || _core.types.isAwaitExpression(node) || _core.types.isIdentifier(node, {
|
||||
name: "arguments"
|
||||
}) || classIdName && _core.types.isIdentifier(node, {
|
||||
name: classIdName
|
||||
}) || _core.types.isMetaProperty(node) && node.meta.name !== "import") {
|
||||
throw null;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
} catch (_unused2) {
|
||||
return true;
|
||||
{
|
||||
try {
|
||||
_core.types.traverseFast(decorator, node => {
|
||||
if (_core.types.isThisExpression(node) || _core.types.isSuper(node) || _core.types.isYieldExpression(node) || _core.types.isAwaitExpression(node) || _core.types.isIdentifier(node, {
|
||||
name: "arguments"
|
||||
}) || classIdName && _core.types.isIdentifier(node, {
|
||||
name: classIdName
|
||||
}) || _core.types.isMetaProperty(node) && node.meta.name !== "import") {
|
||||
throw null;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
} catch (_unused2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
const instancePrivateNames = [];
|
||||
|
@ -488,11 +492,9 @@ function transformClass(path, state, constantSuper, ignoreFunctionLength, classN
|
|||
}
|
||||
default:
|
||||
if (elementNode.static) {
|
||||
var _staticInitLocal;
|
||||
(_staticInitLocal = staticInitLocal) != null ? _staticInitLocal : staticInitLocal = generateLetUidIdentifier(scopeParent, "initStatic");
|
||||
staticInitLocal != null ? staticInitLocal : staticInitLocal = generateLetUidIdentifier(scopeParent, "initStatic");
|
||||
} else {
|
||||
var _protoInitLocal;
|
||||
(_protoInitLocal = protoInitLocal) != null ? _protoInitLocal : protoInitLocal = generateLetUidIdentifier(scopeParent, "initProto");
|
||||
protoInitLocal != null ? protoInitLocal : protoInitLocal = generateLetUidIdentifier(scopeParent, "initProto");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -554,8 +556,7 @@ function transformClass(path, state, constantSuper, ignoreFunctionLength, classN
|
|||
} else if (scopeParent.isStatic(expression.object)) {
|
||||
object = _core.types.cloneNode(expression.object);
|
||||
} else {
|
||||
var _decoratorReceiverId;
|
||||
(_decoratorReceiverId = decoratorReceiverId) != null ? _decoratorReceiverId : decoratorReceiverId = generateLetUidIdentifier(scopeParent, "obj");
|
||||
decoratorReceiverId != null ? decoratorReceiverId : decoratorReceiverId = generateLetUidIdentifier(scopeParent, "obj");
|
||||
object = _core.types.assignmentExpression("=", _core.types.cloneNode(decoratorReceiverId), expression.object);
|
||||
expression.object = _core.types.cloneNode(decoratorReceiverId);
|
||||
}
|
||||
|
@ -993,7 +994,7 @@ function transformClass(path, state, constantSuper, ignoreFunctionLength, classN
|
|||
}
|
||||
computedKeyAssignments = [];
|
||||
}
|
||||
applyDecsBody.push(_core.types.expressionStatement(createLocalsAssignment(elementLocals, classLocals, elementDecorations, (_classDecorationsId = classDecorationsId) != null ? _classDecorationsId : _core.types.arrayExpression(classDecorations), _core.types.numericLiteral(classDecorationsFlag), needsInstancePrivateBrandCheck ? lastInstancePrivateName : null, setClassName, _core.types.cloneNode(superClass), state, version)));
|
||||
applyDecsBody.push(_core.types.expressionStatement(createLocalsAssignment(elementLocals, classLocals, elementDecorations, classDecorationsId != null ? classDecorationsId : _core.types.arrayExpression(classDecorations), _core.types.numericLiteral(classDecorationsFlag), needsInstancePrivateBrandCheck ? lastInstancePrivateName : null, setClassName, _core.types.cloneNode(superClass), state, version)));
|
||||
if (staticInitLocal) {
|
||||
applyDecsBody.push(_core.types.expressionStatement(_core.types.callExpression(_core.types.cloneNode(staticInitLocal), [_core.types.thisExpression()])));
|
||||
}
|
||||
|
@ -1265,12 +1266,12 @@ function _default({
|
|||
const ignoreFunctionLength = (_assumption2 = assumption("ignoreFunctionLength")) != null ? _assumption2 : loose;
|
||||
const namedEvaluationVisitor = NamedEvaluationVisitoryFactory(isDecoratedAnonymousClassExpression, visitClass);
|
||||
function visitClass(path, state, className) {
|
||||
var _className, _node$id;
|
||||
var _node$id;
|
||||
if (VISITED.has(path)) return;
|
||||
const {
|
||||
node
|
||||
} = path;
|
||||
(_className = className) != null ? _className : className = (_node$id = node.id) == null ? void 0 : _node$id.name;
|
||||
className != null ? className : className = (_node$id = node.id) == null ? void 0 : _node$id.name;
|
||||
const newPath = transformClass(path, state, constantSuper, ignoreFunctionLength, className, namedEvaluationVisitor, version);
|
||||
if (newPath) {
|
||||
VISITED.add(newPath);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -38,9 +38,8 @@ function buildPrivateNamesMap(className, privateFieldsAsSymbolsOrProperties, pro
|
|||
let initAdded = false;
|
||||
let id;
|
||||
if (!privateFieldsAsSymbolsOrProperties && newHelpers(file) && isMethod && !isStatic) {
|
||||
var _classBrandId;
|
||||
initAdded = !!classBrandId;
|
||||
(_classBrandId = classBrandId) != null ? _classBrandId : classBrandId = prop.scope.generateUidIdentifier(`${className}_brand`);
|
||||
classBrandId != null ? classBrandId : classBrandId = prop.scope.generateUidIdentifier(`${className}_brand`);
|
||||
id = classBrandId;
|
||||
} else {
|
||||
id = prop.scope.generateUidIdentifier(name);
|
||||
|
@ -897,7 +896,6 @@ function inheritLoc(node, original) {
|
|||
return node;
|
||||
}
|
||||
function buildFieldsInitNodes(ref, superRef, props, privateNamesMap, file, setPublicClassFields, privateFieldsAsSymbolsOrProperties, noUninitializedPrivateFieldAccess, constantSuper, innerBindingRef) {
|
||||
var _ref, _ref2;
|
||||
let classRefFlags = 0;
|
||||
let injectSuperRef;
|
||||
const staticNodes = [];
|
||||
|
@ -906,12 +904,11 @@ function buildFieldsInitNodes(ref, superRef, props, privateNamesMap, file, setPu
|
|||
const pureStaticNodes = [];
|
||||
let classBindingNode = null;
|
||||
const getSuperRef = _core.types.isIdentifier(superRef) ? () => superRef : () => {
|
||||
var _injectSuperRef;
|
||||
(_injectSuperRef = injectSuperRef) != null ? _injectSuperRef : injectSuperRef = props[0].scope.generateUidIdentifierBasedOnNode(superRef);
|
||||
injectSuperRef != null ? injectSuperRef : injectSuperRef = props[0].scope.generateUidIdentifierBasedOnNode(superRef);
|
||||
return injectSuperRef;
|
||||
};
|
||||
const classRefForInnerBinding = (_ref = ref) != null ? _ref : props[0].scope.generateUidIdentifier((innerBindingRef == null ? void 0 : innerBindingRef.name) || "Class");
|
||||
(_ref2 = ref) != null ? _ref2 : ref = _core.types.cloneNode(innerBindingRef);
|
||||
const classRefForInnerBinding = ref != null ? ref : props[0].scope.generateUidIdentifier((innerBindingRef == null ? void 0 : innerBindingRef.name) || "Class");
|
||||
ref != null ? ref : ref = _core.types.cloneNode(innerBindingRef);
|
||||
for (const prop of props) {
|
||||
if (prop.isClassProperty()) {
|
||||
ts.assertFieldTransformed(prop);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -57,8 +57,7 @@ function createClassFeaturePlugin({
|
|||
}
|
||||
}
|
||||
{
|
||||
var _api;
|
||||
(_api = api) != null ? _api : api = {
|
||||
api != null ? api : api = {
|
||||
assumption: () => void 0
|
||||
};
|
||||
}
|
||||
|
@ -95,20 +94,19 @@ function createClassFeaturePlugin({
|
|||
(0, _features.enableFeature)(file, feature, loose);
|
||||
{
|
||||
if (typeof file.get(versionKey) === "number") {
|
||||
file.set(versionKey, "7.26.9");
|
||||
file.set(versionKey, "7.27.0");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!file.get(versionKey) || _semver.lt(file.get(versionKey), "7.26.9")) {
|
||||
file.set(versionKey, "7.26.9");
|
||||
if (!file.get(versionKey) || _semver.lt(file.get(versionKey), "7.27.0")) {
|
||||
file.set(versionKey, "7.27.0");
|
||||
}
|
||||
},
|
||||
visitor: {
|
||||
Class(path, {
|
||||
file
|
||||
}) {
|
||||
var _ref;
|
||||
if (file.get(versionKey) !== "7.26.9") return;
|
||||
if (file.get(versionKey) !== "7.27.0") return;
|
||||
if (!(0, _features.shouldTransform)(path, file)) return;
|
||||
const pathIsClassDeclaration = path.isClassDeclaration();
|
||||
if (pathIsClassDeclaration) (0, _typescript.assertFieldTransformed)(path);
|
||||
|
@ -173,7 +171,7 @@ function createClassFeaturePlugin({
|
|||
path.ensureFunctionName(false);
|
||||
ref = path.scope.generateUidIdentifier((innerBinding == null ? void 0 : innerBinding.name) || "Class");
|
||||
}
|
||||
const classRefForDefine = (_ref = ref) != null ? _ref : _core.types.cloneNode(innerBinding);
|
||||
const classRefForDefine = ref != null ? ref : _core.types.cloneNode(innerBinding);
|
||||
const privateNamesMap = (0, _fields.buildPrivateNamesMap)(classRefForDefine.name, privateFieldsAsSymbolsOrProperties != null ? privateFieldsAsSymbolsOrProperties : loose, props, file);
|
||||
const privateNamesNodes = (0, _fields.buildPrivateNamesNodes)(privateNamesMap, privateFieldsAsProperties != null ? privateFieldsAsProperties : loose, privateFieldsAsSymbols != null ? privateFieldsAsSymbols : false, file);
|
||||
(0, _fields.transformPrivateNamesUsage)(classRefForDefine, path, privateNamesMap, {
|
||||
|
@ -229,7 +227,7 @@ function createClassFeaturePlugin({
|
|||
file
|
||||
}) {
|
||||
{
|
||||
if (file.get(versionKey) !== "7.26.9") return;
|
||||
if (file.get(versionKey) !== "7.27.0") return;
|
||||
const decl = path.get("declaration");
|
||||
if (decl.isClassDeclaration() && (0, _decorators.hasDecorators)(decl.node)) {
|
||||
if (decl.node.id) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -43,7 +43,10 @@ function handleClassTDZ(path, state) {
|
|||
}
|
||||
}
|
||||
const classFieldDefinitionEvaluationTDZVisitor = {
|
||||
ReferencedIdentifier: handleClassTDZ
|
||||
ReferencedIdentifier: handleClassTDZ,
|
||||
"TSTypeAnnotation|TypeAnnotation"(path) {
|
||||
path.skip();
|
||||
}
|
||||
};
|
||||
function injectInitialization(path, constructor, nodes, renamer, lastReturnsThis) {
|
||||
if (!nodes.length) return;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@babel/helper-create-class-features-plugin",
|
||||
"version": "7.26.9",
|
||||
"version": "7.27.0",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"license": "MIT",
|
||||
"description": "Compile class public and private fields, private methods and decorators to ES6",
|
||||
|
@ -23,14 +23,14 @@
|
|||
"@babel/helper-optimise-call-expression": "^7.25.9",
|
||||
"@babel/helper-replace-supers": "^7.26.5",
|
||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
|
||||
"@babel/traverse": "^7.26.9",
|
||||
"@babel/traverse": "^7.27.0",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.9",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/helper-plugin-test-runner": "^7.25.9",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@types/charcodes": "^0.2.0",
|
||||
|
|
|
@ -49,17 +49,17 @@ function createRegExpFeaturePlugin({
|
|||
}
|
||||
{
|
||||
if (typeof file.get(versionKey) === "number") {
|
||||
file.set(versionKey, "7.26.3");
|
||||
file.set(versionKey, "7.27.0");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!file.get(versionKey) || _semver.lt(file.get(versionKey), "7.26.3")) {
|
||||
file.set(versionKey, "7.26.3");
|
||||
if (!file.get(versionKey) || _semver.lt(file.get(versionKey), "7.27.0")) {
|
||||
file.set(versionKey, "7.27.0");
|
||||
}
|
||||
},
|
||||
visitor: {
|
||||
RegExpLiteral(path) {
|
||||
var _file$get2, _newFlags;
|
||||
var _file$get2;
|
||||
const {
|
||||
node
|
||||
} = path;
|
||||
|
@ -99,7 +99,7 @@ function createRegExpFeaturePlugin({
|
|||
(0, _helperAnnotateAsPure.default)(call);
|
||||
path.replaceWith(call);
|
||||
}
|
||||
node.flags = (0, _util.transformFlags)(regexpuOptions, (_newFlags = newFlags) != null ? _newFlags : node.flags);
|
||||
node.flags = (0, _util.transformFlags)(regexpuOptions, newFlags != null ? newFlags : node.flags);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13,9 +13,9 @@ function generateRegexpuOptions(pattern, toTransform) {
|
|||
};
|
||||
const featDuplicateNamedGroups = () => {
|
||||
if (!feat("duplicateNamedCaptureGroups")) return false;
|
||||
const regex = /\(\?<([^>]+)>/g;
|
||||
const regex = /\(\?<([^>]+)(>|$)/g;
|
||||
const seen = new Set();
|
||||
for (let match; match = regex.exec(pattern); seen.add(match[1])) {
|
||||
for (let match; (match = regex.exec(pattern)) && match[2]; seen.add(match[1])) {
|
||||
if (seen.has(match[1])) return "transform";
|
||||
}
|
||||
return false;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@babel/helper-create-regexp-features-plugin",
|
||||
"version": "7.26.3",
|
||||
"version": "7.27.0",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"license": "MIT",
|
||||
"description": "Compile ESNext Regular Expressions to ES5",
|
||||
|
@ -26,7 +26,7 @@
|
|||
"@babel/core": "^7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.26.0",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/helper-plugin-test-runner": "^7.25.9"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -14,20 +14,28 @@ function intersection(a, b) {
|
|||
function has$1(object, key) {
|
||||
return Object.prototype.hasOwnProperty.call(object, key);
|
||||
}
|
||||
function getType(target) {
|
||||
return Object.prototype.toString.call(target).slice(8, -1);
|
||||
function resolve$1(path, resolved = new Set()) {
|
||||
if (resolved.has(path)) return;
|
||||
resolved.add(path);
|
||||
if (path.isVariableDeclarator()) {
|
||||
if (path.get("id").isIdentifier()) {
|
||||
return resolve$1(path.get("init"), resolved);
|
||||
}
|
||||
} else if (path.isReferencedIdentifier()) {
|
||||
const binding = path.scope.getBinding(path.node.name);
|
||||
if (!binding) return path;
|
||||
if (!binding.constant) return;
|
||||
return resolve$1(binding.path, resolved);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
function resolveId(path) {
|
||||
if (path.isIdentifier() && !path.scope.hasBinding(path.node.name, /* noGlobals */true)) {
|
||||
return path.node.name;
|
||||
}
|
||||
if (path.isPure()) {
|
||||
const {
|
||||
deopt
|
||||
} = path.evaluate();
|
||||
if (deopt && deopt.isIdentifier()) {
|
||||
return deopt.node.name;
|
||||
}
|
||||
const resolved = resolve$1(path);
|
||||
if (resolved != null && resolved.isIdentifier()) {
|
||||
return resolved.node.name;
|
||||
}
|
||||
}
|
||||
function resolveKey(path, computed = false) {
|
||||
|
@ -75,26 +83,43 @@ function resolveSource(obj) {
|
|||
placement: "static"
|
||||
};
|
||||
}
|
||||
if (obj.isRegExpLiteral()) {
|
||||
return {
|
||||
id: "RegExp",
|
||||
placement: "prototype"
|
||||
};
|
||||
} else if (obj.isFunction()) {
|
||||
return {
|
||||
id: "Function",
|
||||
placement: "prototype"
|
||||
};
|
||||
} else if (obj.isPure()) {
|
||||
const {
|
||||
value
|
||||
} = obj.evaluate();
|
||||
if (value !== undefined) {
|
||||
const path = resolve$1(obj);
|
||||
switch (path == null ? void 0 : path.type) {
|
||||
case "RegExpLiteral":
|
||||
return {
|
||||
id: getType(value),
|
||||
id: "RegExp",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "FunctionExpression":
|
||||
return {
|
||||
id: "Function",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "StringLiteral":
|
||||
return {
|
||||
id: "String",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "NumberLiteral":
|
||||
return {
|
||||
id: "Number",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "BooleanLiteral":
|
||||
return {
|
||||
id: "Boolean",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "ObjectExpression":
|
||||
return {
|
||||
id: "Object",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "ArrayExpression":
|
||||
return {
|
||||
id: "Array",
|
||||
placement: "prototype"
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: null,
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -18,20 +18,28 @@ function intersection(a, b) {
|
|||
function has$1(object, key) {
|
||||
return Object.prototype.hasOwnProperty.call(object, key);
|
||||
}
|
||||
function getType(target) {
|
||||
return Object.prototype.toString.call(target).slice(8, -1);
|
||||
function resolve$1(path, resolved = new Set()) {
|
||||
if (resolved.has(path)) return;
|
||||
resolved.add(path);
|
||||
if (path.isVariableDeclarator()) {
|
||||
if (path.get("id").isIdentifier()) {
|
||||
return resolve$1(path.get("init"), resolved);
|
||||
}
|
||||
} else if (path.isReferencedIdentifier()) {
|
||||
const binding = path.scope.getBinding(path.node.name);
|
||||
if (!binding) return path;
|
||||
if (!binding.constant) return;
|
||||
return resolve$1(binding.path, resolved);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
function resolveId(path) {
|
||||
if (path.isIdentifier() && !path.scope.hasBinding(path.node.name, /* noGlobals */true)) {
|
||||
return path.node.name;
|
||||
}
|
||||
if (path.isPure()) {
|
||||
const {
|
||||
deopt
|
||||
} = path.evaluate();
|
||||
if (deopt && deopt.isIdentifier()) {
|
||||
return deopt.node.name;
|
||||
}
|
||||
const resolved = resolve$1(path);
|
||||
if (resolved != null && resolved.isIdentifier()) {
|
||||
return resolved.node.name;
|
||||
}
|
||||
}
|
||||
function resolveKey(path, computed = false) {
|
||||
|
@ -79,26 +87,43 @@ function resolveSource(obj) {
|
|||
placement: "static"
|
||||
};
|
||||
}
|
||||
if (obj.isRegExpLiteral()) {
|
||||
return {
|
||||
id: "RegExp",
|
||||
placement: "prototype"
|
||||
};
|
||||
} else if (obj.isFunction()) {
|
||||
return {
|
||||
id: "Function",
|
||||
placement: "prototype"
|
||||
};
|
||||
} else if (obj.isPure()) {
|
||||
const {
|
||||
value
|
||||
} = obj.evaluate();
|
||||
if (value !== undefined) {
|
||||
const path = resolve$1(obj);
|
||||
switch (path == null ? void 0 : path.type) {
|
||||
case "RegExpLiteral":
|
||||
return {
|
||||
id: getType(value),
|
||||
id: "RegExp",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "FunctionExpression":
|
||||
return {
|
||||
id: "Function",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "StringLiteral":
|
||||
return {
|
||||
id: "String",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "NumberLiteral":
|
||||
return {
|
||||
id: "Number",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "BooleanLiteral":
|
||||
return {
|
||||
id: "Boolean",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "ObjectExpression":
|
||||
return {
|
||||
id: "Object",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "ArrayExpression":
|
||||
return {
|
||||
id: "Array",
|
||||
placement: "prototype"
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: null,
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -23,20 +23,28 @@ function intersection(a, b) {
|
|||
function has(object, key) {
|
||||
return Object.prototype.hasOwnProperty.call(object, key);
|
||||
}
|
||||
function getType(target) {
|
||||
return Object.prototype.toString.call(target).slice(8, -1);
|
||||
function resolve(path, resolved = new Set()) {
|
||||
if (resolved.has(path)) return;
|
||||
resolved.add(path);
|
||||
if (path.isVariableDeclarator()) {
|
||||
if (path.get("id").isIdentifier()) {
|
||||
return resolve(path.get("init"), resolved);
|
||||
}
|
||||
} else if (path.isReferencedIdentifier()) {
|
||||
const binding = path.scope.getBinding(path.node.name);
|
||||
if (!binding) return path;
|
||||
if (!binding.constant) return;
|
||||
return resolve(binding.path, resolved);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
function resolveId(path) {
|
||||
if (path.isIdentifier() && !path.scope.hasBinding(path.node.name, /* noGlobals */true)) {
|
||||
return path.node.name;
|
||||
}
|
||||
if (path.isPure()) {
|
||||
const {
|
||||
deopt
|
||||
} = path.evaluate();
|
||||
if (deopt && deopt.isIdentifier()) {
|
||||
return deopt.node.name;
|
||||
}
|
||||
const resolved = resolve(path);
|
||||
if (resolved != null && resolved.isIdentifier()) {
|
||||
return resolved.node.name;
|
||||
}
|
||||
}
|
||||
function resolveKey(path, computed = false) {
|
||||
|
@ -84,26 +92,43 @@ function resolveSource(obj) {
|
|||
placement: "static"
|
||||
};
|
||||
}
|
||||
if (obj.isRegExpLiteral()) {
|
||||
return {
|
||||
id: "RegExp",
|
||||
placement: "prototype"
|
||||
};
|
||||
} else if (obj.isFunction()) {
|
||||
return {
|
||||
id: "Function",
|
||||
placement: "prototype"
|
||||
};
|
||||
} else if (obj.isPure()) {
|
||||
const {
|
||||
value
|
||||
} = obj.evaluate();
|
||||
if (value !== undefined) {
|
||||
const path = resolve(obj);
|
||||
switch (path == null ? void 0 : path.type) {
|
||||
case "RegExpLiteral":
|
||||
return {
|
||||
id: getType(value),
|
||||
id: "RegExp",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "FunctionExpression":
|
||||
return {
|
||||
id: "Function",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "StringLiteral":
|
||||
return {
|
||||
id: "String",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "NumberLiteral":
|
||||
return {
|
||||
id: "Number",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "BooleanLiteral":
|
||||
return {
|
||||
id: "Boolean",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "ObjectExpression":
|
||||
return {
|
||||
id: "Object",
|
||||
placement: "prototype"
|
||||
};
|
||||
case "ArrayExpression":
|
||||
return {
|
||||
id: "Array",
|
||||
placement: "prototype"
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
id: null,
|
||||
|
|
|
@ -20,15 +20,18 @@ indent_size = 1
|
|||
[package.json]
|
||||
indent_style = tab
|
||||
|
||||
[lib/core.json]
|
||||
indent_style = tab
|
||||
|
||||
[CHANGELOG.md]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{*.json,Makefile}]
|
||||
max_line_length = unset
|
||||
max_line_length = off
|
||||
|
||||
[test/{dotdot,resolver,module_dir,multirepo,node_path,pathfilter,precedence}/**/*]
|
||||
indent_style = unset
|
||||
indent_size = unset
|
||||
max_line_length = unset
|
||||
insert_final_newline = unset
|
||||
indent_style = off
|
||||
indent_size = off
|
||||
max_line_length = off
|
||||
insert_final_newline = off
|
|
@ -15,7 +15,7 @@
|
|||
"global-require": 1,
|
||||
"id-length": [2, { "min": 1, "max": 40 }],
|
||||
"max-lines": [2, 350],
|
||||
"max-lines-per-function": 1,
|
||||
"max-lines-per-function": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"max-params": 0,
|
||||
"max-statements-per-line": [2, { "max": 2 }],
|
|
@ -1,4 +1,6 @@
|
|||
var async = require('./lib/async');
|
||||
async.core = require('./lib/core');
|
||||
async.isCore = require('./lib/is-core');
|
||||
async.sync = require('./lib/sync');
|
||||
|
||||
module.exports = async;
|
|
@ -44,7 +44,7 @@ var defaultRealpath = function realpath(x, cb) {
|
|||
};
|
||||
|
||||
var maybeRealpath = function maybeRealpath(realpath, x, opts, cb) {
|
||||
if (!opts || !opts.preserveSymlinks) {
|
||||
if (opts && opts.preserveSymlinks === false) {
|
||||
realpath(x, cb);
|
||||
} else {
|
||||
cb(null, x);
|
||||
|
@ -59,7 +59,7 @@ var defaultReadPackage = function defaultReadPackage(readFile, pkgfile, cb) {
|
|||
var pkg = JSON.parse(body);
|
||||
cb(null, pkg);
|
||||
} catch (jsonErr) {
|
||||
cb(jsonErr);
|
||||
cb(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -118,26 +118,12 @@ module.exports = function resolve(x, options, callback) {
|
|||
opts,
|
||||
function (err, realStart) {
|
||||
if (err) cb(err);
|
||||
else validateBasedir(realStart);
|
||||
else init(realStart);
|
||||
}
|
||||
);
|
||||
|
||||
function validateBasedir(basedir) {
|
||||
if (opts.basedir) {
|
||||
var dirError = new TypeError('Provided basedir "' + basedir + '" is not a directory' + (opts.preserveSymlinks ? '' : ', or a symlink to a directory'));
|
||||
dirError.code = 'INVALID_BASEDIR';
|
||||
isDirectory(basedir, function (err, result) {
|
||||
if (err) return cb(err);
|
||||
if (!result) { return cb(dirError); }
|
||||
validBasedir(basedir);
|
||||
});
|
||||
} else {
|
||||
validBasedir(basedir);
|
||||
}
|
||||
}
|
||||
|
||||
var res;
|
||||
function validBasedir(basedir) {
|
||||
function init(basedir) {
|
||||
if ((/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/).test(x)) {
|
||||
res = path.resolve(basedir, x);
|
||||
if (x === '.' || x === '..' || x.slice(-1) === '/') res += '/';
|
||||
|
@ -242,12 +228,12 @@ module.exports = function resolve(x, options, callback) {
|
|||
if (!ex) return loadpkg(path.dirname(dir), cb);
|
||||
|
||||
readPackage(readFile, pkgfile, function (err, pkgParam) {
|
||||
if (err && !(err instanceof SyntaxError)) cb(err);
|
||||
if (err) cb(err);
|
||||
|
||||
var pkg = pkgParam;
|
||||
|
||||
if (pkg && opts.packageFilter) {
|
||||
pkg = opts.packageFilter(pkg, pkgfile, dir);
|
||||
pkg = opts.packageFilter(pkg, pkgfile);
|
||||
}
|
||||
cb(null, pkg, dir);
|
||||
});
|
||||
|
@ -264,7 +250,7 @@ module.exports = function resolve(x, options, callback) {
|
|||
}
|
||||
|
||||
maybeRealpath(realpath, x, opts, function (unwrapErr, pkgdir) {
|
||||
if (unwrapErr) return loadAsDirectory(path.dirname(x), fpkg, cb);
|
||||
if (unwrapErr) return cb(unwrapErr);
|
||||
var pkgfile = path.join(pkgdir, 'package.json');
|
||||
isFile(pkgfile, function (err, ex) {
|
||||
if (err) return cb(err);
|
||||
|
@ -276,7 +262,7 @@ module.exports = function resolve(x, options, callback) {
|
|||
var pkg = pkgParam;
|
||||
|
||||
if (pkg && opts.packageFilter) {
|
||||
pkg = opts.packageFilter(pkg, pkgfile, pkgdir);
|
||||
pkg = opts.packageFilter(pkg, pkgfile);
|
||||
}
|
||||
|
||||
if (pkg && pkg.main) {
|
||||
|
@ -297,13 +283,7 @@ module.exports = function resolve(x, options, callback) {
|
|||
loadAsDirectory(dir, pkg, function (err, n, pkg) {
|
||||
if (err) return cb(err);
|
||||
if (n) return cb(null, n, pkg);
|
||||
loadAsFile(path.join(x, 'index'), pkg, function (err, m, pkg) {
|
||||
if (err) return cb(err);
|
||||
if (m) return cb(null, m, pkg);
|
||||
var incorrectMainError = new Error("Cannot find module '" + path.resolve(x, pkg.main) + "'. Please verify that the package.json has a valid \"main\" entry");
|
||||
incorrectMainError.code = 'INCORRECT_PACKAGE_MAIN';
|
||||
return cb(incorrectMainError);
|
||||
});
|
||||
loadAsFile(path.join(x, 'index'), pkg, cb);
|
||||
});
|
||||
});
|
||||
return;
|
|
@ -48,14 +48,18 @@ var defaultRealpathSync = function realpathSync(x) {
|
|||
};
|
||||
|
||||
var maybeRealpathSync = function maybeRealpathSync(realpathSync, x, opts) {
|
||||
if (!opts || !opts.preserveSymlinks) {
|
||||
if (opts && opts.preserveSymlinks === false) {
|
||||
return realpathSync(x);
|
||||
}
|
||||
return x;
|
||||
};
|
||||
|
||||
var defaultReadPackageSync = function defaultReadPackageSync(readFileSync, pkgfile) {
|
||||
return JSON.parse(readFileSync(pkgfile));
|
||||
var body = readFileSync(pkgfile);
|
||||
try {
|
||||
var pkg = JSON.parse(body);
|
||||
return pkg;
|
||||
} catch (jsonErr) {}
|
||||
};
|
||||
|
||||
var getPackageCandidates = function getPackageCandidates(x, start, opts) {
|
||||
|
@ -73,8 +77,8 @@ module.exports = function resolveSync(x, options) {
|
|||
var opts = normalizeOptions(x, options);
|
||||
|
||||
var isFile = opts.isFile || defaultIsFile;
|
||||
var isDirectory = opts.isDirectory || defaultIsDir;
|
||||
var readFileSync = opts.readFileSync || fs.readFileSync;
|
||||
var isDirectory = opts.isDirectory || defaultIsDir;
|
||||
var realpathSync = opts.realpathSync || defaultRealpathSync;
|
||||
var readPackageSync = opts.readPackageSync || defaultReadPackageSync;
|
||||
if (opts.readFileSync && opts.readPackageSync) {
|
||||
|
@ -92,12 +96,6 @@ module.exports = function resolveSync(x, options) {
|
|||
// ensure that `basedir` is an absolute path at this point, resolving against the process' current working directory
|
||||
var absoluteStart = maybeRealpathSync(realpathSync, path.resolve(basedir), opts);
|
||||
|
||||
if (opts.basedir && !isDirectory(absoluteStart)) {
|
||||
var dirError = new TypeError('Provided basedir "' + opts.basedir + '" is not a directory' + (opts.preserveSymlinks ? '' : ', or a symlink to a directory'));
|
||||
dirError.code = 'INVALID_BASEDIR';
|
||||
throw dirError;
|
||||
}
|
||||
|
||||
if ((/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/).test(x)) {
|
||||
var res = path.resolve(absoluteStart, x);
|
||||
if (x === '.' || x === '..' || x.slice(-1) === '/') res += '/';
|
||||
|
@ -144,37 +142,32 @@ module.exports = function resolveSync(x, options) {
|
|||
}
|
||||
if ((/[/\\]node_modules[/\\]*$/).test(dir)) return;
|
||||
|
||||
var pkgfile = path.join(isDirectory(dir) ? maybeRealpathSync(realpathSync, dir, opts) : dir, 'package.json');
|
||||
var pkgfile = path.join(maybeRealpathSync(realpathSync, dir, opts), 'package.json');
|
||||
|
||||
if (!isFile(pkgfile)) {
|
||||
return loadpkg(path.dirname(dir));
|
||||
}
|
||||
|
||||
var pkg;
|
||||
try {
|
||||
pkg = readPackageSync(readFileSync, pkgfile);
|
||||
} catch (e) {
|
||||
if (!(e instanceof SyntaxError)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
var pkg = readPackageSync(readFileSync, pkgfile);
|
||||
|
||||
if (pkg && opts.packageFilter) {
|
||||
pkg = opts.packageFilter(pkg, pkgfile, dir);
|
||||
// v2 will pass pkgfile
|
||||
pkg = opts.packageFilter(pkg, /*pkgfile,*/ dir); // eslint-disable-line spaced-comment
|
||||
}
|
||||
|
||||
return { pkg: pkg, dir: dir };
|
||||
}
|
||||
|
||||
function loadAsDirectorySync(x) {
|
||||
var pkgfile = path.join(isDirectory(x) ? maybeRealpathSync(realpathSync, x, opts) : x, '/package.json');
|
||||
var pkgfile = path.join(maybeRealpathSync(realpathSync, x, opts), '/package.json');
|
||||
if (isFile(pkgfile)) {
|
||||
try {
|
||||
var pkg = readPackageSync(readFileSync, pkgfile);
|
||||
} catch (e) {}
|
||||
|
||||
if (pkg && opts.packageFilter) {
|
||||
pkg = opts.packageFilter(pkg, pkgfile, x);
|
||||
// v2 will pass pkgfile
|
||||
pkg = opts.packageFilter(pkg, /*pkgfile,*/ x); // eslint-disable-line spaced-comment
|
||||
}
|
||||
|
||||
if (pkg && pkg.main) {
|
||||
|
@ -187,17 +180,11 @@ module.exports = function resolveSync(x, options) {
|
|||
pkg.main = 'index';
|
||||
}
|
||||
try {
|
||||
var mainPath = path.resolve(x, pkg.main);
|
||||
var m = loadAsFileSync(mainPath);
|
||||
var m = loadAsFileSync(path.resolve(x, pkg.main));
|
||||
if (m) return m;
|
||||
var n = loadAsDirectorySync(mainPath);
|
||||
var n = loadAsDirectorySync(path.resolve(x, pkg.main));
|
||||
if (n) return n;
|
||||
var checkIndex = loadAsFileSync(path.resolve(x, 'index'));
|
||||
if (checkIndex) return checkIndex;
|
||||
} catch (e) { }
|
||||
var incorrectMainError = new Error("Cannot find module '" + path.resolve(x, pkg.main) + "'. Please verify that the package.json has a valid \"main\" entry");
|
||||
incorrectMainError.code = 'INCORRECT_PACKAGE_MAIN';
|
||||
throw incorrectMainError;
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "resolve",
|
||||
"description": "resolve like require.resolve() on behalf of files asynchronously and synchronously",
|
||||
"version": "2.0.0-next.5",
|
||||
"version": "1.22.10",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/browserify/resolve.git"
|
||||
|
@ -10,18 +10,6 @@
|
|||
"resolve": "./bin/resolve"
|
||||
},
|
||||
"main": "index.js",
|
||||
"exports": {
|
||||
".": [
|
||||
{
|
||||
"import": "./index.mjs",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index.js"
|
||||
],
|
||||
"./sync": "./lib/sync.js",
|
||||
"./async": "./lib/async.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"keywords": [
|
||||
"resolve",
|
||||
"require",
|
||||
|
@ -29,7 +17,7 @@
|
|||
"module"
|
||||
],
|
||||
"scripts": {
|
||||
"prepack": "npmignore --auto --commentLines=autogenerated",
|
||||
"prepack": "npmignore --auto --commentLines=autogenerated && cp node_modules/is-core-module/core.json ./lib/ ||:",
|
||||
"prepublishOnly": "safe-publish-latest",
|
||||
"prepublish": "not-in-publish || npm run prepublishOnly",
|
||||
"prelint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')",
|
||||
|
@ -38,25 +26,25 @@
|
|||
"tests-only": "tape test/*.js",
|
||||
"pretest": "npm run lint",
|
||||
"test": "npm run --silent tests-only",
|
||||
"posttest": "npm run test:multirepo && aud --production",
|
||||
"posttest": "npm run test:multirepo && npx npm@'>= 10.2' audit --production",
|
||||
"test:multirepo": "cd ./test/resolver/multirepo && npm install && npm test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ljharb/eslint-config": "^21.1.0",
|
||||
"array.prototype.map": "^1.0.6",
|
||||
"aud": "^2.0.3",
|
||||
"@ljharb/eslint-config": "^21.1.1",
|
||||
"array.prototype.map": "^1.0.7",
|
||||
"copy-dir": "^1.3.0",
|
||||
"eclint": "^2.8.1",
|
||||
"eslint": "=8.8.0",
|
||||
"in-publish": "^2.0.1",
|
||||
"mkdirp": "^0.5.5",
|
||||
"mv": "^2.1.1",
|
||||
"npmignore": "^0.3.0",
|
||||
"npmignore": "^0.3.1",
|
||||
"object-keys": "^1.1.1",
|
||||
"rimraf": "^2.7.1",
|
||||
"safe-publish-latest": "^2.0.0",
|
||||
"tap": "^0.4.13",
|
||||
"tape": "^5.7.0",
|
||||
"semver": "^6.3.1",
|
||||
"tap": "0.4.13",
|
||||
"tape": "^5.9.0",
|
||||
"tmp": "^0.0.31"
|
||||
},
|
||||
"license": "MIT",
|
||||
|
@ -69,7 +57,7 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.13.0",
|
||||
"is-core-module": "^2.16.0",
|
||||
"path-parse": "^1.0.7",
|
||||
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||
},
|
||||
|
@ -77,7 +65,11 @@
|
|||
"ignore": [
|
||||
".github/workflows",
|
||||
"appveyor.yml",
|
||||
"test/resolver/malformed_package_json"
|
||||
"test/resolver/malformed_package_json",
|
||||
"test/list-exports"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
}
|
|
@ -80,7 +80,7 @@ options are:
|
|||
* `opts.readPackage(readFile, pkgfile, cb)` - function to asynchronously read and parse a package.json file
|
||||
* readFile - the passed `opts.readFile` or `fs.readFile` if not specified
|
||||
* pkgfile - path to package.json
|
||||
* cb - callback. a SyntaxError error argument will be ignored, all other error arguments will be treated as an error.
|
||||
* cb - callback
|
||||
|
||||
* `opts.packageFilter(pkg, pkgfile, dir)` - transform the parsed package.json contents before looking at the "main" field
|
||||
* pkg - package data
|
||||
|
@ -111,6 +111,8 @@ options are:
|
|||
|
||||
* opts.preserveSymlinks - if true, doesn't resolve `basedir` to real path before resolving.
|
||||
This is the way Node resolves dependencies when executed with the [--preserve-symlinks](https://nodejs.org/api/all.html#cli_preserve_symlinks) flag.
|
||||
**Note:** this property is currently `true` by default but it will be changed to
|
||||
`false` in the next major version because *Node's resolution algorithm does not preserve symlinks by default*.
|
||||
|
||||
default `opts` values:
|
||||
|
||||
|
@ -154,13 +156,13 @@ default `opts` values:
|
|||
var pkg = JSON.parse(body);
|
||||
cb(null, pkg);
|
||||
} catch (jsonErr) {
|
||||
cb(jsonErr);
|
||||
cb(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
moduleDirectory: 'node_modules',
|
||||
preserveSymlinks: false
|
||||
preserveSymlinks: true
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -185,14 +187,13 @@ options are:
|
|||
|
||||
* opts.realpathSync - function to synchronously resolve a potential symlink to its real path
|
||||
|
||||
* `opts.readPackageSync(readFileSync, pkgfile)` - function to synchronously read and parse a package.json file. a thrown SyntaxError will be ignored, all other exceptions will propagate.
|
||||
* `opts.readPackageSync(readFileSync, pkgfile)` - function to synchronously read and parse a package.json file
|
||||
* readFileSync - the passed `opts.readFileSync` or `fs.readFileSync` if not specified
|
||||
* pkgfile - path to package.json
|
||||
|
||||
* `opts.packageFilter(pkg, pkgfile, dir)` - transform the parsed package.json contents before looking at the "main" field
|
||||
* `opts.packageFilter(pkg, dir)` - transform the parsed package.json contents before looking at the "main" field
|
||||
* pkg - package data
|
||||
* pkgfile - path to package.json
|
||||
* dir - directory that contains package.json
|
||||
* dir - directory that contains package.json (Note: the second argument will change to "pkgfile" in v2)
|
||||
|
||||
* `opts.pathFilter(pkg, path, relativePath)` - transform a path within a package
|
||||
* pkg - package data
|
||||
|
@ -218,6 +219,8 @@ options are:
|
|||
|
||||
* opts.preserveSymlinks - if true, doesn't resolve `basedir` to real path before resolving.
|
||||
This is the way Node resolves dependencies when executed with the [--preserve-symlinks](https://nodejs.org/api/all.html#cli_preserve_symlinks) flag.
|
||||
**Note:** this property is currently `true` by default but it will be changed to
|
||||
`false` in the next major version because *Node's resolution algorithm does not preserve symlinks by default*.
|
||||
|
||||
default `opts` values:
|
||||
|
||||
|
@ -258,10 +261,14 @@ default `opts` values:
|
|||
return file;
|
||||
},
|
||||
readPackageSync: function defaultReadPackageSync(readFileSync, pkgfile) {
|
||||
return JSON.parse(readFileSync(pkgfile));
|
||||
var body = readFileSync(pkgfile);
|
||||
try {
|
||||
var pkg = JSON.parse(body);
|
||||
return pkg;
|
||||
} catch (jsonErr) {}
|
||||
},
|
||||
moduleDirectory: 'node_modules',
|
||||
preserveSymlinks: false
|
||||
preserveSymlinks: true
|
||||
}
|
||||
```
|
||||
|
2
node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve/test/dotdot/abc/index.js
generated
vendored
Normal file
2
node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve/test/dotdot/abc/index.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
var x = require('..');
|
||||
console.log(x);
|
1
node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve/test/dotdot/index.js
generated
vendored
Normal file
1
node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve/test/dotdot/index.js
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
module.exports = 'whatever';
|
|
@ -23,7 +23,7 @@ test('non-existent basedir should not throw when preserveSymlinks is false', fun
|
|||
var module = './dotdot/abc';
|
||||
|
||||
resolve(module, opts, function (err, res) {
|
||||
t.equal(err.code, 'INVALID_BASEDIR');
|
||||
t.equal(err.code, 'MODULE_NOT_FOUND');
|
||||
t.equal(res, undefined);
|
||||
});
|
||||
});
|
|
@ -3,14 +3,14 @@ var test = require('tape');
|
|||
var resolve = require('../');
|
||||
|
||||
test('filter', function (t) {
|
||||
t.plan(5);
|
||||
t.plan(4);
|
||||
var dir = path.join(__dirname, 'resolver');
|
||||
var packageFilterArgs;
|
||||
resolve('./baz', {
|
||||
basedir: dir,
|
||||
packageFilter: function (pkg, pkgfile, dir) {
|
||||
packageFilter: function (pkg, pkgfile) {
|
||||
pkg.main = 'doom'; // eslint-disable-line no-param-reassign
|
||||
packageFilterArgs = [pkg, pkgfile, dir];
|
||||
packageFilterArgs = [pkg, pkgfile];
|
||||
return pkg;
|
||||
}
|
||||
}, function (err, res, pkg) {
|
||||
|
@ -29,9 +29,6 @@ test('filter', function (t) {
|
|||
'second packageFilter argument is "pkgfile"'
|
||||
);
|
||||
|
||||
var packageFileDir = packageFilterArgs[2];
|
||||
t.equal(packageFileDir, path.join(dir, 'baz'), 'third packageFilter argument is "dir"');
|
||||
|
||||
t.end();
|
||||
});
|
||||
});
|
33
node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve/test/filter_sync.js
generated
vendored
Normal file
33
node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve/test/filter_sync.js
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
var path = require('path');
|
||||
var test = require('tape');
|
||||
var resolve = require('../');
|
||||
|
||||
test('filter', function (t) {
|
||||
var dir = path.join(__dirname, 'resolver');
|
||||
var packageFilterArgs;
|
||||
var res = resolve.sync('./baz', {
|
||||
basedir: dir,
|
||||
// NOTE: in v2.x, this will be `pkg, pkgfile, dir`, but must remain "broken" here in v1.x for compatibility
|
||||
packageFilter: function (pkg, /*pkgfile,*/ dir) { // eslint-disable-line spaced-comment
|
||||
pkg.main = 'doom'; // eslint-disable-line no-param-reassign
|
||||
packageFilterArgs = 'is 1.x' ? [pkg, dir] : [pkg, pkgfile, dir]; // eslint-disable-line no-constant-condition, no-undef
|
||||
return pkg;
|
||||
}
|
||||
});
|
||||
|
||||
t.equal(res, path.join(dir, 'baz/doom.js'), 'changing the package "main" works');
|
||||
|
||||
var packageData = packageFilterArgs[0];
|
||||
t.equal(packageData.main, 'doom', 'package "main" was altered');
|
||||
|
||||
if (!'is 1.x') { // eslint-disable-line no-constant-condition
|
||||
var packageFile = packageFilterArgs[1];
|
||||
t.equal(packageFile, path.join(dir, 'baz', 'package.json'), 'package.json path is correct');
|
||||
}
|
||||
|
||||
var packageDir = packageFilterArgs['is 1.x' ? 1 : 2]; // eslint-disable-line no-constant-condition
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
t.equal(packageDir, path.join(dir, 'baz'), ('is 1.x' ? 'second' : 'third') + ' packageFilter argument is "dir"');
|
||||
|
||||
t.end();
|
||||
});
|
|
@ -10,7 +10,6 @@ test('mock', function (t) {
|
|||
|
||||
var dirs = {};
|
||||
dirs[path.resolve('/foo/bar')] = true;
|
||||
dirs[path.resolve('/foo/node_modules')] = true;
|
||||
|
||||
function opts(basedir) {
|
||||
return {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue