Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

View file

@ -0,0 +1,15 @@
ISC License
Copyright (c) 2021, Andrea Giammarchi, @WebReflection
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View file

@ -0,0 +1,30 @@
# structured-clone-es
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![bundle][bundle-src]][bundle-href]
[![JSDocs][jsdocs-src]][jsdocs-href]
[![License][license-src]][license-href]
A redistribution of [`@ungap/structured-clone`](https://github.com/ungap/structured-clone) that ships Node.js compatible ESM.
As `@ungap/structured-clone` use `.js` for both CJS and ESM, making the ESM version not working in Node.js. This package re-bundles it, ships TypeScript definitions, and adds ESM support for Node.js.
```ts
import { parse, stringify, structuredClone } from 'structured-clone-es'
```
The `structuredClone` function is moved from default export to named export. `parse` and `stringify` are also exported from the main entry, the `/json` sub module is removed.
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/structured-clone-es?style=flat&colorA=080f12&colorB=1fa669
[npm-version-href]: https://npmjs.com/package/structured-clone-es
[npm-downloads-src]: https://img.shields.io/npm/dm/structured-clone-es?style=flat&colorA=080f12&colorB=1fa669
[npm-downloads-href]: https://npmjs.com/package/structured-clone-es
[bundle-src]: https://img.shields.io/bundlephobia/minzip/structured-clone-es?style=flat&colorA=080f12&colorB=1fa669&label=minzip
[bundle-href]: https://bundlephobia.com/result?p=structured-clone-es
[license-src]: https://img.shields.io/github/license/antfu/structured-clone-es.svg?style=flat&colorA=080f12&colorB=1fa669
[license-href]: https://github.com/antfu/structured-clone-es/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=1fa669
[jsdocs-href]: https://www.jsdocs.io/package/structured-clone-es

View file

@ -0,0 +1,11 @@
/**
* Represent a structured clone value as string.
*/
declare const stringify: (obj: any) => string;
/**
* Revive a previously stringified structured clone.
*/
declare const parse: (str: string) => unknown;
declare const structuredClone: typeof globalThis.structuredClone;
export { parse, stringify, structuredClone };

View file

@ -0,0 +1,11 @@
/**
* Represent a structured clone value as string.
*/
declare const stringify: (obj: any) => string;
/**
* Revive a previously stringified structured clone.
*/
declare const parse: (str: string) => unknown;
declare const structuredClone: typeof globalThis.structuredClone;
export { parse, stringify, structuredClone };

View file

@ -0,0 +1,285 @@
const VOID = -1;
const PRIMITIVE = 0;
const ARRAY = 1;
const OBJECT = 2;
const DATE = 3;
const REGEXP = 4;
const MAP = 5;
const SET = 6;
const ERROR = 7;
const BIGINT = 8;
// export const SYMBOL = 9;
const env = typeof self === 'object' ? self : globalThis;
const deserializer = ($, _) => {
const as = (out, index) => {
$.set(index, out);
return out;
};
const unpair = index => {
if ($.has(index))
return $.get(index);
const [type, value] = _[index];
switch (type) {
case PRIMITIVE:
case VOID:
return as(value, index);
case ARRAY: {
const arr = as([], index);
for (const index of value)
arr.push(unpair(index));
return arr;
}
case OBJECT: {
const object = as({}, index);
for (const [key, index] of value)
object[unpair(key)] = unpair(index);
return object;
}
case DATE:
return as(new Date(value), index);
case REGEXP: {
const {source, flags} = value;
return as(new RegExp(source, flags), index);
}
case MAP: {
const map = as(new Map, index);
for (const [key, index] of value)
map.set(unpair(key), unpair(index));
return map;
}
case SET: {
const set = as(new Set, index);
for (const index of value)
set.add(unpair(index));
return set;
}
case ERROR: {
const {name, message} = value;
return as(new env[name](message), index);
}
case BIGINT:
return as(BigInt(value), index);
case 'BigInt':
return as(Object(BigInt(value)), index);
}
return as(new env[type](value), index);
};
return unpair;
};
/**
* @typedef {Array<string,any>} Record a type representation
*/
/**
* Returns a deserialized value from a serialized array of Records.
* @param {Record[]} serialized a previously serialized value.
* @returns {any}
*/
const deserialize = serialized => deserializer(new Map, serialized)(0);
const EMPTY = '';
const {toString} = {};
const {keys} = Object;
const typeOf = value => {
const type = typeof value;
if (type !== 'object' || !value)
return [PRIMITIVE, type];
const asString = toString.call(value).slice(8, -1);
switch (asString) {
case 'Array':
return [ARRAY, EMPTY];
case 'Object':
return [OBJECT, EMPTY];
case 'Date':
return [DATE, EMPTY];
case 'RegExp':
return [REGEXP, EMPTY];
case 'Map':
return [MAP, EMPTY];
case 'Set':
return [SET, EMPTY];
}
if (asString.includes('Array'))
return [ARRAY, asString];
if (asString.includes('Error'))
return [ERROR, asString];
return [OBJECT, asString];
};
const shouldSkip = ([TYPE, type]) => (
TYPE === PRIMITIVE &&
(type === 'function' || type === 'symbol')
);
const serializer = (strict, json, $, _) => {
const as = (out, value) => {
const index = _.push(out) - 1;
$.set(value, index);
return index;
};
const pair = value => {
if ($.has(value))
return $.get(value);
let [TYPE, type] = typeOf(value);
switch (TYPE) {
case PRIMITIVE: {
let entry = value;
switch (type) {
case 'bigint':
TYPE = BIGINT;
entry = value.toString();
break;
case 'function':
case 'symbol':
if (strict)
throw new TypeError('unable to serialize ' + type);
entry = null;
break;
case 'undefined':
return as([VOID], value);
}
return as([TYPE, entry], value);
}
case ARRAY: {
if (type)
return as([type, [...value]], value);
const arr = [];
const index = as([TYPE, arr], value);
for (const entry of value)
arr.push(pair(entry));
return index;
}
case OBJECT: {
if (type) {
switch (type) {
case 'BigInt':
return as([type, value.toString()], value);
case 'Boolean':
case 'Number':
case 'String':
return as([type, value.valueOf()], value);
}
}
if (json && ('toJSON' in value))
return pair(value.toJSON());
const entries = [];
const index = as([TYPE, entries], value);
for (const key of keys(value)) {
if (strict || !shouldSkip(typeOf(value[key])))
entries.push([pair(key), pair(value[key])]);
}
return index;
}
case DATE:
return as([TYPE, value.toISOString()], value);
case REGEXP: {
const {source, flags} = value;
return as([TYPE, {source, flags}], value);
}
case MAP: {
const entries = [];
const index = as([TYPE, entries], value);
for (const [key, entry] of value) {
if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry))))
entries.push([pair(key), pair(entry)]);
}
return index;
}
case SET: {
const entries = [];
const index = as([TYPE, entries], value);
for (const entry of value) {
if (strict || !shouldSkip(typeOf(entry)))
entries.push(pair(entry));
}
return index;
}
}
const {message} = value;
return as([TYPE, {name: type, message}], value);
};
return pair;
};
/**
* @typedef {Array<string,any>} Record a type representation
*/
/**
* Returns an array of serialized Records.
* @param {any} value a serializable value.
* @param {{json?: boolean, lossy?: boolean}?} options an object with a `lossy` or `json` property that,
* if `true`, will not throw errors on incompatible types, and behave more
* like JSON stringify would behave. Symbol and Function will be discarded.
* @returns {Record[]}
*/
const serialize = (value, {json, lossy} = {}) => {
const _ = [];
return serializer(!(json || lossy), !!json, new Map, _)(value), _;
};
/**
* @typedef {Array<string,any>} Record a type representation
*/
/**
* Returns an array of serialized Records.
* @param {any} any a serializable value.
* @param {{transfer?: any[], json?: boolean, lossy?: boolean}?} options an object with
* a transfer option (ignored when polyfilled) and/or non standard fields that
* fallback to the polyfill if present.
* @returns {Record[]}
*/
const _structuredClone = typeof structuredClone === "function" ?
/* c8 ignore start */
(any, options) => (
options && ('json' in options || 'lossy' in options) ?
deserialize(serialize(any, options)) : structuredClone(any)
) :
(any, options) => deserialize(serialize(any, options));
/*! (c) Andrea Giammarchi - ISC */
const {parse: $parse, stringify: $stringify} = JSON;
const options = {json: true, lossy: true};
/**
* Revive a previously stringified structured clone.
* @param {string} str previously stringified data as string.
* @returns {any} whatever was previously stringified as clone.
*/
const parse$1 = str => deserialize($parse(str));
/**
* Represent a structured clone value as string.
* @param {any} any some clone-able value to stringify.
* @returns {string} the value stringified.
*/
const stringify$1 = any => $stringify(serialize(any, options));
const stringify = stringify$1;
const parse = parse$1;
const structuredClone$1 = _structuredClone;
export { parse, stringify, structuredClone$1 as structuredClone };

