version 02

This commit is contained in:
Alain Vasquez Ramirez 2025-03-26 19:04:28 -06:00
parent 50469288e1
commit deb60c112f
689 changed files with 17565 additions and 7826 deletions

54
estilo.css Normal file
View File

@ -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;
}

View File

@ -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>

658
node_modules/.package-lock.json generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

7
node_modules/.vite/deps/chunk-ZPUNMYDO.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

286
node_modules/.vite/deps/ra-core.js generated vendored
View File

@ -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

View File

@ -8,7 +8,7 @@ import {
require_get,
require_isIndex,
require_isSymbol
} from "./chunk-FFYJRC36.js";
} from "./chunk-ZPUNMYDO.js";
import {
__commonJS,
__toESM

View File

@ -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

View File

@ -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"
}

View File

@ -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;

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

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

File diff suppressed because it is too large Load Diff

View File

@ -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';

View File

@ -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';

View File

@ -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 */

View File

@ -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;
};

View File

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

View File

@ -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 '';
};

View File

@ -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;
}

View File

@ -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;
};

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

@ -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
];

View File

@ -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': {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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":[]}

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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": {

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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 }],

View File

@ -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;

View File

@ -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;

View File

@ -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) {}
}
}

View File

@ -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"
}
}

View File

@ -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
}
```

View File

@ -0,0 +1,2 @@
var x = require('..');
console.log(x);

View File

@ -0,0 +1 @@
module.exports = 'whatever';

View File

@ -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);
});
});

View File

@ -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();
});
});

View 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();
});

View File

@ -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