add create script

pull/411/head
Cory LaViska 2021-04-07 17:03:24 -04:00
rodzic 5bea4269a7
commit 9b8bee2bc5
5 zmienionych plików z 173 dodań i 1 usunięć

Wyświetl plik

@ -65,6 +65,16 @@ To generate a production build, run the following command.
npm run build
```
### Creating New Components
To scaffold a new component, run the following command, replacing `sl-tag-name` with the desired tag name.
```bash
npm run create sl-tag-name
```
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
### Contributing
Shoelace is an open source project and contributions are encouraged! If you're interesting in contributing, please review the [contribution guidelines](CONTRIBUTING.md) first.

Wyświetl plik

@ -10,6 +10,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
- Added `click()` method to `sl-checkbox`, `sl-radio`, and `sl-switch`
- Added the `activation` prop to `sl-tab-group` to allow for automatic and manual tab activation
- Added `npm run create <tag>` script to scaffold new components faster
- Fixed a bug in `sl-tooltip` where events weren't properly cleaned up on disconnect
- Fixed a bug in `sl-tooltip` where they wouldn't display after toggling `disabled` off and on again [#391](https://github.com/shoelace-style/shoelace/issues/391)
- Fixed a bug in `sl-details` where `show()` and `hide()` would toggle the control when disabled

Wyświetl plik

@ -90,6 +90,16 @@ npm start
After the initial build, a browser will open automatically to a local version of the docs. The documentation is powered by Docsify, which uses raw markdown files to generate pages on the fly.
### Creating New Components
To scaffold a new component, run the following command, replacing `sl-tag-name` with the desired tag name.
```bash
npm run create sl-tag-name
```
This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.
### Dev Sandbox
Component development occurs _within_ the local docs site. I've found that offering common variations _in the docs_ is more beneficial for users than segmenting demos and code examples into separate tools such as Storybook. This encourages more thorough documentation, streamlines development for maintainers, and simplifies how the project is built. It also reduces installation and startup times significantly.

Wyświetl plik

@ -32,7 +32,8 @@
"start": "node scripts/build.cjs --dev",
"build": "node scripts/build.cjs",
"prepublishOnly": "npm run build",
"prettier": "prettier --write --loglevel warn ."
"prettier": "prettier --write --loglevel warn .",
"create": "node scripts/create-component.cjs"
},
"dependencies": {
"@popperjs/core": "^2.7.0",

Wyświetl plik

@ -0,0 +1,150 @@
const args = process.argv.slice(2);
const chalk = require('chalk');
const fs = require('fs');
const mkdirp = require('mkdirp');
const path = require('path');
const tagName = (args[0] + '').toLowerCase().trim();
const tagNameWithoutPrefix = tagName.replace(/^sl-/, '');
const className = tagName.replace(/(^\w|-\w)/g, string => string.replace(/-/, '').toUpperCase());
const readableName = tagNameWithoutPrefix
.replace(/-/g, ' ')
.replace(/\w\S*/g, string => string.charAt(0).toUpperCase() + string.substr(1).toLowerCase());
const version = require('../package.json').version;
const minorVersion = version.split('.').slice(0, 2).join('.');
// Check for tag name
if (!tagName) {
console.error('Please provide a tag name for the new component.\n');
process.exit();
}
// Verify tag name prefix
if (!/^sl-/.test(tagName)) {
console.error('Tag names must start with the sl- prefix.\n');
process.exit();
}
// Generate a source file
const componentFile = `src/components/${tagNameWithoutPrefix}/${tagNameWithoutPrefix}.ts`;
if (fs.existsSync(componentFile)) {
console.error(`There is already a component using the <${tagName}> tag!\n`);
process.exit();
}
const componentSource = `
import { LitElement, html, unsafeCSS } from 'lit';
import { customElement } from 'lit/decorators';
import styles from 'sass:./${tagNameWithoutPrefix}.scss';
/**
* @since ${minorVersion}
* @status experimental
*
* @dependency sl-tag-here
* @dependency sl-tag-here
*
* @slot - The default slot.
* @slot example - A named slot called example.
*
* @part base - The component's base wrapper.
* @part example - Another part called example.
*/
@customElement('${tagName}')
export default class ${className} extends LitElement {
static styles = unsafeCSS(styles);
render() {
return html\`
<div part="base">
<slot></slot>
</div>
\`;
}
}
declare global {
interface HTMLElementTagNameMap {
'${tagName}': ${className};
}
}
`.trimLeft();
// Generate a stylesheet
const stylesFile = `src/components/${tagNameWithoutPrefix}/${tagNameWithoutPrefix}.scss`;
const stylesSource = `
@use '../../styles/component';
/**
* @prop --custom-property-here: Description here
*/
:host {
display: block;
}
`.trimLeft();
// Generate a docs page
const docsFile = `docs/components/${tagNameWithoutPrefix}.md`;
const docsSource = `
# ${readableName}
[component-header:${tagName}]
Brief description of the component here, followed by an example.
\`\`\`html preview
<${tagName}>
Hello, world!
</${tagName}>
\`\`\`
## Examples
### Variation
A description of the variation, followed by an example.
\`\`\`html preview
<${tagName}>
Here is a variation
</${tagName}>
\`\`\`
[component-metadata:${tagName}]
`.trimLeft();
// Create the files
mkdirp.sync(path.dirname(componentFile));
mkdirp.sync(path.dirname(stylesFile));
mkdirp.sync(path.dirname(docsFile));
fs.writeFileSync(componentFile, componentSource, 'utf8');
fs.writeFileSync(stylesFile, stylesSource, 'utf8');
fs.writeFileSync(docsFile, docsSource, 'utf8');
// Add it to shoelace.ts
const allExports = fs.readFileSync('src/shoelace.ts', 'utf8');
fs.writeFileSync(
'src/shoelace.ts',
`${allExports.trimRight()}\nexport { default as ${className} } from './components/${tagNameWithoutPrefix}/${tagNameWithoutPrefix}';\n`,
'utf8'
);
// Add it to _sidebar.md
const sidebar = fs.readFileSync('docs/_sidebar.md', 'utf8');
fs.writeFileSync(
'docs/_sidebar.md',
sidebar.replace('- Components', `- Components\n - [${readableName}](/components/${tagNameWithoutPrefix}.md)`),
'utf8'
);
console.log(chalk.green(`The <${tagName}> component has been created:`));
console.log(`
- created ${componentFile}
- created ${stylesFile}
- created ${docsFile}
- updated src/shoelace.ts
- updated docs/_sidebar.md
Use ${chalk.cyan('npm start')} to launch the dev server.
`);