View file

@ -0,0 +1,56 @@
{
"name": "structured-clone-es",
"type": "module",
"version": "1.0.0",
"description": "A re-distribution of @ungap/structured-clone for Node.js comptaible ES Modules",
"author": "Andrea Giammarchi",
"license": "ISC",
"homepage": "https://github.com/antfu/structured-clone-es#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/antfu/structured-clone-es.git"
},
"bugs": "https://github.com/antfu/structured-clone-es/issues",
"keywords": [],
"sideEffects": false,
"exports": {
".": "./dist/index.mjs"
},
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": [
"dist"
],
"devDependencies": {
"@antfu/eslint-config": "^3.14.0",
"@antfu/ni": "^23.2.0",
"@antfu/utils": "^8.1.0",
"@types/node": "^22.10.6",
"@types/ungap__structured-clone": "^1.2.0",
"@ungap/structured-clone": "^1.2.1",
"bumpp": "^9.10.1",
"eslint": "^9.18.0",
"lint-staged": "^15.3.0",
"pnpm": "^9.15.4",
"simple-git-hooks": "^2.11.1",
"tsx": "^4.19.2",
"typescript": "^5.7.3",
"unbuild": "^3.3.1",
"vite": "^6.0.7"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
},
"scripts": {
"build": "unbuild",
"dev": "unbuild --stub",
"lint": "eslint .",
"release": "bumpp && pnpm publish",
"start": "tsx src/index.ts",
"typecheck": "tsc --noEmit"
}
}