mirror of
https://github.com/carbon-design-system/carbon-components-svelte.git
synced 2025-09-14 18:01:06 +00:00
build: use svelte compiler to generate typescript definitions
This commit is contained in:
parent
ba2e77eb47
commit
5c829b5afc
16 changed files with 4948 additions and 948 deletions
|
@ -4,4 +4,5 @@ cache: yarn
|
|||
script:
|
||||
- yarn prepack
|
||||
- yarn build
|
||||
- node scripts/generate-docs.js
|
||||
- cd docs && yarn && yarn test
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
},
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"carbon-icons-svelte": "^10.14.0",
|
||||
"carbon-icons-svelte": "^10.15.0",
|
||||
"flatpickr": "4.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -26,12 +26,15 @@
|
|||
"@storybook/addon-storysource": "^5.3.19",
|
||||
"@storybook/cli": "^5.3.19",
|
||||
"@storybook/svelte": "^5.3.19",
|
||||
"@tsconfig/svelte": "^1.0.8",
|
||||
"babel-loader": "^8.0.6",
|
||||
"comment-parser": "^0.7.5",
|
||||
"rollup": "^2.22.1",
|
||||
"rollup-plugin-svelte": "^5.2.3",
|
||||
"rollup-plugin-terser": "^6.1.0",
|
||||
"svelte": "^3.24.1",
|
||||
"svelte-loader": "^2.13.6"
|
||||
"svelte-loader": "^2.13.6",
|
||||
"typescript": "^3.9.7"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
|
|
132
scripts/generate-docs.js
Normal file
132
scripts/generate-docs.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
const fs = require("fs");
|
||||
const rollup = require("rollup");
|
||||
const pkg = require("../package.json");
|
||||
const svelte = require("rollup-plugin-svelte");
|
||||
const resolve = require("@rollup/plugin-node-resolve").default;
|
||||
const commonjs = require("@rollup/plugin-commonjs");
|
||||
const path = require("path");
|
||||
const { parseComponent } = require("./parse-component");
|
||||
|
||||
async function generateDocs() {
|
||||
let definitions = `
|
||||
// Type definitions for carbon-components-svelte ${pkg.version}
|
||||
// Project: https://github.com/IBM/carbon-components-svelte
|
||||
|
||||
class CarbonSvelteBase {
|
||||
$$prop_def: {};
|
||||
|
||||
$$slot_def: {};
|
||||
|
||||
// stub all 'on:{event}' directives
|
||||
$on(eventname: string, handler: (e: Event) => any): () => void;
|
||||
}\n\n`;
|
||||
|
||||
const shared_types = new Set();
|
||||
const groups = new Map();
|
||||
const components = new Map();
|
||||
const bundle = await rollup.rollup({
|
||||
input: "src",
|
||||
plugins: [svelte(), resolve(), commonjs()],
|
||||
});
|
||||
const { output } = await bundle.generate({ format: "es", file: pkg.module });
|
||||
|
||||
for (const chunkOrAsset of output) {
|
||||
if (chunkOrAsset.type !== "asset" && chunkOrAsset.isEntry) {
|
||||
chunkOrAsset.exports.forEach((exportee) => {
|
||||
components.set(exportee, {});
|
||||
});
|
||||
|
||||
Object.keys(chunkOrAsset.modules)
|
||||
.sort()
|
||||
.forEach(async (filename) => {
|
||||
const { dir, ext, name } = path.parse(filename);
|
||||
const moduleName = name.replace(/\./g, "");
|
||||
|
||||
if (ext === ".svelte" && components.has(moduleName)) {
|
||||
const group = dir
|
||||
.split("src/")
|
||||
.pop()
|
||||
.split("/")[0];
|
||||
|
||||
if (groups.has(group)) {
|
||||
groups.set(group, [...groups.get(group), moduleName]);
|
||||
} else {
|
||||
groups.set(group, [moduleName]);
|
||||
}
|
||||
|
||||
const source = fs.readFileSync(filename, "utf-8");
|
||||
const component = parseComponent(source, {
|
||||
component: moduleName,
|
||||
onTypeDef: (tag) => {
|
||||
if (shared_types.has(tag.name)) return;
|
||||
|
||||
shared_types.add(tag.name);
|
||||
|
||||
const ts_type = tag.type.startsWith("{")
|
||||
? `interface ${tag.name} ${tag.type}`
|
||||
: `type ${tag.name} = ${tag.type};`;
|
||||
|
||||
definitions += ts_type + "\n\n";
|
||||
},
|
||||
});
|
||||
|
||||
let $$prop_def = "";
|
||||
|
||||
component.exported_props.forEach((prop, name) => {
|
||||
$$prop_def += "/**\n";
|
||||
|
||||
prop.description.split("\n").forEach((line) => {
|
||||
$$prop_def += "* " + line + "\n";
|
||||
});
|
||||
|
||||
if (prop.value !== undefined) {
|
||||
$$prop_def += "* @default " + prop.value + "\n";
|
||||
}
|
||||
|
||||
$$prop_def += "*/\n";
|
||||
|
||||
let value = "undefined";
|
||||
|
||||
if (prop.type) {
|
||||
value = prop.type;
|
||||
}
|
||||
|
||||
$$prop_def += name + "?: " + value + ";" + "\n\n";
|
||||
});
|
||||
|
||||
let $$slot_def = "";
|
||||
|
||||
component.slots.forEach((slot, slot_name) => {
|
||||
let value = "";
|
||||
|
||||
slot.attributes.forEach((attribute) => {
|
||||
if (attribute.name !== "name") {
|
||||
value += attribute.name + ": any;";
|
||||
}
|
||||
});
|
||||
|
||||
if (slot.default) {
|
||||
$$slot_def += "default: {" + value + "};" + "\n";
|
||||
} else {
|
||||
$$slot_def +=
|
||||
JSON.stringify(slot_name) + ": {" + value + "};" + "\n";
|
||||
}
|
||||
});
|
||||
|
||||
definitions += `
|
||||
export class ${moduleName} extends CarbonSvelteBase {
|
||||
${!!$$prop_def ? "$$prop_def: {\n" + $$prop_def + "\n}\n" : ""}
|
||||
|
||||
${!!$$slot_def ? "$$slot_def: {\n" + $$slot_def + "\n}\n" : ""}
|
||||
}\n\n`;
|
||||
|
||||
components.set(moduleName, component);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(pkg.types, definitions);
|
||||
}
|
||||
|
||||
generateDocs();
|
115
scripts/parse-component.js
Normal file
115
scripts/parse-component.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
const { parse, walk } = require("svelte/compiler");
|
||||
const commentParser = require("comment-parser");
|
||||
|
||||
function parseComponent(source, hooks) {
|
||||
const exported_props = new Map();
|
||||
const slots = new Map();
|
||||
const forwarded_events = new Map();
|
||||
const dispatched_events = new Map();
|
||||
|
||||
let hasDispatchedEvents = false;
|
||||
let dispatcher_name = null;
|
||||
let callee = [];
|
||||
|
||||
walk(parse(source), {
|
||||
enter(node, parent, prop) {
|
||||
switch (node.type) {
|
||||
case "CallExpression":
|
||||
if (hasDispatchedEvents) {
|
||||
if (node.callee.name === "createEventDispatcher") {
|
||||
dispatcher_name = parent.id.name;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Identifier":
|
||||
if (node.name === "createEventDispatcher") {
|
||||
hasDispatchedEvents = true;
|
||||
}
|
||||
|
||||
if (prop === "callee") {
|
||||
callee.push({ name: node.name, parent });
|
||||
}
|
||||
break;
|
||||
case "ExportNamedDeclaration":
|
||||
const { id, init } = node.declaration.declarations[0];
|
||||
|
||||
let value = undefined;
|
||||
let type = undefined;
|
||||
let description = null;
|
||||
|
||||
if (init != null) {
|
||||
value = init.raw;
|
||||
}
|
||||
|
||||
const general_comments = commentParser(source);
|
||||
|
||||
general_comments.forEach((comment) => {
|
||||
comment.tags.forEach((tag) => {
|
||||
if (tag.tag === "typedef") hooks.onTypeDef(tag);
|
||||
});
|
||||
});
|
||||
|
||||
if (node.leadingComments) {
|
||||
const comment = commentParser(
|
||||
"/*" + node.leadingComments[0].value + "*/"
|
||||
);
|
||||
|
||||
description = comment[0].description;
|
||||
type = comment[0].tags[0].type;
|
||||
} else {
|
||||
throw Error(
|
||||
`[${hooks.component}] property \`${id.name}\` should be annotated.`
|
||||
);
|
||||
}
|
||||
|
||||
exported_props.set(id.name, { value, type, description });
|
||||
break;
|
||||
case "Slot":
|
||||
let slot_name = null;
|
||||
|
||||
const slot_attributes = [];
|
||||
|
||||
node.attributes.forEach((attribute) => {
|
||||
if (attribute.name === "name") {
|
||||
slot_name = attribute.value[0].raw;
|
||||
} else {
|
||||
slot_attributes.push(attribute);
|
||||
}
|
||||
});
|
||||
|
||||
slots.set(slot_name == null ? "default" : slot_name, {
|
||||
attributes: node.attributes,
|
||||
children: node.children,
|
||||
default: slot_name == null,
|
||||
});
|
||||
break;
|
||||
case "EventHandler":
|
||||
if (node.expression == null) {
|
||||
forwarded_events.set(node.name, node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (hasDispatchedEvents) {
|
||||
callee.forEach((node) => {
|
||||
if (node.name === dispatcher_name) {
|
||||
const [name, detail] = node.parent.arguments;
|
||||
|
||||
dispatched_events.set(name.raw, {
|
||||
detail: detail ? source.slice(detail.start, detail.end) : undefined,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
exported_props,
|
||||
slots,
|
||||
forwarded_events,
|
||||
dispatched_events,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { parseComponent };
|
|
@ -16,7 +16,17 @@
|
|||
* @type {string} [placeholder=""]
|
||||
*/
|
||||
export let placeholder = "";
|
||||
|
||||
/**
|
||||
* Specify the Regular Expression for the input value
|
||||
* @type {string} [placeholder="\\d{1,2}\\/\\d{1,2}\\/\\d{4}"]
|
||||
*/
|
||||
export let pattern = "\\d{1,2}\\/\\d{1,2}\\/\\d{4}";
|
||||
|
||||
/**
|
||||
* Set to `true` to disable the input
|
||||
* @type {boolean} [disabled=false]
|
||||
*/
|
||||
export let disabled = false;
|
||||
|
||||
/**
|
||||
|
@ -30,7 +40,17 @@
|
|||
* @type {string} [id]
|
||||
*/
|
||||
export let id = "ccs-" + Math.random().toString(36);
|
||||
|
||||
/**
|
||||
* Specify the label text
|
||||
* @type {string} [labelText=""]
|
||||
*/
|
||||
export let labelText = "";
|
||||
|
||||
/**
|
||||
* Set to `true` to visually hide the label text
|
||||
* @type {boolean} [hideLabel=false]
|
||||
*/
|
||||
export let hideLabel = false;
|
||||
|
||||
/**
|
||||
|
@ -45,6 +65,10 @@
|
|||
*/
|
||||
export let invalidText = "";
|
||||
|
||||
/**
|
||||
* Set a name for the input element
|
||||
* @type {string} [name=""]
|
||||
*/
|
||||
export let name = undefined;
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,10 +3,24 @@
|
|||
* Set to `true` to indicate an invalid state
|
||||
* @type {boolean} [invalid=false]
|
||||
*/
|
||||
export let invalid = false;
|
||||
export let invalid = false;
|
||||
|
||||
/**
|
||||
* Set to `true` to render a form requirement
|
||||
* @type {boolean} [message=false]
|
||||
*/
|
||||
export let message = false;
|
||||
|
||||
/**
|
||||
* Specify the message text
|
||||
* @type {string} [messageText=""]
|
||||
*/
|
||||
export let messageText = "";
|
||||
|
||||
/**
|
||||
* Specify the legend text
|
||||
* @type {string} [legendText=""]
|
||||
*/
|
||||
export let legendText = "";
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
<script>
|
||||
/**
|
||||
* @typedef {string} MultiSelectItemId
|
||||
* @typedef {string} MultiSelectItemText
|
||||
* @typedef {{ id: MultiSelectItemId; text: MultiSelectItemText; }} MultiSelectItem
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set the multiselect items
|
||||
* @type {MultiSelectItem[]} [items=[]]
|
||||
|
@ -153,6 +147,12 @@
|
|||
*/
|
||||
export let name = undefined;
|
||||
|
||||
/**
|
||||
* @typedef {string} MultiSelectItemId
|
||||
* @typedef {string} MultiSelectItemText
|
||||
* @typedef {{ id: MultiSelectItemId; text: MultiSelectItemText; }} MultiSelectItem
|
||||
*/
|
||||
|
||||
import { afterUpdate, setContext } from "svelte";
|
||||
import WarningFilled16 from "carbon-icons-svelte/lib/WarningFilled16";
|
||||
import { Checkbox } from "../Checkbox";
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
/**
|
||||
* Specify the title of the icon
|
||||
* @type {string} [title]
|
||||
*/
|
||||
export let title = undefined;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
/**
|
||||
* Set to `true` to use the vertical variant
|
||||
* @type {boolean} [vertical=false]
|
||||
*/
|
||||
export let vertical = false;
|
||||
</script>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
/**
|
||||
* Set to `true` to use the vertical variant
|
||||
* @type {boolean} [vertical=false]
|
||||
*/
|
||||
export let vertical = false;
|
||||
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
<script>
|
||||
export let disabled = false;
|
||||
export let hidden = false;
|
||||
export let text = "";
|
||||
/**
|
||||
* Specify the option value
|
||||
* @type {string} [value=""]
|
||||
*/
|
||||
export let value = "";
|
||||
|
||||
/**
|
||||
* Specify the option text
|
||||
* @type {string} [text=""]
|
||||
*/
|
||||
export let text = "";
|
||||
|
||||
/**
|
||||
* Set to `true` to hide the option
|
||||
* @type {boolean} [hidden=false]
|
||||
*/
|
||||
export let hidden = false;
|
||||
|
||||
/**
|
||||
* Set to `true` to disable the option
|
||||
* @type {boolean} [disabled=false]
|
||||
*/
|
||||
export let disabled = false;
|
||||
|
||||
import { getContext, onDestroy } from "svelte";
|
||||
|
||||
const ctx = getContext("Select") || getContext("TimePickerSelect");
|
||||
|
|
|
@ -1,5 +1,74 @@
|
|||
<script>
|
||||
/**
|
||||
* Specify the value of the slider
|
||||
* @type {string} [value=""]
|
||||
*/
|
||||
export let value = "";
|
||||
|
||||
/**
|
||||
* Set the maximum slider value
|
||||
* @type {number} [max=100]
|
||||
*/
|
||||
export let max = 100;
|
||||
|
||||
/**
|
||||
* Specify the label for the max value
|
||||
* @type {string} [maxLabel=""]
|
||||
*/
|
||||
export let maxLabel = "";
|
||||
|
||||
/**
|
||||
* Set the minimum slider value
|
||||
* @type {number} [min=100]
|
||||
*/
|
||||
export let min = 0;
|
||||
|
||||
/**
|
||||
* Specify the label for the min value
|
||||
* @type {string} [minLabel=""]
|
||||
*/
|
||||
export let minLabel = "";
|
||||
|
||||
/**
|
||||
* Set the step value
|
||||
* @type {number} [step=1]
|
||||
*/
|
||||
export let step = 1;
|
||||
|
||||
/**
|
||||
* Set the step multiplier value
|
||||
* @type {number} [stepMultiplier=4]
|
||||
*/
|
||||
export let stepMultiplier = 4;
|
||||
|
||||
/**
|
||||
* Set to `true` to require a value
|
||||
* @type {boolean} [required=false]
|
||||
*/
|
||||
export let required = false;
|
||||
|
||||
/**
|
||||
* Specify the input type
|
||||
* @type {string} [inputType="number"]
|
||||
*/
|
||||
export let inputType = "number";
|
||||
|
||||
/**
|
||||
* Set to `true` to disable the slider
|
||||
* @type {boolean} [disabled=false]
|
||||
*/
|
||||
export let disabled = false;
|
||||
|
||||
/**
|
||||
* Set to `true` to enable the light variant
|
||||
* @type {boolean} [light=false]
|
||||
*/
|
||||
export let light = false;
|
||||
|
||||
/**
|
||||
* Set to `true` to hide the text input
|
||||
* @type {boolean} [hideTextInput=false]
|
||||
*/
|
||||
export let hideTextInput = false;
|
||||
|
||||
/**
|
||||
|
@ -7,7 +76,6 @@
|
|||
* @type {string} [id]
|
||||
*/
|
||||
export let id = "ccs-" + Math.random().toString(36);
|
||||
export let inputType = "number";
|
||||
|
||||
/**
|
||||
* Set to `true` to indicate an invalid state
|
||||
|
@ -21,26 +89,11 @@
|
|||
*/
|
||||
export let labelText = "";
|
||||
|
||||
/**
|
||||
* Set to `true` to enable the light variant
|
||||
* @type {boolean} [light=false]
|
||||
*/
|
||||
export let light = false;
|
||||
|
||||
export let max = 100;
|
||||
export let maxLabel = "";
|
||||
export let min = 0;
|
||||
export let minLabel = "";
|
||||
|
||||
/**
|
||||
* Set a name for the slider element
|
||||
* @type {string} [name=""]
|
||||
*/
|
||||
export let name = "";
|
||||
export let required = false;
|
||||
export let step = 1;
|
||||
export let stepMultiplier = 4;
|
||||
export let value = "";
|
||||
|
||||
/**
|
||||
* Obtain a reference to the HTML element
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
<script>
|
||||
/**
|
||||
* Set to `true` to select the item
|
||||
* @type {boolean} [isSelected]
|
||||
*/
|
||||
export let isSelected = undefined;
|
||||
|
||||
/**
|
||||
* Specify the `href` attribute
|
||||
* @type {string} [href]
|
||||
*/
|
||||
export let href = undefined;
|
||||
|
||||
/**
|
||||
* Specify the item text
|
||||
* @type {string} [text]
|
||||
*/
|
||||
export let text = undefined;
|
||||
</script>
|
||||
|
||||
|
|
1
tsconfig.json
Normal file
1
tsconfig.json
Normal file
|
@ -0,0 +1 @@
|
|||
{ "extends": "@tsconfig/svelte/tsconfig.json" }
|
5438
types/index.d.ts
vendored
5438
types/index.d.ts
vendored
File diff suppressed because it is too large
Load diff
23
yarn.lock
23
yarn.lock
|
@ -1546,6 +1546,11 @@
|
|||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@tsconfig/svelte@^1.0.8":
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-1.0.8.tgz#3669305544f8ccbc945dc6906e5be2e0770e7389"
|
||||
integrity sha512-o6vRhB2axVYXuur37VhHeOj7KYrQD5/y51Brsgfy/ymMTP0kGIvnOLcN9IR6NuzkdKJvnNhGYMGJPOh/MHYuZQ==
|
||||
|
||||
"@types/anymatch@*":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
|
||||
|
@ -3078,10 +3083,10 @@ capture-stack-trace@^1.0.0:
|
|||
resolved "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d"
|
||||
integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==
|
||||
|
||||
carbon-icons-svelte@^10.14.0:
|
||||
version "10.14.0"
|
||||
resolved "https://registry.npmjs.org/carbon-icons-svelte/-/carbon-icons-svelte-10.14.0.tgz#a26984db41bb3b04afcabfdbcf481d0387c4763b"
|
||||
integrity sha512-Ucfy6A0GtvCxBPNCuUaFj7QsxV6hN/R8E8L/RMoytdrkZFD+tkl5pUVOHypcmYYZF7Dumnxr6ePr2bvwyTs5lg==
|
||||
carbon-icons-svelte@^10.15.0:
|
||||
version "10.15.0"
|
||||
resolved "https://registry.npmjs.org/carbon-icons-svelte/-/carbon-icons-svelte-10.15.0.tgz#2e4a7f7e8c71c260239c8210d0506d023efc824f"
|
||||
integrity sha512-8J9+EHA+r1gp/8upFC8PD/mpreIvC61vkqhkOgxnCVVFixidd8XK8SIaMSlUJeovjImAh2Zj4AB4aMPsl/Xubg==
|
||||
|
||||
case-sensitive-paths-webpack-plugin@^2.2.0:
|
||||
version "2.3.0"
|
||||
|
@ -3405,6 +3410,11 @@ commander@^4.0.1, commander@^4.1.1:
|
|||
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
||||
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
||||
|
||||
comment-parser@^0.7.5:
|
||||
version "0.7.5"
|
||||
resolved "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.5.tgz#06db157a3b34addf8502393743e41897e2c73059"
|
||||
integrity sha512-iH9YA35ccw94nx5244GVkpyC9eVTsL71jZz6iz5w6RIf79JLF2AsXHXq9p6Oaohyl3sx5qSMnGsWUDFIAfWL4w==
|
||||
|
||||
commondir@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
|
||||
|
@ -10057,6 +10067,11 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^3.9.7:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
|
||||
uid-number@0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue