diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000..51932413 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", + "changelog": [ + "@svitejs/changesets-changelog-github-compact", + { "repo": "skeletonlabs/skeleton" } + ], + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9cde0bd5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,75 @@ +name: CI + +on: + pull_request: + +# cancel in-progress runs on new commits to same PR (github.event.number) +concurrency: + group: ${{ github.workflow }}-${{ github.event.number || github.sha }} + cancel-in-progress: true + +jobs: + check: + name: Run svelte-check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: pnpm/action-setup@v2 + with: + version: 8 + - uses: actions/setup-node@v3 + with: + node-version: 18 + + # PNPM Store cache setup + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Run svelte-check + run: pnpm ci:check + env: + VERCEL_ENV: dev + + lint: + name: Run linter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: pnpm/action-setup@v2 + with: + version: 8 + - uses: actions/setup-node@v3 + with: + node-version: 18 + + # PNPM Store cache setup + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Run prettier and eslint + run: pnpm ci:lint + diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml new file mode 100644 index 00000000..b0ff7f56 --- /dev/null +++ b/.github/workflows/release-dev.yml @@ -0,0 +1,60 @@ +name: Publish Skeleton @dev Release +on: + push: + branches: + - dev + paths: + - "packages/skeleton/**" + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + dev-release: + name: Build & Publish @dev Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Use PNPM v8 + uses: pnpm/action-setup@v2 + with: + version: 8 + + - name: Use Node v18 + uses: actions/setup-node@v3 + with: + node-version: 18 + + # PNPM Store cache setup + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Bump version to dev release + run: node scripts/dev-version.js + + - name: Packaging + run: pnpm ci:package + + - name: Authenticate to NPM & Publish + run: | + cat << EOF > "$HOME/.npmrc" + //registry.npmjs.org/:_authToken=$NPM_TOKEN + EOF + pnpm publish packages/skeleton --access public --tag dev --no-git-checks + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..6a35d583 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,70 @@ +name: Publish Skeleton +on: + push: + branches: + - master + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + name: Build & Publish @latest Release + if: github.repository == 'skeletonlabs/skeleton' + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Use PNPM v8 + uses: pnpm/action-setup@v2 + with: + version: 8 + + - name: Use Node v18 + uses: actions/setup-node@v3 + with: + node-version: 18 + + # PNPM Store cache setup + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Create Release Pull Request or Publish + id: changesets + uses: changesets/action@v1 + with: + commit: "chore(release): version package" + title: "chore(release): version package" + publish: pnpm ci:release + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update tw-settings.json after publish + if: steps.changesets.outputs.published == 'true' + continue-on-error: true + run: | + git add ./packages/skeleton/scripts/tw-settings.json + git commit -m "updated tw-settings.json" + git push + + - name: Merge master into dev after publish + if: steps.changesets.outputs.published == 'true' + run: | + git checkout dev + git merge master + git push diff --git a/.gitignore b/.gitignore index 7d2c487b..c7d2de47 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ src/lib/tailwind/generated vite.config.ts.timestamp-**.mjs /packages/* +!/packages/create-skeleton-app !/packages/skeleton /sites/* -!/sites/skeleton.dev \ No newline at end of file +!/sites/skeleton.dev diff --git a/package.json b/package.json index 7621f8a8..28251c2e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,14 @@ "postinstall": "pnpm -r sync", "csa": "node ./packages/create-skeleton-app/src/index.js --types=typescript --prettier --eslint --playwright=false --vitest=false --codeblocks --popups --typography --forms -t=skeleton --skeletontemplate=welcome -p=sites --monorepo --inspector", "csl": "node ./packages/create-skeleton-app/src/index.js --types=typescript --library --prettier --eslint --playwright --vitest --codeblocks --popups --typography --forms -t=skeleton --skeletontemplate=bare -p=packages --monorepo --inspector", - "templategen": "node ./scripts/template-gen.js" + "templategen": "node ./scripts/template-gen.js", + "format": "pnpm --parallel format", + "ci:publish": "changeset publish", + "ci:package": "pnpm -r package", + "ci:release": "pnpm ci:package && pnpm ci:publish", + "ci:lint": "pnpm -r lint", + "ci:check": "pnpm -r check", + "cs": "changeset" }, "license": "MIT", "homepage": "https://skeleton.dev/", @@ -36,6 +43,8 @@ "sveltekit" ], "devDependencies": { + "@changesets/cli": "^2.26.1", + "@svitejs/changesets-changelog-github-compact": "^1.1.0", "cspell": "^6.31.1", "shelljs": "^0.8.5" }, diff --git a/packages/create-skeleton-app/.eslintrc.cjs b/packages/create-skeleton-app/.eslintrc.cjs new file mode 100644 index 00000000..176fe9dd --- /dev/null +++ b/packages/create-skeleton-app/.eslintrc.cjs @@ -0,0 +1,14 @@ +module.exports = { + root: true, + extends: ['eslint:recommended', 'prettier'], + ignorePatterns: ['*.cjs'], + parserOptions: { + sourceType: 'module', + ecmaVersion: 2020, + }, + env: { + browser: false, + es2017: true, + node: true, + }, +}; diff --git a/packages/create-skeleton-app/.gitignore b/packages/create-skeleton-app/.gitignore new file mode 100644 index 00000000..cca9fbd3 --- /dev/null +++ b/packages/create-skeleton-app/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +node_modules +dist +package +.turbo \ No newline at end of file diff --git a/packages/create-skeleton-app/.prettierignore b/packages/create-skeleton-app/.prettierignore new file mode 100644 index 00000000..48366998 --- /dev/null +++ b/packages/create-skeleton-app/.prettierignore @@ -0,0 +1,13 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock \ No newline at end of file diff --git a/packages/create-skeleton-app/.prettierrc b/packages/create-skeleton-app/.prettierrc new file mode 100644 index 00000000..bf79d406 --- /dev/null +++ b/packages/create-skeleton-app/.prettierrc @@ -0,0 +1,8 @@ +{ + "tabWidth": 4, + "useTabs": true, + "semi": true, + "singleQuote": true, + "printWidth": 140, + "trailingComma": "all" +} diff --git a/packages/create-skeleton-app/CODE_OF_CONDUCT.md b/packages/create-skeleton-app/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..adae0062 --- /dev/null +++ b/packages/create-skeleton-app/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +This repository is governed by the Skeleton Code of Conduct. + +https://github.com/skeletonlabs/community/blob/main/CODE_OF_CONDUCT.md diff --git a/packages/create-skeleton-app/LICENSE b/packages/create-skeleton-app/LICENSE new file mode 100644 index 00000000..63267b02 --- /dev/null +++ b/packages/create-skeleton-app/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Skeleton Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/create-skeleton-app/README-MONO.md b/packages/create-skeleton-app/README-MONO.md new file mode 100644 index 00000000..a91dfb78 --- /dev/null +++ b/packages/create-skeleton-app/README-MONO.md @@ -0,0 +1,26 @@ +# create-skeleton-app + +This is a special multi-repo version of the site created by CSA. + +Differences from a normal CSA site: + +- Vite alias to the @skeletonlabs/skeleton project +- Removed @skeletonlabs/skeleton from package.json +- Added Vercel deploy command to package.json + +At this point it only supports deploying to Vercel. + +## Reminder + +Since you have just created this site with `pnpm site `, make sure to `git init`, `git add .`, `gh repo create` and run `pnpm dev` at least once so that the alias gets setup in .svelte-kit + +## Deploying a site to Vercel + +Repos that are not part of the main Skeleton repo will not work independently of the monorepo due to the adjustments to the @skeletonlabs/skeleton package noted above. Therefore to deploy a site, it is necessary to take advantage of the `vercel build` and `vercel deploy` of a local production build (or you can have fun setting up a GH deploy pipeline) + +```bash +# ensure you have the vercel cli tool +pnpm i -g vercel +``` + +Two scripts have been added to package.json diff --git a/packages/create-skeleton-app/README.md b/packages/create-skeleton-app/README.md new file mode 100644 index 00000000..510229ec --- /dev/null +++ b/packages/create-skeleton-app/README.md @@ -0,0 +1,33 @@ +[![Skeleton](https://user-images.githubusercontent.com/1509726/199282306-7454adcb-b765-4618-8438-67655a7dee47.png)](https://www.skeleton.dev/) + +[![npm version](https://img.shields.io/npm/v/create-skeleton-app?logo=npm&color=cb3837)](https://www.npmjs.com/package/create-skeleton-app) +[![Chat](https://img.shields.io/discord/1003691521280856084?label=chat&logo=discord&color=7289da)](https://discord.gg/EXqV7W8MtY) +[![Twitter Follow](https://img.shields.io/twitter/follow/SkeletonUI?style=social)](https://twitter.com/SkeletonUI) +[![license](https://img.shields.io/badge/license-MIT-%23bada55)](https://github.com/Brain-Bones/skeleton/blob/master/LICENSE) + +# 💀 Create Skeleton App + +This is the CLI tool for setting up a new Skeleton App that uses [Skeleton](https://skeleton.dev/), [SvelteKit](https://kit.svelte.dev/) and [Tailwind CSS](https://tailwindcss.com/). + +`npm create skeleton-app@latest` + +Is all you need to get started. It also supports using `npm`, `pnpm` and `yarn`. + +While it largely mirrors the standard Svelte-Kit [create-svelte](https://github.com/sveltejs/kit/tree/master/packages/create-svelte) app, it adds some additional choices that are relevant to Skeleton. + +# Info + +You can see all command line options by running `npm create skeleton-app@latest -h` + +The `Enable Svelte-Kit experimental inspector?` option allows you to press ctrl-shift or opt-shift in the browser window of your running project to see an outline of each component - clicking will then launch you directly to the source of that component in VSCode. More information about this option can be found [here](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md#inspector). + +The Tailwind plugins are purely optional, see their [docs](https://tailwindcss.com/docs/plugins#official-plugins) for more information. You can also use those docs to add the plugins after initially creating your project with the CLI. + +## 👋 Community + +- [Join the Discord](https://discord.gg/EXqV7W8MtY) +- [Follow on Twitter](https://twitter.com/SkeletonUI) + +## 🐞 Report an Issue + +- [Submit Issue](https://github.com/skeleton/create-skeleton-app/issues/new/choose) diff --git a/packages/create-skeleton-app/package.json b/packages/create-skeleton-app/package.json new file mode 100644 index 00000000..ba65addd --- /dev/null +++ b/packages/create-skeleton-app/package.json @@ -0,0 +1,54 @@ +{ + "name": "create-skeleton-app", + "version": "0.0.44", + "description": "Use this CLI app to setup a new Skeleton application in a new SvelteKit project.", + "keywords": [ + "skeleton", + "svelte", + "sveltekit", + "svelte-kit" + ], + "homepage": "https://www.skeleton.dev", + "repository": { + "type": "git", + "url": "https://github.com/skeletonlabs/skeleton", + "directory": "packages/create-skeleton-app/" + }, + "license": "MIT", + "author": "Skeleton Admin ", + "type": "module", + "main": "./src/index.js", + "bin": "./src/index.js", + "files": [ + "src/**", + "templates/**" + ], + "engines": { + "node": ">=14.16" + }, + "scripts": { + "dev": "node src/index.js", + "long": "node src/index.js --types=typescript --prettier --eslint --playwright=false --vitest=false --codeblocks=true --popups=true --typography=false --forms=false -t crimson --skeletontemplate=welcome", + "pub:beta": "npm publish --tag beta", + "pub:next": "npm publish --tag next", + "pub:release": "npm publish", + "release": "npm publish", + "lint": "prettier --ignore-path .prettierignore --check --plugin-search-dir=. . && eslint --fix --ignore-path .gitignore .", + "format": "prettier --plugin-search-dir . --write ." + }, + "dependencies": { + "@clack/prompts": "^0.6.3", + "create-svelte": "^4.2.0", + "fs-extra": "^11.1.1", + "got": "^12.6.0", + "kleur": "^4.1.5", + "mri": "^1.2.0", + "semver": "^7.5.1" + }, + "devDependencies": { + "eslint": "^8.41.0", + "eslint-config-prettier": "^8.8.0", + "prettier": "^2.8.8", + "svelte": "^3.59.1" + } +} diff --git a/packages/create-skeleton-app/pnpm-lock.yaml b/packages/create-skeleton-app/pnpm-lock.yaml new file mode 100644 index 00000000..c532d631 --- /dev/null +++ b/packages/create-skeleton-app/pnpm-lock.yaml @@ -0,0 +1,918 @@ +lockfileVersion: '6.0' + +dependencies: + '@clack/prompts': + specifier: ^0.6.3 + version: 0.6.3 + create-svelte: + specifier: ^4.2.0 + version: 4.2.0 + fs-extra: + specifier: ^11.1.1 + version: 11.1.1 + got: + specifier: ^12.6.0 + version: 12.6.0 + kleur: + specifier: ^4.1.5 + version: 4.1.5 + mri: + specifier: ^1.2.0 + version: 1.2.0 + semver: + specifier: ^7.5.1 + version: 7.5.1 + +devDependencies: + eslint: + specifier: ^8.41.0 + version: 8.41.0 + eslint-config-prettier: + specifier: ^8.8.0 + version: 8.8.0(eslint@8.41.0) + prettier: + specifier: ^2.8.8 + version: 2.8.8 + svelte: + specifier: ^3.59.1 + version: 3.59.1 + +packages: + + /@clack/core@0.3.2: + resolution: {integrity: sha512-FZnsNynwGDIDktx6PEZK1EuCkFpY4ldEX6VYvfl0dqeoLPb9Jpw1xoUXaVcGR8ExmYNm1w2vdGdJkEUYD/2pqg==} + dependencies: + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + + /@clack/prompts@0.6.3: + resolution: {integrity: sha512-AM+kFmAHawpUQv2q9+mcB6jLKxXGjgu/r2EQjEwujgpCdzrST6BJqYw00GRn56/L/Izw5U7ImoLmy00X/r80Pw==} + dependencies: + '@clack/core': 0.3.2 + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + bundledDependencies: + - is-unicode-supported + + /@eslint-community/eslint-utils@4.4.0(eslint@8.41.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.41.0 + eslint-visitor-keys: 3.4.1 + dev: true + + /@eslint-community/regexpp@4.5.1: + resolution: {integrity: sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.0.3: + resolution: {integrity: sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.5.2 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.41.0: + resolution: {integrity: sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.8: + resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@sindresorhus/is@5.3.0: + resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==} + engines: {node: '>=14.16'} + dev: false + + /@szmarczak/http-timer@5.0.1: + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + dependencies: + defer-to-connect: 2.0.1 + dev: false + + /@types/http-cache-semantics@4.0.1: + resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} + dev: false + + /acorn-jsx@5.3.2(acorn@8.8.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.2 + dev: true + + /acorn@8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + dev: false + + /cacheable-request@10.2.10: + resolution: {integrity: sha512-v6WB+Epm/qO4Hdlio/sfUn69r5Shgh39SsE9DSd4bIezP0mblOlObI+I0kUEM7J0JFc+I7pSeMeYaOYtX1N/VQ==} + engines: {node: '>=14.16'} + dependencies: + '@types/http-cache-semantics': 4.0.1 + get-stream: 6.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.2 + mimic-response: 4.0.0 + normalize-url: 8.0.0 + responselike: 3.0.0 + dev: false + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /create-svelte@4.2.0: + resolution: {integrity: sha512-jngi/IOM4NIGL4A61fN6diilrxcNe1iH3pziK6QmsL95h3B2p8gFyc4xZ7Oi9UbxO74o/kivrd3cIwqefWd0bA==} + hasBin: true + dependencies: + '@clack/prompts': 0.6.3 + kleur: 4.1.5 + dev: false + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: false + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + dev: false + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier@8.8.0(eslint@8.41.0): + resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.41.0 + dev: true + + /eslint-scope@7.2.0: + resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.1: + resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.41.0: + resolution: {integrity: sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.41.0) + '@eslint-community/regexpp': 4.5.1 + '@eslint/eslintrc': 2.0.3 + '@eslint/js': 8.41.0 + '@humanwhocodes/config-array': 0.11.8 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.0 + eslint-visitor-keys: 3.4.1 + espree: 9.5.2 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.20.0 + graphemer: 1.4.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.5.2: + resolution: {integrity: sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.2 + acorn-jsx: 5.3.2(acorn@8.8.2) + eslint-visitor-keys: 3.4.1 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + dev: false + + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: false + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: false + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /got@12.6.0: + resolution: {integrity: sha512-WTcaQ963xV97MN3x0/CbAriXFZcXCfgxVp91I+Ze6pawQOa7SgzwSx2zIJJsX+kTajMnVs0xcFD1TxZKFqhdnQ==} + engines: {node: '>=14.16'} + dependencies: + '@sindresorhus/is': 5.3.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.10 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.0 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: false + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: false + + /http2-wrapper@2.2.0: + resolution: {integrity: sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==} + engines: {node: '>=10.19.0'} + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + dev: false + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: false + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.0 + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + + /keyv@4.5.2: + resolution: {integrity: sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==} + dependencies: + json-buffer: 3.0.1 + dev: false + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: false + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: false + + /mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /normalize-url@8.0.0: + resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} + engines: {node: '>=14.16'} + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + + /p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + dev: false + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: false + + /resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + dev: false + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} + dependencies: + lowercase-keys: 3.0.0 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /semver@7.5.1: + resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /svelte@3.59.1: + resolution: {integrity: sha512-pKj8fEBmqf6mq3/NfrB9SLtcJcUvjYSWyePlfCqN9gujLB25RitWK8PvFzlwim6hD/We35KbPlRteuA6rnPGcQ==} + engines: {node: '>= 8'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /universalify@2.0.0: + resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + engines: {node: '>= 10.0.0'} + dev: false + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /word-wrap@1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/packages/create-skeleton-app/src/creator.js b/packages/create-skeleton-app/src/creator.js new file mode 100644 index 00000000..6e1c8565 --- /dev/null +++ b/packages/create-skeleton-app/src/creator.js @@ -0,0 +1,323 @@ +// Types +import { create } from 'create-svelte'; +import fs from 'fs-extra'; +import got from 'got'; +import { bold, cyan, red } from 'kleur/colors'; +import { spawnSync } from 'node:child_process'; +import path from 'path'; +import process from 'process'; +import { dist, mkdirp, removeFilesExceptSync, whichPMRuns } from './utils.js'; +import * as url from 'url'; +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); + +// NOTE: Any changes here must also be reflected in the --help output in utils.js and shortcut expansions in index.js. +// Probably a good idea to do a search on the values you are changing to catch any other areas they are used in + +export class SkeletonOptions { + // svelte-create expects these options, do not change the names or values. + constructor() { + this.name = 'new-skel-app'; + this.template = 'skeleton'; + this.types = 'typescript'; + this.prettier = true; + this.eslint = true; + this.playwright = false; + this.vitest = false; + + // create-skeleton-app additions + this._ = []; //catch all for extraneous params from mri, used to capture project name. + this.help = false; + this.quiet = false; + this.path = '.'; + this.forms = false; + this.typography = false; + this.codeblocks = false; + this.popups = true; + this.inspector = false; + this.skeletontheme = 'skeleton'; + this.skeletontemplate = 'bare'; + this.packagemanager = 'pnpm'; + this.packages = []; + + // props below are private to the Skeleton team + this.verbose = false; + this.monorepo = false; + this.packages = []; + this.skeletontemplatedir = '../templates'; + this.workspace = ''; + } +} + +export async function createSkeleton(opts) { + const startPath = process.cwd(); + + // Hidden option to change the install type to be a Svelte-Kit library project + if (opts?.library) { + opts.template = 'skeletonlib'; + } + + //create-svelte will build the base install for us + await create(opts.path, opts); + process.chdir(opts.path); + + // install packages + opts.packagemanager = whichPMRuns()?.name || 'npm'; + + // the order matters due to dependency resolution, because yarn + let packages = ['postcss', 'autoprefixer', 'tailwindcss', '@skeletonlabs/skeleton']; + // Extra packages for a monorepo install + if (opts?.monorepo) { + packages.push('@sveltejs/adapter-vercel'); + packages.push('is-ci'); + } + + // Tailwind Packages + if (opts?.typography) packages.push('@tailwindcss/typography'); + if (opts?.forms) packages.push('@tailwindcss/forms'); + + // Component dependencies + if (opts?.codeblocks) packages.push('highlight.js'); + if (opts?.popups) packages.push('@floating-ui/dom'); + + let result = spawnSync(opts.packagemanager, ['add', '-D', ...packages], { + shell: true, + }); + + // Capture any errors from stderr and display for the user to report it to us + if (result?.stderr.toString().length) { + console.log( + red( + bold( + 'The following was reported to stderr - please read carefully to determine whether it actually affects your install:\n', + ), + ), + result?.stderr.toString(), + ); + } + + // Just to help with any user error reports + if (opts.verbose) { + const stdout = result?.stdout.toString(); + if (stdout.length) console.log(bold(cyan('stdout:')), stdout); + const stderr = result?.stderr.toString(); + if (stderr.length) console.log(bold(red('stderr:')), stderr); + } + + // write out config files + out('svelte.config.js', createSvelteConfig(opts)); + out('.vscode/settings.json', await createVSCodeSettings()); + out('tailwind.config.cjs', createTailwindConfig(opts)); + out('postcss.config.cjs', createPostCssConfig()); + + // Monorepo additions + if (opts?.monorepo) { + fs.copySync(__dirname + '../README-MONO.md', process.cwd() + '/README.md', { overwrite: true }); + mkdirp('scripts'); + fs.copySync(__dirname + './swapdeps.mjs', process.cwd() + '/scripts/swapdeps.mjs', { overwrite: true }); + let pkg = JSON.parse(fs.readFileSync('package.json')); + pkg.scripts['install'] = 'node ./scripts/swapdeps.mjs'; + pkg.scripts['dep'] = 'vercel build && vercel deploy --prebuilt'; + pkg.scripts['prod'] = 'vercel build --prod && vercel deploy --prebuilt --prod'; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2)); + } + // copy over selected template + copyTemplate(opts); + // creating the missing lib folder... + mkdirp(path.join('src', 'lib')); + // go back to starting location in case we get called again to create another template + process.chdir(startPath); + return opts; +} + +async function createVSCodeSettings() { + try { + mkdirp('.vscode'); + const data = await got('https://raw.githubusercontent.com/skeletonlabs/skeleton/master/scripts/tw-settings.json').text(); + return data; + } catch (error) { + console.error( + 'Unable to download settings file for VSCode, please read manual instructions at https://skeleton.dev/guides/install', + ); + } +} + +function createSvelteConfig(opts) { + // For some reason create-svelte will turn off preprocessing for jsdoc and no type checking + // this will break the using of all CSS preprocessing as well, which is undesirable. + // Here we will just return the typescript default setup + let str = ''; + if (opts?.monorepo) { + str += `import adapter from '@sveltejs/adapter-vercel';\n`; + } else { + str += `import adapter from '@sveltejs/adapter-auto';\n`; + } + str += `import { vitePreprocess } from '@sveltejs/kit/vite';`; + if (opts?.monorepo) { + str += `\nimport path from 'path';`; + } + str += ` +/** @type {import('@sveltejs/kit').Config} */ +const config = { + // Consult https://kit.svelte.dev/docs/integrations#preprocessors + // for more information about preprocessors + preprocess: vitePreprocess(), + ${ + opts?.inspector + ? ` + vitePlugin: { + inspector: true, + },` + : '' + } + kit: { + // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. + // If your environment is not supported or you settled on a specific environment, switch out the adapter. + // See https://kit.svelte.dev/docs/adapters for more information about adapters. + adapter: adapter() + } +}; +export default config;`; + return str; +} + +function createTailwindConfig(opts) { + let plugins = []; + let pluginImports = []; + + if (opts.forms == true) { + pluginImports.push(`import forms from '@tailwindcss/forms'`); + plugins.push(`forms`); + } + if (opts.typography == true) { + pluginImports.push(`import typography from '@tailwindcss/typography'`); + plugins.push(`typography`); + } + pluginImports.push(`import skeleton from '@skeletonlabs/skeleton/tailwind/skeleton.cjs'`); + plugins.push(`...skeleton()`); + + const str = `import { join } from 'path' +${pluginImports.join('\n')} + +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: 'class', + content: ['./src/**/*.{html,js,svelte,ts}', join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')], + theme: { + extend: {}, + }, + plugins: [${plugins.join(',')}], +} +`; + return str; +} + +function createPostCssConfig() { + const str = `module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}`; + return str; +} + +function copyTemplate(opts) { + const src = path.resolve(dist(opts.skeletontemplatedir), opts.skeletontemplate); + + fs.copySync(src + '/src', './src', { overwrite: true }); + fs.copySync(src + '/static', './static', { overwrite: true }); + + // All fonts are in the template static folder, so we need to remove the ones that are not relevant to the theme + // and then update the app.postcss file to include the correct font + let fontFamily = ''; + let fontFile = ''; + switch (opts.skeletontheme) { + case 'gold-nouveau': + case 'modern': + case 'seasonal': + fontFamily = 'Quicksand'; + fontFile = ['Quicksand.ttf']; + break; + case 'rocket': + fontFamily = 'Space Grotesk'; + fontFile = ['SpaceGrotesk.ttf']; + break; + case 'seafoam': + fontFamily = 'Playfair Display'; + fontFile = ['PlayfairDisplay-Italic.ttf']; + break; + case 'vintage': + fontFamily = 'Abril Fatface'; + fontFile = ['AbrilFatface.ttf']; + break; + default: + fontFamily = ''; + fontFile = ''; + } + if (fontFamily !== '') { + fs.appendFileSync( + './src/app.postcss', + ` +@font-face { + font-family: '${fontFamily}'; + src: url('/fonts/${fontFile}'); + font-display: swap; +}`, + ); + removeFilesExceptSync('./static/fonts/', fontFile); + } else { + fs.removeSync('./static/fonts'); + } + + // patch back in their theme choice - it may have been replaced by the theme template, it may still be the correct auto-genned one, depends on the template - we don't care, this fixes it. + let content = fs.readFileSync('./src/routes/+layout.svelte', { + encoding: 'utf8', + flag: 'r', + }); + const themeReg = /theme-.*\.css';$/gim; + content = content.replace(themeReg, `theme-${opts.skeletontheme}.css';`); + content = (opts.types === 'typescript' ? "`, + ); + } + + if (opts?.highlightjs) { + content = content.replace( + scriptEndReg, + ` + // Floating UI for Popups + import { computePosition, autoUpdate, flip, shift, offset, arrow } from '@floating-ui/dom'; + import { storePopup } from '@skeletonlabs/skeleton'; + storePopup.set({ computePosition, autoUpdate, flip, shift, offset, arrow }); +`, + ); + } + + fs.writeFileSync('./src/routes/+layout.svelte', content); + + // update the to have the data-theme + content = fs.readFileSync('./src/app.html', { + encoding: 'utf8', + flag: 'r', + }); + fs.writeFileSync( + './src/app.html', + content.replace('', ``), + ); +} + +function out(filename, data) { + if (data == undefined) return; + fs.writeFileSync(filename, data); +} diff --git a/packages/create-skeleton-app/src/index.js b/packages/create-skeleton-app/src/index.js new file mode 100755 index 00000000..851efde6 --- /dev/null +++ b/packages/create-skeleton-app/src/index.js @@ -0,0 +1,278 @@ +#!/usr/bin/env node +import { SkeletonOptions, createSkeleton } from './creator.js'; +import fs from 'fs-extra'; +import mri from 'mri'; +import { bold, cyan, gray, grey, red } from 'kleur/colors'; +import { intro, text, select, multiselect, spinner } from '@clack/prompts'; +import events from 'events'; +import { dist, getHelpText, goodbye } from './utils.js'; +import path from 'path'; +import semver from 'semver'; +// Minimum version required for Svelte Kit +const requiredVersion = '16.14.0'; + +async function main() { + if (semver.lt(process.version, requiredVersion)) { + console.error(`You need to be running Node ${requiredVersion} to use Svelte Kit`); + process.exit(1); + } + + // This is required to handle spawning processes + events.EventEmitter.defaultMaxListeners = 15; + + const startPath = process.cwd(); + // grab any passed arguments from the command line + let opts = await parseArgs(); + + if ('quiet' in opts) { + // in quiet mode we prefill the defaults, then overlay the passed options and bypass all of askForMissingParams so that it + // doesn't have to constantly check for quietmode all the time. + let defaults = new SkeletonOptions(); + opts = Object.assign(defaults, opts); + } else { + // in interactive mode we ask the user to fill anything not passed in + opts = await askForMissingParams(opts); + } + + // Now that we have all of the options, lets create it. + const s = spinner(); + s.start('Installing'); + await createSkeleton(opts); + s.stop('Done installing'); + // And give the user some final information on what to do Next + if (!opts?.quiet) { + const pm = opts.packagemanager; + let runString = `${pm} dev\n`; + + if (pm == 'npm') { + runString = 'npm run dev\n'; + } + let finalInstructions = bold(cyan(`\nDone! You can now:\n\n`)); + if (startPath != opts.path) { + finalInstructions += bold(cyan(`cd ${path.relative(startPath, opts.path)}\n`)); + } + finalInstructions += bold(cyan(runString)); + finalInstructions += grey(`Need some help or found an issue? Visit us on Discord https://discord.gg/EXqV7W8MtY`); + console.log(finalInstructions); + } + process.exit(); +} + +async function parseArgs() { + const argv = process.argv.slice(2); + + // mri will parse argv and expand any shorthand args. Accepted args are the literal props of SkelOptions + /** @type {SkeletonOptions} */ + const opts = mri(argv, { + alias: { + h: 'help', + n: 'name', + p: 'path', + t: 'skeletontheme', + m: 'monorepo', + q: 'quiet', + v: 'verbose', + }, + boolean: [ + 'help', + 'quiet', + 'monorepo', + 'skeletonui', + 'library', + 'prettier', + 'eslint', + 'playwright', + 'vitest', + 'inspector', + 'codeblocks', + 'popups', + 'forms', + 'typography', + 'verbose', + ], + }); + + // If a user invokes 'create-app blah foo', it falls into the _ catch all list, the best we can do is take the first one and use that as the name + // if args are passed in incorrectly such as --prettier=0 instead of --prettier=false then a 0 will be added to the _ collection, we check that the + // first one isn't a bungled arg set to 0 + if (opts._.length && opts._[0] != 0) { + opts.name = opts._[0]; + } + // Show help if specified regardless of how many other options are specified, have fun updating the text string in utils.ts :( + if ('help' in opts) { + console.log(getHelpText()); + process.exit(); + } + return opts; +} + +function checkIfDirSafeToInstall(path) { + // Check if the directory already exists. + if (!fs.existsSync(path)) return; + + //lets see whats in there + const conflicts = fs + .readdirSync(path) + .filter((file) => + /^(package.json|svelte.config.js|tailwind.config.cjs|pnpm-lock.yaml|postcss.config.cjs|vite.config.ts)$/.test(file), + ); + + if (conflicts.length > 0) { + console.log("create-skeleton-app doesn't support updating an existing project, it needs a new empty directory to install into"); + console.log(`The directory ${path} contains files that could conflict:`); + console.log(); + for (const file of conflicts) { + try { + const stats = fs.lstatSync(path + '/' + file); + if (stats.isDirectory()) { + console.log(` ${red(file)}/`); + } else { + console.log(` ${red(file)}`); + } + } catch { + console.log(` ${red(file)}`); + } + } + console.log('Either try using a new directory name, or remove the files listed above.'); + process.exit(1); + } +} +/** + * @param {SkeletonOptions} opts + */ +export async function askForMissingParams(opts) { + const { version } = JSON.parse(fs.readFileSync(dist('../package.json'), 'utf-8')); + + intro(`Create Skeleton App ${gray(`(version ${version})`)} + +${bold(cyan('Welcome to Skeleton 💀! A UI toolkit for Svelte + Tailwind'))} + +Problems? Open an issue on ${cyan('https://github.com/skeletonlabs/skeleton/issues')} if none exists already.`); + + //NOTE: When doing checks here, make sure to test for the presence of the prop, not the prop value as it may be set to false deliberately. + if (!('name' in opts)) { + opts.name = await text({ + message: 'Name for your new project:?', + placeholder: 'my-app', + validate(value) { + if (value.length === 0) return `App name is required!`; + }, + }); + goodbye(opts.name); + } + // test the path to make sure it is safe to install + if (opts.path === undefined) opts.path = process.cwd(); + opts.name = opts.name.replace(/\s+/g, '-').toLowerCase(); + opts.path = path.resolve(opts.path, opts.name); + checkIfDirSafeToInstall(opts.path); + + if (!('types' in opts)) { + opts.types = await select({ + message: 'Add type checking with TypeScript?', + options: [ + { value: 'typescript', label: 'Yes, using TypeScript syntax' }, + { value: 'checkjs', label: 'Yes, using JavaScript with JSDoc comments' }, + { value: null, label: 'No' }, + ], + }); + goodbye(opts.type); + } + + // Setup dev oriented packages and settings + if ( + !['eslint', 'prettier', 'playwright', 'vitest', 'inspector'].every((value) => { + return Object.keys(opts).includes(value); + }) + ) { + const optionalInstalls = await multiselect({ + message: 'What would you like setup in your project:', + // test opts for which values have been provided and prefill them + initialValues: ['eslint', 'prettier', 'playwright', 'vitest', 'inspector'].filter((value) => { + return Object.keys(opts).includes(value); + }), + options: [ + { value: 'eslint', label: 'Add ESLint for code linting?' }, + { value: 'prettier', label: 'Add Prettier for code formatting ?' }, + { value: 'playwright', label: 'Add Playwright for browser testing ?' }, + { value: 'vitest', label: 'Add Vitest for unit testing ?' }, + { value: 'inspector', label: 'Add Svelte Inspector for quick access to your source files from the browser ?' }, + ], + required: false, + }); + goodbye(optionalInstalls); + optionalInstalls.every((value) => (opts[value] = true)); + } + + // Additional packages to install + if ( + !['forms', 'typography', 'codeblocks', 'popups'].every((value) => { + return Object.keys(opts).includes(value); + }) + ) { + const packages = await multiselect({ + message: 'What other packages would you like to install:', + initialValues: ['forms', 'typography', 'codeblocks', 'popups'].filter((value) => { + return Object.keys(opts).includes(value); + }), + options: [ + { value: 'forms', label: 'Add Tailwind forms ?' }, + { value: 'typography', label: 'Add Tailwind typography ?' }, + { value: 'codeblocks', label: 'Add CodeBlock (installs highlight.js) ?' }, + { value: 'popups', label: 'Add Popups (installs floating-ui) ?' }, + ], + required: false, + }); + goodbye(packages); + packages.every((value) => (opts[value] = true)); + } + + // Skeleton Theme Selection + if (!('skeletontheme' in opts)) { + opts.skeletontheme = await select({ + message: 'Select a theme:', + options: [ + { label: 'Skeleton', value: 'skeleton' }, + { label: 'Modern', value: 'modern' }, + { label: 'Hamlindigo', value: 'hamlindigo' }, + { label: 'Rocket', value: 'rocket' }, + { label: 'Sahara', value: 'sahara' }, + { label: 'Gold Nouveau', value: 'gold-nouveau' }, + { label: 'Vintage', value: 'vintage' }, + { label: 'Seafoam', value: 'seafoam' }, + { label: 'Crimson', value: 'crimson' }, + ], + }); + goodbye(opts.skeletontheme); + } + + //Skeleton Template Selection + if (!('skeletontemplate' in opts)) { + // need to check whether a templatedir has been passed in (might be from a script in package.json pointing to real template projects) + const templateDir = opts.skeletontemplatedir || '../templates'; + let parsedChoices = []; + fs.readdirSync(dist(templateDir)).forEach((dir) => { + const meta_file = dist(`${templateDir}/${dir}/csa-meta.json`); + const { position, label, description, enabled } = JSON.parse(fs.readFileSync(meta_file, 'utf8')); + if (enabled) { + parsedChoices.push({ + position, + label, + description, + value: dir, + }); + } + }); + parsedChoices.sort((a, b) => a.position - b.position); + opts.skeletontemplate = await select({ + message: 'Which Skeleton app template?', + options: parsedChoices, + }); + goodbye(opts.skeletontemplate); + } + + const skelOpts = new SkeletonOptions(); + Object.assign(skelOpts, opts); + return skelOpts; +} + +main(); diff --git a/packages/create-skeleton-app/src/swapdeps.mjs b/packages/create-skeleton-app/src/swapdeps.mjs new file mode 100644 index 00000000..b3d36145 --- /dev/null +++ b/packages/create-skeleton-app/src/swapdeps.mjs @@ -0,0 +1,94 @@ +#!/usr/bin/env node +import isCI from 'is-ci'; +import { readFileSync, writeFileSync } from 'fs'; +import { execSync } from 'child_process'; + +// no it can't be run on preinstall +// no it can't be a nice little npm package +// yes it's running install twice +// yes it's a hack +// but it works (on Vercel at least) + +export function makeWorkspacePackageLinks(pkg) { + if (pkg?.deployConfig?.dependencies != undefined) { + for (const [dep, version] of Object.entries(pkg.deployConfig.dependencies)) { + pkg.dependencies[dep] = 'workspace:^'; + } + } + if (pkg?.deployConfig?.devDependencies != undefined) { + for (const [devDep, version] of Object.entries(pkg.deployConfig.devDependencies)) { + pkg.devDependencies[devDep] = 'workspace:^'; + } + } + if (pkg?.deployConfig?.peerDependencies != undefined) { + for (const [peerDep, version] of Object.entries(pkg.deployConfig.dependencies)) { + pkg.peerDependencies[peerDep] = 'workspace:^'; + } + } +} + +export function makeVersionedPackageLinks(pkg) { + let clean = true; + if (pkg?.deployConfig?.dependencies != undefined) { + for (const [dep, version] of Object.entries(pkg.deployConfig.dependencies)) { + if (pkg.dependencies[dep] !== version) { + pkg.dependencies[dep] = version; + clean = false; + } + } + } + if (pkg?.deployConfig?.devDependencies != undefined) { + for (const [devDep, version] of Object.entries(pkg?.deployConfig?.devDependencies)) { + if (pkg?.devDependencies[devDep] !== version) { + pkg.devDependencies[devDep] = version; + clean = false; + } + } + } + if (pkg?.deployConfig?.peerDependencies != undefined) { + for (const [peerDep, version] of Object.entries(pkg?.deployConfig?.devDependencies)) { + if (pkg?.peerDependencies[peerDep] !== version) { + pkg.peerDependencies[peerDep] = version; + clean = false; + } + } + } + return { pkg: pkg, clean: clean }; +} + +export function swapdeps() { + let pkg = JSON.parse(readFileSync('./package.json', 'utf8')); + let clean = true; + + switch (process.argv.slice(2)[0]) { + case 'workspace': + console.log('Setting dependencies to workspace:^'); + makeWorkspacePackageLinks(pkg); + break; + case 'versioned': + console.log('Setting dependencies to versioned'); + makeVersionedPackageLinks(pkg); + break; + case '-h': + case 'h': + case '--help': + case 'help': + console.log( + 'swapdeps [workspace|versioned] or no args for auto-change to versioned if in a CI environment or workspace links if not', + ); + break; + default: + if (isCI) { + ({ pkg, clean } = makeVersionedPackageLinks(pkg)); + } else { + console.log('No CI detected, setting dependencies to workspace:^'); + makeWorkspacePackageLinks(pkg); + } + } + writeFileSync('./package.json', JSON.stringify(pkg, null, 2), 'utf8'); + if (clean === false) { + execSync('pnpm install --no-frozen-lockfile'); + } +} + +swapdeps(); diff --git a/packages/create-skeleton-app/src/utils.js b/packages/create-skeleton-app/src/utils.js new file mode 100644 index 00000000..d2ff4bf8 --- /dev/null +++ b/packages/create-skeleton-app/src/utils.js @@ -0,0 +1,94 @@ +import { fileURLToPath } from 'url'; +import { cancel, isCancel } from '@clack/prompts'; +import path from 'path'; +import fs from 'fs-extra'; + +export function whichPMRuns() { + const userAgent = process.env.npm_config_user_agent; + if (!userAgent) { + return undefined; + } + const pmSpec = userAgent.split(' ')[0] || ''; + const separatorPos = pmSpec.lastIndexOf('/'); + const name = pmSpec?.substring(0, separatorPos); + return { + name: name === 'npminstall' ? 'cnpm' : name, + version: pmSpec?.substring(separatorPos + 1), + }; +} + +/** @param {string} dir */ +export function mkdirp(dir) { + try { + fs.mkdirSync(dir, { recursive: true }); + } catch (e) { + if (e.code === 'EEXIST') return; + throw e; + } +} + +export function dist(pathToFind) { + let pathAdjust = ''; + let base = fileURLToPath(new URL(`./`, import.meta.url).href); + if (base.endsWith('shared', base.length - 1)) { + pathAdjust = '../'; + } + + const res = path.resolve(base, pathAdjust, pathToFind); + return res; +} + +export function removeFilesExceptSync(directoryPath, filesToKeep) { + const files = fs.readdirSync(directoryPath); + const filesToRemove = files.filter((file) => !filesToKeep.includes(file)); + for (const file of filesToRemove) { + const filePath = path.join(directoryPath, file); + fs.removeSync(filePath); + } +} + +export function goodbye(option) { + if (isCancel(option)) { + cancel('Install cancelled, nothing written to disk'); + process.exit(0); + } +} + +export function getHelpText() { + // Must use spaces for adjustments as output can get very wonky with tab output + // Why not array of arrays, TBH it's more readable in source like this and easy to edit with column selection etc. + // But the advantage would be that padEnd could be adjusted to the console.width... will wait for feedback. + return ` +Option Short Quiet Default Values Description +--help -h This help screen +--quiet -q Quiet mode - see below +--verbose -v Show shell output for troubleshooting +--name -n new-skel-app string, no spaces Name of the directory for the project +--types typescript typescript|checkjs TypeScript or JavaScript with JSDoc +--prettier true true|false Whether Prettier is added +--eslint true true|false Whether ESLint is added +--playwright false true|false Whether Playwright is added +--vitest false true|false Whether Vitest is added +--codeblocks false true|false Install codeblock optional dependencies +--popups true true|false Install popups dependencies +--path -p '' relative or absolute path Location to install, name is appended +--forms false true|false Add Tailwinds Forms plugin +--typography false true|false Add Tailwinds Typography plugin +--skeletontheme -t skeleton skeleton Choose one for the Skeleton theme + modern + hamlindigo + rocket + sahara + gold-nouveau + vintage + seafoam + crimson +--skeletontemplate bare bare The Skeleton template to use + welcome + +Quiet mode is for automated installs for testing, CI/CD. It will take all of the default values in the +Quiet Default column, but you can provide any other flags to override as you see fit. If you just want +to generate a new project but still ask for a name, you need to provide all the other args except the +ones to be filled in by the user. +`; +} diff --git a/packages/create-skeleton-app/templates/bare/csa-meta.json b/packages/create-skeleton-app/templates/bare/csa-meta.json new file mode 100644 index 00000000..8828c1ff --- /dev/null +++ b/packages/create-skeleton-app/templates/bare/csa-meta.json @@ -0,0 +1,6 @@ +{ + "position": 5, + "label": "Bare Bones", + "description": "A blank slate for you to create your app", + "enabled": true +} diff --git a/packages/create-skeleton-app/templates/bare/src/app.d.ts b/packages/create-skeleton-app/templates/bare/src/app.d.ts new file mode 100644 index 00000000..8f4d6389 --- /dev/null +++ b/packages/create-skeleton-app/templates/bare/src/app.d.ts @@ -0,0 +1,9 @@ +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +// and what to do when importing types +declare namespace App { + // interface Locals {} + // interface PageData {} + // interface Error {} + // interface Platform {} +} diff --git a/packages/create-skeleton-app/templates/bare/src/app.html b/packages/create-skeleton-app/templates/bare/src/app.html new file mode 100644 index 00000000..77e65f20 --- /dev/null +++ b/packages/create-skeleton-app/templates/bare/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/create-skeleton-app/templates/bare/src/app.postcss b/packages/create-skeleton-app/templates/bare/src/app.postcss new file mode 100644 index 00000000..a9c67238 --- /dev/null +++ b/packages/create-skeleton-app/templates/bare/src/app.postcss @@ -0,0 +1,5 @@ +/*place global styles here */ +html, +body { + @apply h-full; +} diff --git a/packages/create-skeleton-app/templates/bare/src/routes/+layout.svelte b/packages/create-skeleton-app/templates/bare/src/routes/+layout.svelte new file mode 100644 index 00000000..3a331d8a --- /dev/null +++ b/packages/create-skeleton-app/templates/bare/src/routes/+layout.svelte @@ -0,0 +1,10 @@ + + + diff --git a/packages/create-skeleton-app/templates/bare/src/routes/+page.svelte b/packages/create-skeleton-app/templates/bare/src/routes/+page.svelte new file mode 100644 index 00000000..b856d97f --- /dev/null +++ b/packages/create-skeleton-app/templates/bare/src/routes/+page.svelte @@ -0,0 +1,13 @@ + + +
+
+

Let's get cracking bones!

+

Start by exploring:

+
    +
  • /src/routes/+layout.svelte - barebones layout, the CSS import order is critical!
  • +
  • /src/app.postcss - minimal css to make the page full screen, may not be relevant for your project
  • +
  • /src/routes/+page.svelte - this page, you can replace the contents
  • +
+
+
diff --git a/packages/create-skeleton-app/templates/bare/static/favicon.png b/packages/create-skeleton-app/templates/bare/static/favicon.png new file mode 100644 index 00000000..c4e3735c Binary files /dev/null and b/packages/create-skeleton-app/templates/bare/static/favicon.png differ diff --git a/packages/create-skeleton-app/templates/bare/static/fonts/AbrilFatface.ttf b/packages/create-skeleton-app/templates/bare/static/fonts/AbrilFatface.ttf new file mode 100644 index 00000000..a2917114 Binary files /dev/null and b/packages/create-skeleton-app/templates/bare/static/fonts/AbrilFatface.ttf differ diff --git a/packages/create-skeleton-app/templates/bare/static/fonts/PlayfairDisplay-Italic.ttf b/packages/create-skeleton-app/templates/bare/static/fonts/PlayfairDisplay-Italic.ttf new file mode 100644 index 00000000..f5c5f067 Binary files /dev/null and b/packages/create-skeleton-app/templates/bare/static/fonts/PlayfairDisplay-Italic.ttf differ diff --git a/packages/create-skeleton-app/templates/bare/static/fonts/Quicksand.ttf b/packages/create-skeleton-app/templates/bare/static/fonts/Quicksand.ttf new file mode 100644 index 00000000..0ec22199 Binary files /dev/null and b/packages/create-skeleton-app/templates/bare/static/fonts/Quicksand.ttf differ diff --git a/packages/create-skeleton-app/templates/bare/static/fonts/SpaceGrotesk.ttf b/packages/create-skeleton-app/templates/bare/static/fonts/SpaceGrotesk.ttf new file mode 100644 index 00000000..cf0b5034 Binary files /dev/null and b/packages/create-skeleton-app/templates/bare/static/fonts/SpaceGrotesk.ttf differ diff --git a/packages/create-skeleton-app/templates/welcome/csa-meta.json b/packages/create-skeleton-app/templates/welcome/csa-meta.json new file mode 100644 index 00000000..1580cee2 --- /dev/null +++ b/packages/create-skeleton-app/templates/welcome/csa-meta.json @@ -0,0 +1,6 @@ +{ + "position": 10, + "label": "Skeleton Welcome", + "description": "A single page to welcome you to Skeleton", + "enabled": true +} diff --git a/packages/create-skeleton-app/templates/welcome/src/app.d.ts b/packages/create-skeleton-app/templates/welcome/src/app.d.ts new file mode 100644 index 00000000..8f4d6389 --- /dev/null +++ b/packages/create-skeleton-app/templates/welcome/src/app.d.ts @@ -0,0 +1,9 @@ +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +// and what to do when importing types +declare namespace App { + // interface Locals {} + // interface PageData {} + // interface Error {} + // interface Platform {} +} diff --git a/packages/create-skeleton-app/templates/welcome/src/app.html b/packages/create-skeleton-app/templates/welcome/src/app.html new file mode 100644 index 00000000..423dbd3c --- /dev/null +++ b/packages/create-skeleton-app/templates/welcome/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/create-skeleton-app/templates/welcome/src/app.postcss b/packages/create-skeleton-app/templates/welcome/src/app.postcss new file mode 100644 index 00000000..ce158688 --- /dev/null +++ b/packages/create-skeleton-app/templates/welcome/src/app.postcss @@ -0,0 +1,5 @@ +/*place global styles here */ +html, +body { + @apply h-full overflow-hidden; +} diff --git a/packages/create-skeleton-app/templates/welcome/src/routes/+layout.svelte b/packages/create-skeleton-app/templates/welcome/src/routes/+layout.svelte new file mode 100644 index 00000000..e9f609c8 --- /dev/null +++ b/packages/create-skeleton-app/templates/welcome/src/routes/+layout.svelte @@ -0,0 +1,49 @@ + + + + + + + + + Skeleton + + + + Discord + + + Twitter + + + GitHub + + + + + + + diff --git a/packages/create-skeleton-app/templates/welcome/src/routes/+page.svelte b/packages/create-skeleton-app/templates/welcome/src/routes/+page.svelte new file mode 100644 index 00000000..67c03533 --- /dev/null +++ b/packages/create-skeleton-app/templates/welcome/src/routes/+page.svelte @@ -0,0 +1,71 @@ + + +
+
+

Welcome to Skeleton.

+ +
+
+ + + +
+ + +
+

Try editing the following:

+

/src/routes/+layout.svelte

+

/src/routes/+page.svelte

+
+
+
+ + diff --git a/packages/create-skeleton-app/templates/welcome/static/favicon.png b/packages/create-skeleton-app/templates/welcome/static/favicon.png new file mode 100644 index 00000000..c4e3735c Binary files /dev/null and b/packages/create-skeleton-app/templates/welcome/static/favicon.png differ diff --git a/packages/create-skeleton-app/templates/welcome/static/fonts/AbrilFatface.ttf b/packages/create-skeleton-app/templates/welcome/static/fonts/AbrilFatface.ttf new file mode 100644 index 00000000..a2917114 Binary files /dev/null and b/packages/create-skeleton-app/templates/welcome/static/fonts/AbrilFatface.ttf differ diff --git a/packages/create-skeleton-app/templates/welcome/static/fonts/PlayfairDisplay-Italic.ttf b/packages/create-skeleton-app/templates/welcome/static/fonts/PlayfairDisplay-Italic.ttf new file mode 100644 index 00000000..f5c5f067 Binary files /dev/null and b/packages/create-skeleton-app/templates/welcome/static/fonts/PlayfairDisplay-Italic.ttf differ diff --git a/packages/create-skeleton-app/templates/welcome/static/fonts/Quicksand.ttf b/packages/create-skeleton-app/templates/welcome/static/fonts/Quicksand.ttf new file mode 100644 index 00000000..0ec22199 Binary files /dev/null and b/packages/create-skeleton-app/templates/welcome/static/fonts/Quicksand.ttf differ diff --git a/packages/create-skeleton-app/templates/welcome/static/fonts/SpaceGrotesk.ttf b/packages/create-skeleton-app/templates/welcome/static/fonts/SpaceGrotesk.ttf new file mode 100644 index 00000000..cf0b5034 Binary files /dev/null and b/packages/create-skeleton-app/templates/welcome/static/fonts/SpaceGrotesk.ttf differ diff --git a/packages/skeleton/.eslintrc.cjs b/packages/skeleton/.eslintrc.cjs index e445f1f2..69bbd18c 100644 --- a/packages/skeleton/.eslintrc.cjs +++ b/packages/skeleton/.eslintrc.cjs @@ -3,8 +3,11 @@ module.exports = { parser: '@typescript-eslint/parser', extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], plugins: ['svelte3', '@typescript-eslint'], - ignorePatterns: ['*.cjs'], - overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], + ignorePatterns: ['*.cjs', '.temp/**/*'], + overrides: [ + { files: ['*.svelte'], processor: 'svelte3/svelte3' }, + { files: ['*.test.ts'], rules: { '@typescript-eslint/no-restricted-imports': ['off'], 'no-restricted-imports': ['off'] } } + ], settings: { 'svelte3/typescript': () => require('typescript') }, @@ -22,6 +25,9 @@ module.exports = { '@typescript-eslint/no-restricted-imports': [ 'error', { patterns: [{ group: ['$lib/*', '$lib', '!./*', '!../*'], message: 'Please only use RELATIVE import paths instead.' }] } - ] + ], + + 'no-empty-function': 'off', + '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }] } }; diff --git a/packages/skeleton/.prettierignore b/packages/skeleton/.prettierignore index d8762e9b..65db2568 100644 --- a/packages/skeleton/.prettierignore +++ b/packages/skeleton/.prettierignore @@ -11,4 +11,7 @@ pnpm-lock.yaml .vscode .github /static/font-awesome -/static/fonts \ No newline at end of file +/static/fonts +/.temp +/dist +/scripts/tw-settings.json diff --git a/packages/skeleton/package.json b/packages/skeleton/package.json index 73121379..a9ce9b40 100644 --- a/packages/skeleton/package.json +++ b/packages/skeleton/package.json @@ -125,4 +125,4 @@ ] } } -} \ No newline at end of file +} diff --git a/packages/skeleton/scripts/tw-settings.json b/packages/skeleton/scripts/tw-settings.json index 3ca895ab..18d0e879 100644 --- a/packages/skeleton/scripts/tw-settings.json +++ b/packages/skeleton/scripts/tw-settings.json @@ -1,7 +1,5 @@ { - "prettier.documentSelectors": [ - "**/*.svelte" - ], + "prettier.documentSelectors": ["**/*.svelte"], "tailwindCSS.classAttributes": [ "class", "accent", @@ -100,4 +98,4 @@ "width", "zIndex" ] -} \ No newline at end of file +} diff --git a/packages/skeleton/src/lib/components/AppRail/AppRailTile.test.ts b/packages/skeleton/src/lib/components/AppRail/AppRailTile.test.ts index d021367a..6e363ea0 100644 --- a/packages/skeleton/src/lib/components/AppRail/AppRailTile.test.ts +++ b/packages/skeleton/src/lib/components/AppRail/AppRailTile.test.ts @@ -20,7 +20,9 @@ describe('AppRailTile.svelte', () => { regionLabel: 'TestAppRailTile', selected: readable('/'), active: 'bg-primary-500', - hover: 'bg-primary-500' + hover: 'bg-primary-500', + group: 'testGroup', + name: 'test' } }); expect(getByTestId('app-rail-tile')).toBeTruthy(); @@ -29,7 +31,10 @@ describe('AppRailTile.svelte', () => { it('Overrides tag when href is passed', async () => { const { getByTestId } = render(AppRailTile, { props: { - href: '/about' + href: '/about', + group: 'testGroup', + name: 'test tile', + value: 'some value' } }); expect(getByTestId('app-rail-tile').querySelector('a')).toBeTruthy(); diff --git a/packages/skeleton/src/lib/components/Avatar/Avatar.svelte b/packages/skeleton/src/lib/components/Avatar/Avatar.svelte index 83585117..1d714a7b 100644 --- a/packages/skeleton/src/lib/components/Avatar/Avatar.svelte +++ b/packages/skeleton/src/lib/components/Avatar/Avatar.svelte @@ -1,6 +1,7 @@