UNPKG

create-parcel-static

Version:

Project builder for creating static sites based Parcel

44 lines (36 loc) 20.3 kB
#!/usr/bin/env node import Ge from"chalk";import q from"chalk";import Ve from"minimist";import v from"chalk";var N={name:"test",version:"1.0.0",description:"",staticFiles:{staticPath:"public"},scripts:{"clear:dist":"rimraf dist"},author:"",license:"ISC",devDependencies:{parcel:"^2.15.2",rimraf:"^6.0.1","@parcel/config-default":"^2.15.2","parcel-reporter-static-files-copy":"^1.5.3"}},A={default:{extends:["@parcel/config-default"],reporters:["...","parcel-reporter-static-files-copy"]}};import y from"deepmerge";import C from"fs-extra";import D from"path";var L=(t,e,s,n)=>{let l={content:[`./src/**/*.{${e}}`],separator:n==="pug"?"'_'":"':'",theme:{extend:{colors:{"dark-gray":"#3c3c43","light-gray":"#ebebef","navy-blue":"#243c5a","light-blue":"#dddde3",charcoal:"#32363f",slate:"#414853",silver:"#515c67","sky-blue":"#2563eb",pink:"#ec4899","soft-silver":"#e4e4e9","creamy-white":"#fffff5"}}},plugins:[]},r=JSON.stringify(l,null,2),o=`import type { Config } from 'tailwindcss'; export default ${r} satisfies Config`,a=`/** @type {import('tailwindcss').Config} */ export default ${r}`;return s===t.typescript.fileExt?o:a},T=()=>({type:"style",title:"Tailwind",name:"tailwind",fileExt:"css",devDeps:{default:{postcss:"^8.5.4",tailwindcss:"^3.4.17"},stylelint:{"stylelint-config-tailwindcss":"^0.0.7"}},configs:{postcss:{plugins:{tailwindcss:{}}},stylelint:{extends:["stylelint-config-standard","stylelint-config-tailwindcss"],rules:{"property-no-vendor-prefix":null,"lightness-notation":null}}},scripts:{stylelint:{"lint:styles":"stylelint src/styles/**/*.css","lint:styles:fix":"stylelint src/styles/**/*.css --fix"},prettier:{"prettier:style":"prettier src/**/*.css --check","prettier:style:fix":"prettier src/**/*.css --write"}}});var c={projectInitData:{},userChoice:{},warnMsgs:[],setUserChoi\u0441e:function(t){this.userChoice=t},setProjectInitData:function(t){this.projectInitData=t},setWarnMsgs:function(t){this.warnMsgs.push(t)},getUserChoice:function(){return this.userChoice}};var F=()=>({type:"style",title:"CSS",name:"css",fileExt:"css",configs:{stylelint:{extends:["stylelint-config-standard"]}},scripts:{stylelint:{"lint:styles":"stylelint src/styles/**/*.css","lint:styles:fix":"stylelint src/styles/**/*.css --fix"},prettier:{"prettier:style":"prettier src/**/*.css --check","prettier:style:fix":"prettier src/**/*.css --write"}}});var J=()=>({type:"markup",title:"Ejs",name:"ejs",fileExt:"ejs",devDeps:{default:{ejs:"^3.1.10","parcel-transformer-ejs":"^1.0.1"},prettier:{"prettier-plugin-ejs":"^1.0.3"}},configs:{parcel:{transformers:{"*.ejs":["parcel-transformer-ejs"]}},prettier:{plugins:["prettier-plugin-ejs"]}},scripts:{prettier:{"prettier:markup":"prettier src/**/*.ejs --check","prettier:markup:fix":"prettier src/**/*.ejs --write"}}});var Ce={env:{browser:!0,es6:!0},root:!0,extends:["eslint:recommended"],parserOptions:{ecmaVersion:2020,sourceType:"module"},rules:{"prefer-const":"error","no-var":"error","no-unused-vars":"error"}},M=()=>({type:"tool",title:"EsLint",name:"eslint",devDeps:{default:{eslint:"^8.57.0","eslint-plugin-import":"^2.31.0"},prettier:{"eslint-config-prettier":"^10.1.5"}},configs:{eslint:Ce}});var U=()=>({type:"markup",title:"HTML",name:"html",fileExt:"html",scripts:{prettier:{"prettier:markup":"prettier src/**/*.html --check","prettier:markup:fix":"prettier src/**/*.html --write"}}});var R=()=>({type:"script",title:"JavaScript",name:"javascript",fileExt:"js",scripts:{prettier:{"prettier:scripts":"prettier src/scripts/**/*.js --check","prettier:scripts:fix":"prettier src/scripts/**/*.js --write"},eslint:{"lint:scripts":"eslint src/scripts/**/*.js","lint:scripts:fix":"eslint src/scripts/**/*.js --fix"}}});import H from"deepmerge";var O={name:"jquery",title:"",type:"script",devDeps:{default:{jquery:"^3.7.1"},eslint:{"eslint-config-jquery":"^3.0.2"}},configs:{eslint:{env:{jquery:!0},extends:["jquery"]}}},De={title:"JQuery",name:"jquery",fileExt:"js",scripts:{prettier:{"prettier:scripts":"prettier src/scripts/**/*.js --check","prettier:scripts:fix":"prettier src/scripts/**/*.js --write"},eslint:{"lint:scripts":"eslint src/scripts/**/*.js","lint:scripts:fix":"eslint src/scripts/**/*.js --fix"}}},ke={title:"JQuery (TypeScript)",name:"jqueryts",fileExt:"ts",devDeps:{default:{typescript:"^5.8.3","@types/jquery":"^3.5.30"},eslint:{"@typescript-eslint/eslint-plugin":"^7.18.0","@typescript-eslint/parser":"^7.18.0"}},configs:{eslint:{parser:"@typescript-eslint/parser",plugins:["@typescript-eslint"],extends:["plugin:@typescript-eslint/eslint-recommended","plugin:@typescript-eslint/recommended"]}},scripts:{default:{"check:types":"tsc --noEmit"},prettier:{"prettier:scripts":"prettier src/scripts/**/*.ts --check","prettier:scripts:fix":"prettier src/scripts/**/*.ts --write"},eslint:{"lint:scripts":"eslint src/scripts/**/*.ts","lint:scripts:fix":"eslint src/scripts/**/*.ts --fix"}}},_=()=>H(O,De),Q=()=>H(O,ke);var W=()=>({type:"style",title:"Less",name:"less",fileExt:"less",devDeps:{default:{"@parcel/transformer-less":"^2.15.2"},stylelint:{"stylelint-config-standard-less":"^3.0.1","stylelint-less":"3.0.1"}},configs:{stylelint:{plugins:["stylelint-less"],extends:["stylelint-config-standard-less"],rules:{"at-rule-no-unknown":null,"color-no-invalid-hex":!0,"less/color-no-invalid-hex":!0}}},scripts:{stylelint:{"lint:styles":"stylelint src/styles/**/*.less","lint:styles:fix":"stylelint src/styles/**/*.less --fix"},prettier:{"prettier:style":"prettier src/**/*.less --check","prettier:style:fix":"prettier src/**/*.less --write"}}});var Ee={semi:!0,trailingComma:"all",singleQuote:!0,printWidth:80,tabWidth:2},V=()=>({type:"tool",title:"Prettier",name:"prettier",devDeps:{default:{prettier:"^3.5.3"}},configs:{prettier:Ee,stylelint:{plugins:["stylelint-prettier"]},eslint:{extends:["eslint-config-prettier"]}}});var Y=()=>({type:"markup",title:"Pug",name:"pug",fileExt:"pug",devDeps:{default:{"@parcel/transformer-pug":"^2.15.2"},prettier:{"@prettier/plugin-pug":"^3.4.0"}},scripts:{prettier:{"prettier:markup":"prettier src/**/*.pug --check --plugin=@prettier/plugin-pug","prettier:markup:fix":"prettier src/**/*.pug --write --plugin=@prettier/plugin-pug"}}});var Se=`rules: property-sort-order: 0 no-color-literals: 0 no-vendor-prefixes: 0`,z=()=>({type:"style",title:"SASS (Indented Syntax)",name:"sass",fileExt:"sass",devDeps:{default:{"@parcel/transformer-sass":"2.15.2"},stylelint:{"sass-lint":"^1.13.1"}},configs:{sasslint:Se},scripts:{stylelint:{"lint:styles":"sass-lint src/styles/*.sass -v -q"}}});var G=()=>({type:"style",title:"SASS (SCSS Syntax)",name:"scss",fileExt:"scss",devDeps:{default:{"@parcel/transformer-sass":"^2.15.2"},stylelint:{"stylelint-config-standard-scss":"^15.0.1","stylelint-scss":"^6.12.0"}},configs:{stylelint:{plugins:["stylelint-scss"],rules:{"at-rule-no-unknown":null,"scss/at-rule-no-unknown":!0,"scss/selector-no-redundant-nesting-selector":!0,"lightness-notation":null},extends:["stylelint-scss","stylelint-config-standard-scss"]}},scripts:{stylelint:{"lint:styles":"stylelint src/styles/**/*.scss","lint:styles:fix":"stylelint src/styles/**/*.scss --fix"},prettier:{"prettier:style":"prettier src/**/*.scss --check","prettier:style:fix":"prettier src/**/*.scss --write"}}});var K=()=>({type:"tool",title:"StyleLint",name:"stylelint",devDeps:{default:{stylelint:"^16.2.1","stylelint-config-standard":"^38.0.0"},prettier:{"stylelint-prettier":"^5.0.3"}},configs:{stylelint:{rules:{"property-no-vendor-prefix":null}}}});var X=()=>({type:"style",title:"Stylus",name:"stylus",fileExt:"styl",devDeps:{default:{"@parcel/transformer-stylus":"^2.15.2","stylelint-config-standard":"^36.0.1"},stylelint:{stylelint:"^15.10.3","stylelint-stylus":"^1.0.0"},prettier:{"prettier-plugin-stylus":"^0.1.0"}},configs:{stylelint:{plugins:["stylelint-stylus"],extends:["stylelint-stylus/standard"],rules:{"stylus/declaration-colon":"never","stylus/pythonic":"always","stylus/selector-list-comma":"never","stylus/semicolon":"never","stylus/single-line-comment":"always","stylus/at-extend-style":["@extend","@extends"]}},prettier:{plugins:["prettier-plugin-stylus"]}},scripts:{stylelint:{"lint:styles":"stylelint src/styles/**/*.styl","lint:styles:fix":"stylelint src/styles/**/*.styl --fix"},prettier:{"prettier:style":"prettier src/**/*.styl --check","prettier:style:fix":"prettier src/**/*.styl --write"}}});var Be={compilerOptions:{target:"es2020",module:"esnext",strict:!0,esModuleInterop:!0,skipLibCheck:!0,forceConsistentCasingInFileNames:!0},include:["src/**/*.ts"],exclude:["node_modules","dist"]},Z=()=>({type:"script",title:"TypeScript",name:"typescript",fileExt:"ts",devDeps:{default:{typescript:"5.8.3"},eslint:{"@typescript-eslint/eslint-plugin":"^7.18.0","@typescript-eslint/parser":"^7.18.0"}},configs:{typescript:Be,eslint:{parser:"@typescript-eslint/parser",plugins:["@typescript-eslint"],extends:["plugin:@typescript-eslint/eslint-recommended","plugin:@typescript-eslint/recommended"]}},scripts:{default:{"check:types":"tsc --noEmit"},prettier:{"prettier:scripts":"prettier src/scripts/**/*.ts --check","prettier:scripts:fix":"prettier src/scripts/**/*.ts --write"},eslint:{"lint:scripts":"eslint src/scripts/**/*.ts","lint:scripts:fix":"eslint src/scripts/**/*.ts --fix"}}});var i={html:U(),pug:Y(),ejs:J(),css:F(),sass:z(),scss:G(),less:W(),stylus:X(),tailwind:T(),javascript:R(),typescript:Z(),jquery:_(),jqueryts:Q(),eslint:M(),prettier:V(),stylelint:K(),getPluginData(t){return{name:this[t].name,title:this[t].title,type:this[t].type,fileExt:this[t].fileExt}},getDevDeps(t,e){let s=this[t];if(s&&s.devDeps&&s.devDeps[e])return s.devDeps[e]},getScritps(t,e){let s=this[t];if(s&&s.scripts&&s.scripts[e])return s.scripts[e]},getConfig(t,e){let s=this[t];if(s&&s.configs&&s.configs[e])return s?.configs[e]}};var h={},P={},$e={},k={...A.default},x=[];async function ee(){let{projectInitData:t,userChoice:e}=c,s=i.getPluginData(e.style),n=i.getPluginData(e.markup),l=i.getPluginData(e.script);if(!(n&&s&&l))throw console.error(v.red("Error:"),"markup-handler: Failed loading plugin"),new Error;if(s.name==="tailwind"){let r=i.getConfig("tailwind","postcss");x.push({fileName:".postcssrc",config:y($e,r)});try{await C.writeFile(D.join(t.projectPath,`tailwind.config.${l.fileExt}`),L(i,`,${n.fileExt}, ${l.fileExt}`,l.fileExt,n.name))}catch(o){throw console.error(v.red("Error: "),"Error when saving tailwind config"),o}}if(l.fileExt==="ts"){let r=i.getConfig("typescript","typescript");x.push({fileName:"tsconfig.json",config:r})}if(n.name==="ejs"){let r=i.getConfig("ejs","parcel");k=y(k,r)}if(e.prettier){let r=i.getConfig("prettier","prettier");[n,s,l].forEach(o=>{let a=i.getConfig(o.name,"prettier");a&&(r=y(r,a))}),x.push({fileName:".prettierrc",config:r})}if(e.stylelint)if(h=y(h,i.getConfig("stylelint","stylelint")),s.name==="sass")try{await C.writeFile(D.join(t.projectPath,".sasslintrc"),i.getConfig("sass","sasslint"))}catch(r){throw console.error(v.red("Error: "),"Error when saving sasslint config"),r}else{let r=i.getConfig(s.name,"stylelint");r&&(h=y(h,r)),e.prettier&&(h=y(h,i.getConfig("prettier","stylelint"))),x.push({fileName:".stylelintrc",config:h})}if(e.eslint){P=y(P,i.getConfig("eslint","eslint"));let r=i.getConfig(l.name,"eslint");r&&(P=y(P,r)),e.prettier&&(P=y(P,i.getConfig("prettier","eslint"))),x.push({fileName:".eslintrc",config:P})}x.push({fileName:".parcelrc",config:k}),x.forEach(r=>{try{C.writeJson(D.join(t.projectPath,r.fileName),r.config,{spaces:2})}catch(o){throw console.error(v.red("Error: "),`Error when saving ${r.fileName}`),o}})}import{confirm as be,select as Ie}from"@inquirer/prompts";import te from"chalk";var E=t=>t.reduce((e,s)=>{let n=i.getPluginData(s);return[...e,{name:n.title,value:n.name}]},[]),S=[{name:"markup",type:"select",message:"Select markup engine:",choices:E(["html","pug","ejs"])},{name:"style",type:"select",message:"Select Style processing tool:",choices:E(["css","sass","scss","less","stylus","tailwind"])},{name:"script",type:"select",message:"Select JavaScript tool:",choices:E(["javascript","typescript","jquery","jqueryts"])},{name:"prettier",type:"confirm",message:`Add ${i.getPluginData("prettier").title}?`,default:!0},{name:"stylelint",type:"confirm",message:`Add ${i.getPluginData("stylelint").title}?`,default:!0},{name:"eslint",type:"confirm",message:`Add ${i.getPluginData("eslint").title}?`,default:!0}];async function se(t){let e={};Object.entries(t).forEach(([n,l])=>{let r=S.find(o=>o.name===n);if(r)if(r.type==="select"){let o=r.choices.find(a=>a.value===l);o?e[n]=o.value:console.warn(te.yellow("Warning:"),`The value for --${n} is invalid. See the help (--help, -h) for a list of valid options.`)}else r.type==="confirm"&&(e[n]=l)});let s=S.filter(n=>!(n.name in e));for(let n of s){let l=S.find(r=>r.name===n.name);switch(l.type){case"select":e[l.name]=await Ie(l);break;case"confirm":e[l.name]=await be(l);break;default:throw console.error(te.red("Error:"),"Unsupported question type"),new Error}}return e}import qe from"fs-extra";import{dirname as Ne,join as Ae}from"path";import{fileURLToPath as Le}from"url";var re=()=>{try{let t=Ne(Le(import.meta.url));return qe.readJsonSync(Ae(t,"../package.json"))}catch(t){console.log(t)}};function ie(){console.log(` Usage: npm create parcel-static [project-name] -- [options] yarn create parcel-static [project-name] [options] pnpm create parcel-static [project-name] [options] bun create parcel-static [project-name] [options] Arguments: project-name Name of the project/project directory (optional) Options: --markup Choose template engine: 'html' | 'pug' | 'ejs' --style Choose style processing tool: 'css' | 'scss' | 'sass' | 'stylus' | 'less' | 'tailwind' --script Choose JavaScript tool: 'javascript' | 'typescript' | 'jquery' | 'jqueryts' --eslint Add ESLint --stylelint Add Stylelint --prettier Add Prettier --no-eslint Exclude ESLint (works similarly with Stylelint and Prettier) --version Display package version --help, --h Display this help message Examples: npm create parcel-static npm create parcel-static my-static-app npm create parcel-static my-static-app -- --markup pug --script javascript --eslint yarn create parcel-static my-static-app --style scss --markup html --no-prettier \u{1F4E6} Happy hacking! `)}import B from"chalk";import j from"fs-extra";import d from"path";import{fileURLToPath as Te}from"url";var Fe="../../templates",Je="src";async function Me(t,e,s){let l=await j.readFile(t,"utf-8");for(let[r,o]of Object.entries(s))l=l.replace(new RegExp(r,"g"),o);try{await j.writeFile(e,l,"utf-8")}catch(r){throw console.error(B.red("Error: "),"Error when processing extention paths in index file"),r}}async function ne(){let{projectInitData:t,userChoice:e}=c,s=i.getPluginData(e.style),n=i.getPluginData(e.markup),l=i.getPluginData(e.script);if(!(n&&s&&l))throw console.error(B.red("Error:"),"markup-handler: Failed loading plugin"),new Error;let r=s.name==="tailwind"?"tailwind":"base",o=d.resolve(Te(import.meta.url),Fe),a=d.join(t.projectPath,Je),f=`main.${s.fileExt}`,m=`index.${n.fileExt}`,u=`${l.name}.${l.fileExt}`,g=d.join(o,"template-markup"),w=d.join(o,"templates-script",u),de=d.join(o,`style-system-${r}`,"templates-style",f),he=d.join(o,`style-system-${r}`,"templates-index",m),Pe=d.join(a,"scripts",`main.${l.fileExt}`),xe=d.join(a,"styles",f),je=d.join(a,m),we={"{{style-file}}":f,"{{script-file}}":`main.${l.fileExt}`};try{await j.copy(g,t.projectPath),j.copy(w,Pe),j.copy(de,xe),Me(he,je,we)}catch(ve){throw console.error(B.red("Error: "),"Error when copying markup template"),ve}}import le from"chalk";import Ue from"fs-extra";import Re from"path";var p={...N};function He(t,e){c.setWarnMsgs(`The ${t.toUpperCase()} does not have an official ${e} plugin`)}function $(t,e){let s=i.getScritps(t,e);s?p.scripts={...p.scripts,...s}:He(t,i.getPluginData(e).title)}async function oe(){let{projectInitData:t,userChoice:e}=c,s=i.getPluginData(e.markup),n=i.getPluginData(e.style),l=i.getPluginData(e.script);if(!(s&&n&&l))throw console.error(le.red("Error:"),"Failed loading plugin"),new Error;p.name=t.packageName,p.scripts.start=`parcel src/index.${s.fileExt}`,p.scripts.build=`rimraf dist && parcel build src/index.${s.fileExt} --no-source-maps --public-url ./`,[s,n,l].forEach(o=>{let a=i.getPluginData(o.name),f=i.getDevDeps(a.name,"default"),m=i.getDevDeps(a.name,"stylelint"),u=i.getDevDeps(a.name,"eslint"),g=i.getDevDeps(a.name,"prettier"),w=i.getScritps(a.name,"default");p.devDependencies={...p.devDependencies,...f&&f,...e.eslint&&u&&u,...e.prettier&&g&&g,...e.stylelint&&m&&m},p.scripts={...p.scripts,...w&&w},e.prettier&&$(a.name,"prettier"),e.eslint&&a.type==="script"&&$(a.name,"eslint"),e.stylelint&&a.type==="style"&&$(a.name,"stylelint")});let r=(o,a)=>{let f=i.getDevDeps(o,a),m=new Set(Object.keys(p.devDependencies));return Object.keys(f).reduce((u,g)=>(m.has(g)||(u[g]=f[g]),u),{})};p.devDependencies={...p.devDependencies,...e.prettier&&r("prettier","default"),...e.eslint&&r("eslint","default"),...e.eslint&&e.prettier&&r("eslint","prettier"),...e.stylelint&&r("stylelint","default"),...e.stylelint&&e.prettier&&r("stylelint","prettier")};try{await Ue.writeJson(Re.join(c.projectInitData.projectPath,"package.json"),p,{spaces:2})}catch(o){throw console.error(le.red("Error: "),"Error when saving package.json"),o}}import{confirm as Oe,input as ae,select as _e}from"@inquirer/prompts";import b from"chalk";import I from"fs-extra";import{basename as Qe,resolve as We}from"path";import ce from"path";import pe from"validate-npm-package-name";async function fe(t){let e,s=t,n,r=process.env.npm_config_user_agent?.split(" ")[0].split("/")[0]||"npm",o=s||await ae({message:"Project name:",default:"parcel-project"});if(o.trim()==="/"){e=`${process.cwd()}/parcel-project`,s=n="parcel-project";let u=await ge(e),g=ce.relative(process.cwd(),e);return{projectPath:e,projectName:s,packageName:n,relativePath:g,pkgManager:r,to\u0421lean:u}}e=We(o),s=Qe(e);let a=ce.relative(process.cwd(),e),f=await ge(e),{errors:m}=pe(s);return n=m?await ae({message:"Package name:",default:"parcel-project",validate:u=>{let{errors:g}=pe(u);return g?"Please enter a valid package name.":!0}}):s,{projectPath:e,relativePath:a,projectName:s,packageName:n,pkgManager:r,to\u0421lean:f}}async function ge(t){if(!await I.pathExists(t)||(await I.readdir(t)).length===0)return!1;let n=await _e({message:"The target directory contains existing files. How would you like to proceed?",choices:[{name:"Cancel and manually delete files",value:"cancel"},{name:"Remove existing files and continue (Recommended)",value:"remove"},{name:"Ignore it and continue (Existing files will be replaced upon matching)",value:"continue"}]});return n==="cancel"&&(console.error(b.red("\u2716"),"Operation cancelled"),process.exit(0)),n==="remove"}async function ue(){let t=c.projectInitData.projectPath;await Oe({message:`All files in directory "${t}" will be erased. Continue?`,default:!1})||(console.error(b.red("\u2716"),"Operation cancelled"),process.exit(0));try{return await I.emptyDir(t),t}catch(s){throw console.error(b.red("Error: "),`Failed to clear the directory: ${t}`),console.error("Clear the directory manually and come back"),s}}async function me(){let t=re(),e=Ve(process.argv.slice(2),{string:["_"]});(e.help||e.h)&&(ie(),process.exit(0)),(e.version||e.v)&&(console.log(q.dim(`\u{1F4E6} create-parcel-static v${t.version}`)),process.exit(0)),c.setProjectInitData(await fe(e._[0])),c.setUserChoi\u0441e(await se(e)),c.projectInitData.to\u0421lean&&await ue(),await ne(),await oe(),await ee(),c.warnMsgs.length&&c.warnMsgs.forEach(s=>console.warn(q.yellow("Warning:"),`${s}`)),console.log(q.green("Done!"),"Now run:"),c.projectInitData.relativePath&&console.log(` cd ${c.projectInitData.relativePath}`),console.log(` ${c.projectInitData.pkgManager} install`),console.log(` ${c.projectInitData.pkgManager} start`)}var ye=process.versions.node,Ye=ye.split("."),ze=Ye[0];Number(ze)<14&&(console.error("You are running Node "+ye+`. Create Parcel App requires Node 14 or higher. Please update your version of Node.`),process.exit(1));me().catch(t=>{t.message==="User force closed the prompt with 0 null"&&(console.error(Ge.red("\u2716"),"Operation cancelled"),process.exit(0)),console.error(t),process.exit(1)});