-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
86da482
commit 0c5984c
Showing
50 changed files
with
2,360 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,3 +15,4 @@ | |
/website/build/** | ||
|
||
/plugin-examples | ||
/packages/create-lwc-plugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Local Development of the create-lwc-plugin | ||
|
||
The minimal supported version of [NodeJS](https://nodejs.org/) for development is 18. | ||
|
||
1. Install the dependencies | ||
|
||
```shell | ||
npm install | ||
``` | ||
|
||
2. Create a development stub | ||
|
||
```shell | ||
npm run dev | ||
``` | ||
|
||
3. Running the CLI locally | ||
|
||
```shell | ||
node index.js | ||
``` | ||
|
||
## Publishing new version | ||
|
||
1. Install the dependencies | ||
|
||
```shell | ||
npm install | ||
``` | ||
|
||
2. Bump the version number in the `package.json` | ||
3. Build the package | ||
|
||
```shell | ||
npm run prepublishOnly | ||
``` | ||
|
||
4. Run `npx publint@latest` and ensure that there aren't any issues with the generated `package.json`. | ||
5. Publish the package | ||
```shell | ||
npm publish | ||
``` | ||
Hint: append `--dry-run` to the end of the publish command to see the results of | ||
the publish command without actually uploading the package to NPM. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# create-lwc-plugin | ||
|
||
**create-lwc-plugin** is an npm package designed to simplify the process of | ||
creating a new plugin for Lightweight Charts™. With this generator, you can | ||
quickly scaffold a project from a template for either | ||
|
||
- a Drawing primitive plugin, or | ||
- a Custom series plugin. | ||
|
||
By using this wizard-like tool, you can customize the initial setup of their | ||
plugin project by answering a few questions. This allows for a seamless and | ||
efficient starting point, saving valuable time and effort. | ||
|
||
Whether you are developing a new Drawing primitive plugin or a Custom series | ||
plugin for Lightweight Charts, this generator provides a structured and | ||
organized foundation. It ensures that your plugin adheres to the best practices | ||
and conventions of Lightweight Charts, making it easier to develop, maintain, | ||
and contribute to the community. | ||
|
||
Getting started with your Lightweight Charts plugin development has never been | ||
easier. Let the Lightweight Charts™ Plugin Scaffold Generator | ||
(`create-lwc-plugin`) handle the initial setup, so you can focus on creating | ||
outstanding plugins for Lightweight Charts™. | ||
|
||
✨ Need some examples for inspiration? Check out the | ||
[plugin-examples](https://github.com/tradingview/lightweight-charts/tree/master/plugin-examples) | ||
folder in the Lightweight Charts repo. | ||
|
||
## Scaffolding Your First Lightweight Charts™ Plugin | ||
|
||
With NPM: | ||
|
||
```bash | ||
npm create lwc-plugin@latest | ||
``` | ||
|
||
With Yarn: | ||
|
||
```bash | ||
yarn create lwc-plugin | ||
``` | ||
|
||
With PNPM: | ||
|
||
```bash | ||
pnpm create lwc-plugin | ||
``` | ||
|
||
## Using the generated project | ||
|
||
### Running Locally (during development) | ||
|
||
```shell | ||
npm install | ||
npm run dev | ||
``` | ||
|
||
Visit `localhost:5173` in the browser. | ||
|
||
### Compiling the Plugin | ||
|
||
```shell | ||
npm run compile | ||
``` | ||
|
||
Check the output in the `dist` folder. | ||
|
||
### Publishing To NPM | ||
|
||
You can configure the contents of the package's `package.json` within the | ||
`compile.mjs` script. | ||
|
||
Once you have compiled the plugin (see above section) then you can publish the | ||
package to NPM with these commands: | ||
|
||
```shell | ||
cd dist | ||
npm publish | ||
``` | ||
|
||
Hint: append `--dry-run` to the end of the publish command to see the results of | ||
the publish command without actually uploading the package to NPM. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { defineBuildConfig } from 'unbuild'; | ||
|
||
export default defineBuildConfig({ | ||
entries: ['src/index'], | ||
clean: true, | ||
rollup: { | ||
inlineDependencies: true, | ||
esbuild: { | ||
target: 'node18', | ||
minify: true, | ||
}, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/usr/bin/env node | ||
|
||
import './dist/index.mjs'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "create-lwc-plugin", | ||
"version": "1.0.0", | ||
"type": "module", | ||
"license": "MIT", | ||
"author": "TradingView", | ||
"description": "Wizard-like CLI tool for scaffolding a new plugin for Lightweight Charts™", | ||
"keywords": ["lightweight-charts", "lwc-plugin", "plugins"], | ||
"bin": { | ||
"create-lwc-plugin": "index.js" | ||
}, | ||
"files": [ | ||
"index.js", | ||
"template-*", | ||
"dist" | ||
], | ||
"scripts": { | ||
"dev": "unbuild --stub && echo 'now run `node index.js`'", | ||
"build": "unbuild", | ||
"typecheck": "tsc --noEmit", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"engines": { | ||
"node": "^18.0.0 || >=20.0.0" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/tradingview/lightweight-charts.git", | ||
"directory": "packages/create-lwc-plugin" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/slicedsilver/create-lwc-plugin/issues" | ||
}, | ||
"homepage": "https://tradingview.github.io/lightweight-charts/", | ||
"devDependencies": { | ||
"@clack/prompts": "^0.7.0", | ||
"@types/node": "^20.5.1", | ||
"picocolors": "^1.0.0", | ||
"unbuild": "^1.2.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
|
||
export function formatTargetDir(targetDir: string | undefined) { | ||
return targetDir?.trim().replace(/\/+$/g, ''); | ||
} | ||
|
||
export function copy(src: string, dest: string, contentReplacer?: (content: string) => string) { | ||
const stat = fs.statSync(src); | ||
if (stat.isDirectory()) { | ||
copyDir(src, dest, contentReplacer); | ||
} else { | ||
const content = fs.readFileSync(src).toString(); | ||
fs.writeFileSync(dest, contentReplacer ? contentReplacer(content) : content); | ||
} | ||
} | ||
|
||
export function copyDir(srcDir: string, destDir: string, contentReplacer?: (content: string) => string) { | ||
fs.mkdirSync(destDir, { recursive: true }); | ||
for (const file of fs.readdirSync(srcDir)) { | ||
const srcFile = path.resolve(srcDir, file); | ||
const destFile = path.resolve(destDir, file); | ||
copy(srcFile, destFile, contentReplacer); | ||
} | ||
} | ||
|
||
export function dirExists(dir: string) { | ||
return fs.existsSync(dir); | ||
} | ||
|
||
export function isEmpty(path: string) { | ||
const files = fs.readdirSync(path); | ||
return files.length === 0 || (files.length === 1 && files[0] === '.git'); | ||
} | ||
|
||
export function emptyDir(dir: string) { | ||
if (!fs.existsSync(dir)) { | ||
return; | ||
} | ||
for (const file of fs.readdirSync(dir)) { | ||
if (file === '.git') { | ||
continue; | ||
} | ||
fs.rmSync(path.resolve(dir, file), { recursive: true, force: true }); | ||
} | ||
} | ||
|
||
// editFile(path.resolve(root, `vite.config.${isTs ? 'ts' : 'js'}`), content => { | ||
// return content.replace('@vitejs/plugin-react', '@vitejs/plugin-react-swc'); | ||
// }); | ||
export function editFile(file: string, callback: (content: string) => string) { | ||
const content = fs.readFileSync(file, 'utf-8'); | ||
fs.writeFileSync(file, callback(content), 'utf-8'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
function pkgFromUserAgent(userAgent: string | undefined) { | ||
if (!userAgent) return undefined; | ||
const pkgSpec = userAgent.split(' ')[0]; | ||
const pkgSpecArr = pkgSpec.split('/'); | ||
return { | ||
name: pkgSpecArr[0], | ||
version: pkgSpecArr[1], | ||
}; | ||
} | ||
|
||
export function getPkgManagerName() { | ||
const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent); | ||
return pkgInfo ? pkgInfo.name : 'npm'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export function isValidPackageName(projectName: string) { | ||
return /^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test( | ||
projectName | ||
); | ||
} | ||
|
||
export function toValidPackageName(projectName: string) { | ||
return projectName | ||
.trim() | ||
.toLowerCase() | ||
.replace(/\s+/g, '-') | ||
.replace(/^[._]/, '') | ||
.replace(/[^a-z\d\-~]+/g, '-'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import fs from 'node:fs'; | ||
import path from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
import { intro, outro, spinner, cancel } from '@clack/prompts'; | ||
import color from 'picocolors'; | ||
import { Answers, askQuestions } from './questions'; | ||
import { copy } from './helpers/io'; | ||
|
||
const cwd = process.cwd(); | ||
|
||
const renameFiles: Record<string, string | undefined> = { | ||
_gitignore: '.gitignore', | ||
}; | ||
|
||
async function init() { | ||
console.log(); | ||
intro(color.inverse(' create-lwc-plugin ')); | ||
|
||
let answers: Answers; | ||
try { | ||
answers = await askQuestions(); | ||
} catch (e: unknown) { | ||
if (e instanceof Error) { | ||
cancel(e.message); | ||
} | ||
return process.exit(0); | ||
} | ||
|
||
const s = spinner(); | ||
|
||
s.start('Building your new plugin project'); | ||
const root = path.join(cwd, answers.targetFolderPath); | ||
if (answers.targetFolderPath) { | ||
fs.mkdirSync(root, { recursive: true }); | ||
} | ||
const templateDir = path.resolve( | ||
fileURLToPath(import.meta.url), | ||
'../..', | ||
`template-${answers.projectType}` | ||
); | ||
const commonTemplateDir = path.resolve( | ||
fileURLToPath(import.meta.url), | ||
'../..', | ||
`template-common` | ||
); | ||
|
||
const entryName = 'template-entry'; | ||
const newEntryName = answers.packageName.replace(/lwc-plugin-/, ''); | ||
const entryFileName = `${entryName}.ts`; | ||
const newEntryFileName = `${newEntryName}.ts`; | ||
|
||
const contentsReplacer = (content: string): string => { | ||
const result = content | ||
.replaceAll(entryName, newEntryName) | ||
.replace(/_PLUGINNAME_/g, answers.name) | ||
.replace(/_CLASSNAME_/g, answers.typeName) | ||
.replace(/_PACKAGENAME_/g, answers.packageName); | ||
if (answers.includeHints) { | ||
return result; | ||
} | ||
// Comments starting with '//*' are considered 'hints' | ||
return result.replace(/.*\/\/\*.*\r?\n/g, ''); | ||
}; | ||
|
||
const write = (dir: string, file: string, content?: string) => { | ||
const targetPath = path.join(root, renameFiles[file] ?? file); | ||
if (content) { | ||
fs.writeFileSync(targetPath, contentsReplacer(content)); | ||
} else { | ||
copy(path.join(dir, file), targetPath, contentsReplacer); | ||
} | ||
}; | ||
|
||
const files = fs.readdirSync(templateDir); | ||
for (const file of files) { | ||
write(templateDir, file); | ||
} | ||
|
||
const commonFiles = fs.readdirSync(commonTemplateDir); | ||
for (const file of commonFiles.filter(f => f !== 'package.json')) { | ||
write(commonTemplateDir, file); | ||
} | ||
|
||
const pkg = JSON.parse( | ||
fs.readFileSync(path.join(commonTemplateDir, `package.json`), 'utf-8') | ||
); | ||
|
||
pkg.name = answers.packageName; | ||
|
||
write(root, 'package.json', JSON.stringify(pkg, null, 2) + '\n'); | ||
|
||
fs.renameSync(path.join(root, 'src', entryFileName), path.join(root, 'src', newEntryFileName)); | ||
|
||
s.stop('Built your new plugin project'); | ||
|
||
outro("You're all set!"); | ||
} | ||
|
||
init().catch(e => { | ||
console.error(e); | ||
}); |
Oops, something went wrong.