generate metadata and fix code completion

This commit is contained in:
Cory LaViska
2021-03-03 16:56:42 -05:00
parent 9e3a573b53
commit 0bccc051d2
4 changed files with 49 additions and 14 deletions

View File

@@ -8,6 +8,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
## Next
- Added `vscode.html-custom-data.json` to the build to support IntelliSense
- Moved chunk files into a separate folder
- Updated esbuild to 0.8.54

View File

@@ -108,10 +108,10 @@ For example, `<button>` and `<sl-button>` both have a `type` attribute, but it d
## Code Completion
Shoelace ships with a `custom-elements.json` file that can be used to describe its components to supportive editors, providing code completion (also known as "code hinting" or "IntelliSense"). To enable this, you need to tell your editor where this file is.
### VS Code
Shoelace ships with a file called `vscode.html-custom-data.json` that can be used to describe its components to Visual Studio Code. This enables code completion for Shoelace components (also known as "code hinting" or "IntelliSense"). To enable it, you need to tell VS Code where the file is.
1. [Install Shoelace locally](/getting-started/installation.md#local-installation)
2. Create a folder called `.vscode` at the root of your project
3. Create a file inside the folder called `settings.json`
@@ -119,11 +119,15 @@ Shoelace ships with a `custom-elements.json` file that can be used to describe i
```js
{
"html.customData": ["./node_modules/@shoelace-style/shoelace/dist/custom-elements.json"]
"html.customData": ["./node_modules/@shoelace-style/shoelace/dist/vscode.html-custom-data.json"]
}
```
If `settings.json` already exists in your project, simply add the `html.customData` line to the root of the object.
If `settings.json` already exists, simply add the above line to the root of the object. Note that you may need to restart VS Code for the changes to take affect.
### Other Editors
Most popular editors support custom code completion with a bit of configuration. Please [submit a feature request](https://github.com/shoelace-style/shoelace/issues/new/choose) for your editor of choice. PRs are also welcome!
## React

View File

@@ -92,7 +92,7 @@ execSync('node scripts/make-icons.cjs', { stdio: 'inherit' });
await copy('./dist', './docs/dist');
}
console.log(chalk.green('The build has been generated! 📦'));
console.log(chalk.green('The build has finished! 📦'));
if (options.serve) {
const port = await getPort({

View File

@@ -1,5 +1,5 @@
//
// This script runs TypeDoc and uses its output to generate components.json which is used for the docs.
// This script runs TypeDoc and uses its output to generate metadata files used by the docs
//
const chalk = require('chalk');
const execSync = require('child_process').execSync;
@@ -13,22 +13,29 @@ function getTagName(className) {
return className.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`).replace(/^-/, '');
}
// Takes a prop or param and returns type info as a string and, if applicable, an array of possible values
function getTypeInfo(item) {
const values = [];
let type = item.type.name || '';
if (item.type.type === 'union') {
const types = item.type.types.map(t => {
if (t.type === 'literal' || t.type === 'reference') {
values.push(t.value);
type = `'${item.type.types.map(t => t.value).join(`' | '`)}'`;
}
if (t.type === 'intrinsic') {
values.push(t.name);
type = item.type.types.map(t => t.name).join(' | ');
}
});
}
return type;
return {
type,
values: values.length ? values : undefined
};
}
// Splits a string of tag text into a { name, description } object
@@ -58,7 +65,7 @@ execSync(
const data = JSON.parse(fs.readFileSync('.cache/typedoc.json', 'utf8'));
const modules = data.children;
const components = modules.filter(module => module.kindString === 'Class');
const output = {
const metadata = {
name: package.name,
description: package.description,
version: package.version,
@@ -108,12 +115,13 @@ components.map(async component => {
.filter(child => child.comment && child.comment.shortText); // only with comments
props.map(prop => {
const type = getTypeInfo(prop);
const { type, values } = getTypeInfo(prop);
api.props.push({
name: prop.name,
description: prop.comment.shortText,
type,
values,
defaultValue: prop.defaultValue
});
});
@@ -127,10 +135,11 @@ components.map(async component => {
const signature = method.signatures[0];
const params = Array.isArray(signature.parameters)
? signature.parameters.map(param => {
const type = getTypeInfo(param);
const { type, values } = getTypeInfo(param);
return {
name: param.name,
type,
values,
defaultValue: param.defaultValue
};
})
@@ -154,15 +163,36 @@ components.map(async component => {
.map(tag => api.cssCustomProperties.push({ name: tag.tag, description: tag.description }));
}
output.components.push(api);
metadata.components.push(api);
});
// Generate components.json
(async () => {
const filename = path.join('./dist/components.json');
const outputJson = JSON.stringify(output, null, 2);
const json = JSON.stringify(metadata, null, 2);
await mkdirp(path.dirname(filename));
fs.writeFileSync(filename, outputJson, 'utf8');
console.log(chalk.green(`Successfully generated components.json 🏷\n`));
fs.writeFileSync(filename, json, 'utf8');
})();
// Generate vscode.html-custom-data.json (for IntelliSense)
(async () => {
const filename = path.join('./dist/vscode.html-custom-data.json');
const customData = {
tags: metadata.components.map(component => ({
name: component.tag,
description: component.description,
attributes: component.props.map(prop => ({
name: prop.name,
description: prop.description,
values: prop.values ? prop.values.map(value => ({ name: value })) : undefined
}))
}))
};
const json = JSON.stringify(customData, null, 2);
await mkdirp(path.dirname(filename));
fs.writeFileSync(filename, json, 'utf8');
})();
console.log(chalk.green(`Successfully generated metadata 🏷\n`));