create-slinkity
Advanced tools
Comparing version 1.0.4 to 1.1.1-canary.0
220
cli.js
@@ -7,12 +7,107 @@ #!/usr/bin/env node | ||
const INDEX_MD = 'src/index.md' | ||
const LAYOUT_NJK = 'src/_includes/layout.njk' | ||
const PKG = 'package.json' | ||
const filesToPreprocess = new Set([INDEX_MD, PKG, LAYOUT_NJK]) | ||
const componentFlavorMeta = { | ||
react: { | ||
packageJson: { | ||
dependencies: { | ||
react: '^17.0.2', | ||
'react-dom': '^17.0.2', | ||
}, | ||
devDependencies: { | ||
'@slinkity/renderer-react': '^0.1.0', | ||
}, | ||
}, | ||
slinkityConfig: { | ||
renderer: 'reactRenderer', | ||
importStatement: "import reactRenderer from '@slinkity/renderer-react'", | ||
}, | ||
navLink: { | ||
href: '/react-page', | ||
text: 'React', | ||
}, | ||
shortcode: '{% react "Slinky", hydrate="eager" %}', | ||
exclusiveTemplates: ['src/react-page.jsx', 'src/_includes/Slinky.jsx', 'styles/slinky.scss'], | ||
}, | ||
vue: { | ||
packageJson: { | ||
dependencies: { | ||
vue: '^3.2.28', | ||
}, | ||
devDependencies: { | ||
'@slinkity/renderer-vue': '^0.1.0', | ||
}, | ||
}, | ||
slinkityConfig: { | ||
renderer: 'vueRenderer', | ||
importStatement: "import vueRenderer from '@slinkity/renderer-vue'", | ||
}, | ||
navLink: { | ||
href: '/vue-page', | ||
text: 'Vue', | ||
}, | ||
shortcode: '{% vue "Slinky.vue", hydrate="eager" %}', | ||
exclusiveTemplates: ['src/vue-page.vue', 'src/_includes/Slinky.vue'], | ||
}, | ||
svelte: { | ||
packageJson: { | ||
dependencies: { | ||
svelte: '^3.46.2', | ||
}, | ||
devDependencies: { | ||
'@slinkity/renderer-svelte': '^0.1.0', | ||
}, | ||
}, | ||
slinkityConfig: { | ||
renderer: 'svelteRenderer', | ||
importStatement: "import svelteRenderer from '@slinkity/renderer-svelte'", | ||
}, | ||
navLink: { | ||
href: '/svelte-page', | ||
text: 'Svelte', | ||
}, | ||
shortcode: '{% svelte "Slinky.svelte", hydrate="eager" %}', | ||
exclusiveTemplates: ['src/svelte-page.svelte', 'src/_includes/Slinky.svelte'], | ||
}, | ||
} | ||
function toSlinkityConfigContents(selectedComponentFlavors) { | ||
const renderers = selectedComponentFlavors.map( | ||
(flavor) => componentFlavorMeta[flavor].slinkityConfig.renderer, | ||
) | ||
const imports = selectedComponentFlavors.map( | ||
(flavor) => componentFlavorMeta[flavor].slinkityConfig.importStatement, | ||
) | ||
return `import { defineConfig } from 'slinkity' | ||
${imports.join('\n')} | ||
export default defineConfig({ | ||
renderers: [${renderers.join(', ')}], | ||
}) | ||
` | ||
} | ||
;(async () => { | ||
let dest = process.argv[2] | ||
const promptResponses = await prompts({ | ||
type: dest ? null : 'text', | ||
name: 'dest', | ||
message: 'What is your project called?', | ||
initial: 'my-slinkity-site', | ||
}) | ||
const promptResponses = await prompts([ | ||
{ | ||
type: dest ? null : 'text', | ||
name: 'dest', | ||
message: 'What is your project called?', | ||
initial: 'my-slinkity-site', | ||
}, | ||
{ | ||
type: 'multiselect', | ||
name: 'components', | ||
message: 'What flavor of components do you want, if any?', | ||
choices: [ | ||
{ title: 'React', value: 'react' }, | ||
{ title: 'Vue', value: 'vue' }, | ||
{ title: 'Svelte', value: 'svelte' }, | ||
], | ||
}, | ||
]) | ||
if (!dest) { | ||
@@ -25,18 +120,71 @@ dest = promptResponses.dest | ||
const srcRoot = path.join(__dirname, 'templates/react') | ||
const destRoot = path.join(process.cwd(), dest) | ||
fs.mkdirSync(destRoot) | ||
const srcResolved = path.join(__dirname, 'template') | ||
const destResolved = path.join(process.cwd(), dest) | ||
fs.mkdirSync(destResolved) | ||
// Set package name based on project name | ||
const pkg = require(path.join(srcRoot, PKG)) | ||
// copy files to output | ||
const templates = fs.readdirSync(srcResolved) | ||
const componentTemplates = new Set( | ||
Object.values(componentFlavorMeta).flatMap(({ exclusiveTemplates }) => exclusiveTemplates), | ||
) | ||
const selectedComponentTemplates = new Set( | ||
promptResponses.components.flatMap( | ||
(component) => componentFlavorMeta[component].exclusiveTemplates, | ||
), | ||
) | ||
for (const template of templates) { | ||
const src = path.join(srcResolved, template) | ||
const dest = path.join(destResolved, template) | ||
copy(src, dest, (filePath) => { | ||
// check whether or not we should copy the file | ||
const relativePath = path.relative(srcResolved, filePath) | ||
const isFileToPreprocess = filesToPreprocess.has(relativePath) | ||
const isOmittedComponentTemplate = | ||
componentTemplates.has(relativePath) && !selectedComponentTemplates.has(relativePath) | ||
return isFileToPreprocess || isOmittedComponentTemplate | ||
}) | ||
} | ||
// package.json | ||
const pkg = require(path.join(srcResolved, PKG)) | ||
pkg.name = toValidPackageName(dest) | ||
fs.writeFileSync(path.join(destRoot, PKG), JSON.stringify(pkg, null, 2)) | ||
for (const componentFlavor of promptResponses.components) { | ||
pkg.dependencies = { | ||
...pkg.dependencies, | ||
...componentFlavorMeta[componentFlavor].packageJson.dependencies, | ||
} | ||
pkg.devDependencies = { | ||
...pkg.devDependencies, | ||
...componentFlavorMeta[componentFlavor].packageJson.devDependencies, | ||
} | ||
} | ||
fs.writeFileSync(path.join(destResolved, PKG), JSON.stringify(pkg, null, 2)) | ||
// Copy all template files to dest | ||
// TODO: add "plain" starter alongside "react" | ||
const templateFilePaths = fs.readdirSync(srcRoot).filter(filePath => filePath !== PKG) | ||
for (const templateFilePath of templateFilePaths) { | ||
const src = path.join(srcRoot, templateFilePath) | ||
const dest = path.join(destRoot, templateFilePath) | ||
copy(src, dest) | ||
// index.md | ||
const indexMd = fs.readFileSync(path.join(srcResolved, INDEX_MD)).toString() | ||
const shortcodes = promptResponses.components.map( | ||
(componentFlavor) => componentFlavorMeta[componentFlavor].shortcode, | ||
) | ||
fs.writeFileSync( | ||
path.join(destResolved, INDEX_MD), | ||
indexMd.replace('<!--insert-component-shortcodes-here-->', shortcodes.join('\n')), | ||
) | ||
// layout.njk | ||
const layoutNjk = fs.readFileSync(path.join(srcResolved, LAYOUT_NJK)).toString() | ||
const navLinks = promptResponses.components.map((componentFlavor) => { | ||
const { href, text } = componentFlavorMeta[componentFlavor].navLink | ||
return `<a href="${href}">${text}</a>` | ||
}) | ||
fs.writeFileSync( | ||
path.join(destResolved, LAYOUT_NJK), | ||
layoutNjk.replace('<!--insert-nav-links-here-->', navLinks.join('\n ')), | ||
) | ||
// slinkity.config.js | ||
if (promptResponses.components.length) { | ||
fs.writeFileSync( | ||
path.join(destResolved, 'slinkity.config.js'), | ||
toSlinkityConfigContents(promptResponses.components), | ||
) | ||
} | ||
@@ -48,4 +196,4 @@ | ||
cd ${dest} | ||
yarn | ||
yarn start | ||
npm i | ||
npm start | ||
`) | ||
@@ -56,12 +204,13 @@ console.log(`Step 2: ${red('have fun ❤️')}`) | ||
/** | ||
* Util to copy file or file directory to dest | ||
* Inspired by https://github.com/vitejs/vite/blob/main/packages/create-vite/index.js | ||
* @param {string} src | ||
* @param {string} dest | ||
*/ | ||
function copy(src, dest) { | ||
* Util to copy file or file directory to dest | ||
* Inspired by https://github.com/vitejs/vite/blob/main/packages/create-vite/index.js | ||
* @param {string} src | ||
* @param {string} dest | ||
* @param {(filePath: string) => boolean} shouldOmit | ||
*/ | ||
function copy(src, dest, shouldOmit) { | ||
const stat = fs.statSync(src) | ||
if (stat.isDirectory()) { | ||
copyDir(src, dest) | ||
} else { | ||
copyDir(src, dest, shouldOmit) | ||
} else if (!shouldOmit(src)) { | ||
fs.copyFileSync(src, dest) | ||
@@ -74,6 +223,7 @@ } | ||
* Inspired by https://github.com/vitejs/vite/blob/main/packages/create-vite/index.js | ||
* @param {string} srcDir | ||
* @param {string} destDir | ||
* @param {string} srcDir | ||
* @param {string} destDir | ||
* @param {(filePath: string) => boolean} shouldOmit | ||
*/ | ||
function copyDir(srcDir, destDir) { | ||
function copyDir(srcDir, destDir, shouldOmit) { | ||
fs.mkdirSync(destDir, { recursive: true }) | ||
@@ -83,3 +233,3 @@ for (const file of fs.readdirSync(srcDir)) { | ||
const destFile = path.resolve(destDir, file) | ||
copy(srcFile, destFile) | ||
copy(srcFile, destFile, shouldOmit) | ||
} | ||
@@ -91,3 +241,3 @@ } | ||
* Inspired by https://github.com/vitejs/vite/blob/main/packages/create-vite/index.js | ||
* @param {string} projectName | ||
* @param {string} projectName | ||
* @returns {string} A valid package name | ||
@@ -102,2 +252,2 @@ */ | ||
.replace(/[^a-z0-9-~]+/g, '-') | ||
} | ||
} |
{ | ||
"name": "create-slinkity", | ||
"version": "1.0.4", | ||
"version": "1.1.1-canary.0", | ||
"description": "The splendid starter to scaffold your Slinkity site.", | ||
@@ -49,5 +49,5 @@ "main": "cli.js", | ||
"bugs": { | ||
"url": "https://github.com/slinkity/slinkity-starter/issues" | ||
"url": "https://github.com/slinkity/slinkity/issues" | ||
}, | ||
"homepage": "https://github.com/slinkity/slinkity-starter#readme", | ||
"homepage": "https://github.com/slinkity/slinkity#readme", | ||
"dependencies": { | ||
@@ -54,0 +54,0 @@ "kolorist": "^1.5.1", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
32
378
736147
1
1