kopia lustrzana https://github.com/shoelace-style/shoelace
add create script
rodzic
5bea4269a7
commit
9b8bee2bc5
10
README.md
10
README.md
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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.
|
||||
`);
|
Ładowanie…
Reference in New Issue