chore: add changesets (#1556)

* added scripts and deps

* added version script for dev tag release

* added action scripts

* ignore dist and .temp files

* added changeset config

* format + lint

* dont need that

* simple cache

* reverting back, this cache was more consistent

* changed names

* repo check

* ignore empty arrow functions

* fixed lint errors

* added action to lint on PRs

* added CSA

* lockfile

* update tw-settings.json after publish

* ignore tw-settings.json in prettier

* weird spacing that was breaking the ingore

* added ignore path

* ignore .vercel dir during formatting/linting

* fixed line dupe on format

* fix linting errors

* fixed svelte check errors

* added VERCEL_ENV for svelte-check

* run both lint and check in parallel
This commit is contained in:
CokaKoala
2023-05-25 13:17:31 -04:00
committed by GitHub
parent cc2a472552
commit a521d89fd1
63 changed files with 3844 additions and 43 deletions

14
.changeset/config.json Normal file
View File

@@ -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": []
}

75
.github/workflows/ci.yml vendored Normal file
View File

@@ -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

60
.github/workflows/release-dev.yml vendored Normal file
View File

@@ -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 }}

70
.github/workflows/release.yml vendored Normal file
View File

@@ -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

1
.gitignore vendored
View File

@@ -13,6 +13,7 @@ src/lib/tailwind/generated
vite.config.ts.timestamp-**.mjs vite.config.ts.timestamp-**.mjs
/packages/* /packages/*
!/packages/create-skeleton-app
!/packages/skeleton !/packages/skeleton
/sites/* /sites/*
!/sites/skeleton.dev !/sites/skeleton.dev

View File

@@ -10,7 +10,14 @@
"postinstall": "pnpm -r sync", "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", "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", "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", "license": "MIT",
"homepage": "https://skeleton.dev/", "homepage": "https://skeleton.dev/",
@@ -36,6 +43,8 @@
"sveltekit" "sveltekit"
], ],
"devDependencies": { "devDependencies": {
"@changesets/cli": "^2.26.1",
"@svitejs/changesets-changelog-github-compact": "^1.1.0",
"cspell": "^6.31.1", "cspell": "^6.31.1",
"shelljs": "^0.8.5" "shelljs": "^0.8.5"
}, },

View File

@@ -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,
},
};

View File

@@ -0,0 +1,5 @@
.DS_Store
node_modules
dist
package
.turbo

View File

@@ -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

View File

@@ -0,0 +1,8 @@
{
"tabWidth": 4,
"useTabs": true,
"semi": true,
"singleQuote": true,
"printWidth": 140,
"trailingComma": "all"
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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 <foo>`, 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

View File

@@ -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)

View File

@@ -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 <admin@skeletonlabs.co>",
"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"
}
}

View File

@@ -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

View File

@@ -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' ? "<script lang='ts'>" : '<script>') + content.substring(content.indexOf('\n'));
const scriptEndReg = /<\/script>/g;
if (opts?.highlightjs) {
content = content.replace(
scriptEndReg,
`
// Highlight JS
import hljs from 'highlight.js';
import 'highlight.js/styles/github-dark.css';
import { storeHighlightJs } from '@skeletonlabs/skeleton';
storeHighlightJs.set(hljs);
</script>`,
);
}
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 });
</script>`,
);
}
fs.writeFileSync('./src/routes/+layout.svelte', content);
// update the <body> to have the data-theme
content = fs.readFileSync('./src/app.html', {
encoding: 'utf8',
flag: 'r',
});
fs.writeFileSync(
'./src/app.html',
content.replace('<body>', `<body data-sveltekit-preload-data="hover" data-theme="${opts.skeletontheme}">`),
);
}
function out(filename, data) {
if (data == undefined) return;
fs.writeFileSync(filename, data);
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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.
`;
}

View File

@@ -0,0 +1,6 @@
{
"position": 5,
"label": "Bare Bones",
"description": "A blank slate for you to create your app",
"enabled": true
}

View File

@@ -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 {}
}

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,5 @@
/*place global styles here */
html,
body {
@apply h-full;
}

View File

@@ -0,0 +1,10 @@
<script>
// The ordering of these imports is critical to your app working properly
import '@skeletonlabs/skeleton/themes/theme-skeleton.css';
// If you have source.organizeImports set to true in VSCode, then it will auto change this ordering
import '@skeletonlabs/skeleton/styles/skeleton.css';
// Most of your app wide CSS should be put in this file
import '../app.postcss';
</script>
<slot />

View File

@@ -0,0 +1,13 @@
<!-- YOU CAN DELETE EVERYTHING IN THIS PAGE -->
<div class="container h-full mx-auto flex justify-center items-center">
<div class="space-y-5">
<h1 class="h1">Let's get cracking bones!</h1>
<p>Start by exploring:</p>
<ul>
<li><code class="code">/src/routes/+layout.svelte</code> - barebones layout, the CSS import order is critical!</li>
<li><code class="code">/src/app.postcss</code> - minimal css to make the page full screen, may not be relevant for your project</li>
<li><code class="code">/src/routes/+page.svelte</code> - this page, you can replace the contents</li>
</ul>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,6 @@
{
"position": 10,
"label": "Skeleton Welcome",
"description": "A single page to welcome you to Skeleton",
"enabled": true
}

View File

@@ -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 {}
}

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div style="display: contents" class="h-full overflow-hidden">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,5 @@
/*place global styles here */
html,
body {
@apply h-full overflow-hidden;
}

View File

@@ -0,0 +1,49 @@
<script>
// The ordering of these imports is critical to your app working properly
import '@skeletonlabs/skeleton/themes/theme-skeleton.css';
// If you have source.organizeImports set to true in VSCode, then it will auto change this ordering
import '@skeletonlabs/skeleton/styles/skeleton.css';
// Most of your app wide CSS should be put in this file
import '../app.postcss';
import { AppShell, AppBar } from '@skeletonlabs/skeleton';
</script>
<!-- App Shell -->
<AppShell>
<svelte:fragment slot="header">
<!-- App Bar -->
<AppBar>
<svelte:fragment slot="lead">
<strong class="text-xl uppercase">Skeleton</strong>
</svelte:fragment>
<svelte:fragment slot="trail">
<a
class="btn btn-sm variant-ghost-surface"
href="https://discord.gg/EXqV7W8MtY"
target="_blank"
rel="noreferrer"
>
Discord
</a>
<a
class="btn btn-sm variant-ghost-surface"
href="https://twitter.com/SkeletonUI"
target="_blank"
rel="noreferrer"
>
Twitter
</a>
<a
class="btn btn-sm variant-ghost-surface"
href="https://github.com/skeletonlabs/skeleton"
target="_blank"
rel="noreferrer"
>
GitHub
</a>
</svelte:fragment>
</AppBar>
</svelte:fragment>
<!-- Page Route Content -->
<slot />
</AppShell>

View File

@@ -0,0 +1,71 @@
<!-- YOU CAN DELETE EVERYTHING IN THIS PAGE -->
<div class="container h-full mx-auto flex justify-center items-center">
<div class="space-y-10 text-center flex flex-col items-center">
<h2 class="h2">Welcome to Skeleton.</h2>
<!-- Animated Logo -->
<figure>
<section class="img-bg" />
<svg
class="fill-token -scale-x-[100%]"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 200"
>
<path
fill-rule="evenodd"
d="M98.77 50.95c25.1 0 46.54 8.7 61.86 23a41.34 41.34 0 0 0 5.19-1.93c4.35-2.02 10.06-6.17 17.13-12.43-1.15 10.91-2.38 18.93-3.7 24.04-.7 2.75-1.8 6.08-3.3 10a80.04 80.04 0 0 1 8.42 23.33c6.04 30.3-4.3 43.7-28.33 51.18.18.9.32 1.87.42 2.9.86 8.87-3.62 23.19-9 23.19-3.54 0-5.84-4.93-8.3-12.13-.78 8.34-4.58 17.9-8.98 17.9-4.73 0-7.25-8.84-10.93-20.13a214 214 0 0 1-.64 2.93l-.16.71-.16.71-.17.71c-1.84 7.58-4.46 15.07-8.5 15.07-5.06 0-2.29-15.9-10.8-22.63-43.14 2.36-79.43-13.6-79.43-59.62 0-8.48 2-16.76 5.69-24.45a93.72 93.72 0 0 1-1.77-3.68c-2.87-6.32-6.3-15.88-10.31-28.7 10.26 7.66 18.12 12.22 23.6 13.68.5.14 1.02.26 1.57.36 14.36-14.44 35.88-24.01 60.6-24.01Zm-9.99 62.3c-14.57 0-26.39 11.45-26.39 25.58 0 14.14 11.82 25.6 26.39 25.6s26.39-11.46 26.39-25.6c0-13.99-11.58-25.35-25.95-25.58Zm37.45 31.95c-4.4 0-6.73 9.4-6.73 13.62 0 3.3 1.1 5.12 2.9 5.45 4.39.4 3.05-5.97 5.23-5.97 1.06 0 2.2 1.35 3.34 2.73l.34.42c1.25 1.52 2.5 2.93 3.64 2.49 2.7-1.61 1.67-5.12.74-7.88-3.3-6.96-5.05-10.86-9.46-10.86Zm-36.85-28.45c12.57 0 22.76 9.78 22.76 21.85 0 12.07-10.2 21.85-22.76 21.85-.77 0-1.53-.04-2.29-.11 11.5-1.1 20.46-10.42 20.46-21.74 0-11.32-8.97-20.63-20.46-21.74.76-.07 1.52-.1 2.3-.1Zm65.54-5c-10.04 0-18.18 10.06-18.18 22.47 0 12.4 8.14 22.47 18.18 22.47s18.18-10.06 18.18-22.47c0-12.41-8.14-22.48-18.18-22.48Zm.6 3.62c8.38 0 15.16 8.4 15.16 18.74 0 10.35-6.78 18.74-15.16 18.74-.77 0-1.54-.07-2.28-.21 7.3-1.36 12.89-9.14 12.89-18.53 0-9.4-5.6-17.17-12.89-18.53.74-.14 1.5-.2 2.28-.2Zm3.34-72.27.12.07c.58.38.75 1.16.37 1.74l-2.99 4.6c-.35.55-1.05.73-1.61.44l-.12-.07a1.26 1.26 0 0 1-.37-1.74l2.98-4.6a1.26 1.26 0 0 1 1.62-.44ZM39.66 42l.08.1 2.76 3.93a1.26 1.26 0 0 1-2.06 1.45l-2.76-3.94A1.26 1.26 0 0 1 39.66 42Zm63.28-42 2.85 24.13 10.62-11.94.28 29.72-2.1-.47a77.8 77.8 0 0 0-16.72-2.04c-4.96 0-9.61.67-13.96 2l-2.34.73L83.5 4.96l9.72 18.37L102.94 0Zm-1.87 13.39-7.5 17.96-7.3-13.8-1.03 19.93.22-.06a51.56 51.56 0 0 1 12.1-1.45h.31c4.58 0 9.58.54 15 1.61l.35.07-.15-16.54-9.79 11-2.21-18.72Zm38.86 19.23c.67.2 1.05.89.86 1.56l-.38 1.32c-.17.62-.8 1-1.42.89l-.13-.03a1.26 1.26 0 0 1-.86-1.56l.38-1.32c.19-.66.88-1.05 1.55-.86ZM63.95 31.1l.05.12.7 2.17a1.26 1.26 0 0 1-2.34.9l-.04-.12-.71-2.17a1.26 1.26 0 0 1 2.34-.9Z"
/>
</svg>
</figure>
<!-- / -->
<div class="flex justify-center space-x-2">
<a
class="btn variant-filled"
href="https://skeleton.dev/"
target="_blank"
rel="noreferrer"
>
Launch Documentation
</a>
</div>
<div class="space-y-2">
<p>Try editing the following:</p>
<p><code class="code">/src/routes/+layout.svelte</code></p>
<p><code class="code">/src/routes/+page.svelte</code></p>
</div>
</div>
</div>
<style lang="postcss">
figure {
@apply flex relative flex-col;
}
figure svg,
.img-bg {
@apply w-64 h-64 md:w-80 md:h-80;
}
.img-bg {
@apply absolute z-[-1] rounded-full blur-[50px] transition-all;
animation: pulse 5s cubic-bezier(0, 0, 0, 0.5) infinite,
glow 5s linear infinite;
}
@keyframes glow {
0% {
@apply bg-primary-400/50;
}
33% {
@apply bg-secondary-400/50;
}
66% {
@apply bg-tertiary-400/50;
}
100% {
@apply bg-primary-400/50;
}
}
@keyframes pulse {
50% {
transform: scale(1.5);
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -3,8 +3,11 @@ module.exports = {
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['svelte3', '@typescript-eslint'], plugins: ['svelte3', '@typescript-eslint'],
ignorePatterns: ['*.cjs'], ignorePatterns: ['*.cjs', '.temp/**/*'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], overrides: [
{ files: ['*.svelte'], processor: 'svelte3/svelte3' },
{ files: ['*.test.ts'], rules: { '@typescript-eslint/no-restricted-imports': ['off'], 'no-restricted-imports': ['off'] } }
],
settings: { settings: {
'svelte3/typescript': () => require('typescript') 'svelte3/typescript': () => require('typescript')
}, },
@@ -22,6 +25,9 @@ module.exports = {
'@typescript-eslint/no-restricted-imports': [ '@typescript-eslint/no-restricted-imports': [
'error', 'error',
{ patterns: [{ group: ['$lib/*', '$lib', '!./*', '!../*'], message: 'Please only use RELATIVE import paths instead.' }] } { patterns: [{ group: ['$lib/*', '$lib', '!./*', '!../*'], message: 'Please only use RELATIVE import paths instead.' }] }
] ],
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }]
} }
}; };

View File

@@ -12,3 +12,6 @@ pnpm-lock.yaml
.github .github
/static/font-awesome /static/font-awesome
/static/fonts /static/fonts
/.temp
/dist
/scripts/tw-settings.json

View File

@@ -1,7 +1,5 @@
{ {
"prettier.documentSelectors": [ "prettier.documentSelectors": ["**/*.svelte"],
"**/*.svelte"
],
"tailwindCSS.classAttributes": [ "tailwindCSS.classAttributes": [
"class", "class",
"accent", "accent",

View File

@@ -20,7 +20,9 @@ describe('AppRailTile.svelte', () => {
regionLabel: 'TestAppRailTile', regionLabel: 'TestAppRailTile',
selected: readable('/'), selected: readable('/'),
active: 'bg-primary-500', active: 'bg-primary-500',
hover: 'bg-primary-500' hover: 'bg-primary-500',
group: 'testGroup',
name: 'test'
} }
}); });
expect(getByTestId('app-rail-tile')).toBeTruthy(); expect(getByTestId('app-rail-tile')).toBeTruthy();
@@ -29,7 +31,10 @@ describe('AppRailTile.svelte', () => {
it('Overrides tag when href is passed', async () => { it('Overrides tag when href is passed', async () => {
const { getByTestId } = render(AppRailTile, { const { getByTestId } = render(AppRailTile, {
props: { props: {
href: '/about' href: '/about',
group: 'testGroup',
name: 'test tile',
value: 'some value'
} }
}); });
expect(getByTestId('app-rail-tile').querySelector('a')).toBeTruthy(); expect(getByTestId('app-rail-tile').querySelector('a')).toBeTruthy();

View File

@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
// Types // Types
import type { CssClasses } from '../..'; import type { CssClasses } from '../..';
import type { Action } from 'svelte/action';
// Props (initials) // Props (initials)
/** Initials only - Provide up to two text characters. */ /** Initials only - Provide up to two text characters. */
@@ -15,9 +16,8 @@
export let fallback = ''; export let fallback = '';
/** /**
* Image only. Provide an Svelte action reference, such as `filter`. * Image only. Provide an Svelte action reference, such as `filter`.
* @type {function}
*/ */
export let action: any = () => {}; export let action: Action = () => {};
/** Image only. Provide Svelte action params, such as Apollo. */ /** Image only. Provide Svelte action params, such as Apollo. */
export let actionParams = ''; export let actionParams = '';
@@ -43,7 +43,7 @@
$: classesBase = `${cBase} ${background} ${width} ${border} ${rounded} ${shadow} ${cursor} ${$$props.class ?? ''}`; $: classesBase = `${cBase} ${background} ${width} ${border} ${rounded} ${shadow} ${cursor} ${$$props.class ?? ''}`;
// Utility Functions // Utility Functions
function prunedRestProps(): any { function prunedRestProps() {
delete $$restProps.class; delete $$restProps.class;
return $$restProps; return $$restProps;
} }

View File

@@ -84,7 +84,7 @@
// Return onDestroy handler that will remove the event listener from the external form // Return onDestroy handler that will remove the event listener from the external form
return () => { return () => {
externalForm.removeEventListener('reset', resetFormHandler); externalForm.removeEventListener('reset', resetFormHandler);
} };
}); });
function onInputHandler(): void { function onInputHandler(): void {

View File

@@ -18,7 +18,7 @@
*/ */
export let value: any; export let value: any;
/** Set the hover title. */ /** Set the hover title. */
export let title: string = ''; export let title = '';
// Props (A11y) // Props (A11y)
/** Defines a semantic ARIA label. */ /** Defines a semantic ARIA label. */
@@ -33,8 +33,8 @@
export let fill: CssClasses = getContext('fill'); export let fill: CssClasses = getContext('fill');
// Classes // Classes
const cBase: string = 'flex-auto text-base text-center cursor-pointer'; const cBase = 'flex-auto text-base text-center cursor-pointer';
const cDisabled: string = 'opacity-50 cursor-not-allowed'; const cDisabled = 'opacity-50 cursor-not-allowed';
// Local // Local
let elemInput: HTMLElement; let elemInput: HTMLElement;

View File

@@ -5,7 +5,7 @@ import { writable, type Writable } from 'svelte/store';
import Step from '$lib/components/Stepper/Step.svelte'; import Step from '$lib/components/Stepper/Step.svelte';
let mockState: Writable<any> = writable({ current: 1, total: 1 }); // NOTE: current/total must match! const mockState: Writable<any> = writable({ current: 1, total: 1 }); // NOTE: current/total must match!
describe('Step.svelte', () => { describe('Step.svelte', () => {
it('Renders with mininal props', async () => { it('Renders with mininal props', async () => {

View File

@@ -15,7 +15,7 @@
// Props (stepper) // Props (stepper)
/** Provide the verbiage that represents "Step". */ /** Provide the verbiage that represents "Step". */
export let stepTerm: string = 'Step'; export let stepTerm = 'Step';
/** Provide classes to style the stepper header badges. */ /** Provide classes to style the stepper header badges. */
export let badge: CssClasses = 'variant-filled-surface'; export let badge: CssClasses = 'variant-filled-surface';
/** Provide classes to style the stepper header active step badge. */ /** Provide classes to style the stepper header active step badge. */
@@ -23,7 +23,7 @@
/** Provide classes to style the stepper header border. */ /** Provide classes to style the stepper header border. */
export let border: CssClasses = 'border-surface-400-500-token'; export let border: CssClasses = 'border-surface-400-500-token';
/** Provide the initially selected step*/ /** Provide the initially selected step*/
export let start: number = 0; export let start = 0;
// Props (step) // Props (step)
/** Set the justification for the step navigation buttons. */ /** Set the justification for the step navigation buttons. */
@@ -35,7 +35,7 @@
/** Set the type of the back button. */ /** Set the type of the back button. */
export let buttonBackType: 'submit' | 'reset' | 'button' = 'button'; export let buttonBackType: 'submit' | 'reset' | 'button' = 'button';
/** Provide the HTML label content for the back button. */ /** Provide the HTML label content for the back button. */
export let buttonBackLabel: string = '&larr; Back'; export let buttonBackLabel = '&larr; Back';
// Button (next) // Button (next)
/** Provide arbitrary classes to style the next button. */ /** Provide arbitrary classes to style the next button. */
@@ -43,7 +43,7 @@
/** Set the type of the next button. */ /** Set the type of the next button. */
export let buttonNextType: 'submit' | 'reset' | 'button' = 'button'; export let buttonNextType: 'submit' | 'reset' | 'button' = 'button';
/** Provide the HTML label content for the next button. */ /** Provide the HTML label content for the next button. */
export let buttonNextLabel: string = 'Next &rarr;'; export let buttonNextLabel = 'Next &rarr;';
// Button (complete) // Button (complete)
/** Provide arbitrary classes to style the complete button. */ /** Provide arbitrary classes to style the complete button. */
@@ -51,7 +51,7 @@
/** Set the type of the complete button. */ /** Set the type of the complete button. */
export let buttonCompleteType: 'submit' | 'reset' | 'button' = 'button'; export let buttonCompleteType: 'submit' | 'reset' | 'button' = 'button';
/** Provide the HTML label content for the complete button. */ /** Provide the HTML label content for the complete button. */
export let buttonCompleteLabel: string = 'Complete'; export let buttonCompleteLabel = 'Complete';
// Props (regions) // Props (regions)
/** Provide arbitrary classes to the stepper header region. */ /** Provide arbitrary classes to the stepper header region. */

View File

@@ -16,6 +16,6 @@ module.exports = plugin(({ addComponents }) => {
respectImportant: true, respectImportant: true,
respectPrefix: true respectPrefix: true
}); });
} catch { } } catch {}
} }
}); });

View File

@@ -1,5 +1,5 @@
import { get, writable, type Writable } from 'svelte/store'; import { get, writable, type Writable } from 'svelte/store';
import type { Middleware, PopupSettings } from './types'; import type { PopupSettings } from './types';
// Use a store to pass the Floating UI import references // Use a store to pass the Floating UI import references
export const storePopup: Writable<any> = writable(undefined); export const storePopup: Writable<any> = writable(undefined);
@@ -21,7 +21,7 @@ export function popup(triggerNode: HTMLElement, args: PopupSettings) {
function setDomElements(): void { function setDomElements(): void {
elemPopup = document.querySelector(`[data-popup="${args.target}"]`) ?? document.createElement('div'); elemPopup = document.querySelector(`[data-popup="${args.target}"]`) ?? document.createElement('div');
elemArrow = elemPopup?.querySelector(`.arrow`) ?? document.createElement('div'); elemArrow = elemPopup.querySelector(`.arrow`) ?? document.createElement('div');
} }
setDomElements(); // init setDomElements(); // init
@@ -73,7 +73,7 @@ export function popup(triggerNode: HTMLElement, args: PopupSettings) {
// https://floating-ui.com/docs/arrow // https://floating-ui.com/docs/arrow
if (elemArrow) { if (elemArrow) {
const { x: arrowX, y: arrowY } = middlewareData.arrow; const { x: arrowX, y: arrowY } = middlewareData.arrow;
// @ts-ignore // @ts-expect-error implicit any
const staticSide = { const staticSide = {
top: 'bottom', top: 'bottom',
right: 'left', right: 'left',
@@ -165,7 +165,12 @@ export function popup(triggerNode: HTMLElement, args: PopupSettings) {
} }
// On Tab or ArrowDown key // On Tab or ArrowDown key
const triggerMenuFocused: boolean = popupState.open && document.activeElement === triggerNode; const triggerMenuFocused: boolean = popupState.open && document.activeElement === triggerNode;
if (triggerMenuFocused && (key === 'ArrowDown' || key === 'Tab') && focusableAllowedList.length > 0 && focusablePopupElements.length > 0) { if (
triggerMenuFocused &&
(key === 'ArrowDown' || key === 'Tab') &&
focusableAllowedList.length > 0 &&
focusablePopupElements.length > 0
) {
event.preventDefault(); event.preventDefault();
focusablePopupElements[0].focus(); focusablePopupElements[0].focus();
} }

1433
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

30
scripts/dev-version.js Normal file
View File

@@ -0,0 +1,30 @@
import fs from "fs";
import { exec } from "child_process";
const pkgJsonPaths = ["packages/skeleton/package.json"];
try {
exec("git rev-parse --short HEAD", (err, stdout) => {
if (err) {
console.log(err);
process.exit(1);
}
const commitHash = stdout.trim();
for (const pkgJsonPath of pkgJsonPaths) {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
const oldVersion = pkg.version;
const [major, minor, patch] = oldVersion.split(".").map(Number);
const newVersion = `${major}.${minor}.${patch}-dev.${commitHash}`;
pkg.version = newVersion;
const content = JSON.stringify(pkg, null, "\t") + "\n";
fs.writeFileSync(pkgJsonPath, content);
}
});
} catch (error) {
console.error(error);
process.exit(1);
}

View File

@@ -16,5 +16,8 @@ module.exports = {
browser: true, browser: true,
es2017: true, es2017: true,
node: true node: true
},
rules: {
'no-useless-escape': 'off'
} }
}; };

View File

@@ -12,3 +12,4 @@ pnpm-lock.yaml
.github .github
/static/font-awesome /static/font-awesome
/static/fonts /static/fonts
.vercel

View File

@@ -5,7 +5,6 @@
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build": "vite build", "build": "vite build",
"publish": "npm publish",
"preview": "vite preview", "preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",

View File

@@ -1,6 +1,6 @@
import { DocsFeature, type DocsShellSettings } from '$lib/layouts/DocsShell/types'; import { DocsFeature, type DocsShellSettings } from '$lib/layouts/DocsShell/types';
export let docShellDefaults: DocsShellSettings = { export const docShellDefaults: DocsShellSettings = {
// Heading // Heading
feature: DocsFeature.Component, feature: DocsFeature.Component,
name: '(name)', name: '(name)',

View File

@@ -24,14 +24,10 @@
</div> </div>
<!-- Aside --> <!-- Aside -->
{#if sidebar} {#if sidebar}
<aside class="layout-cols-aside {classesColRight}">
<!-- Ad Position --> <!-- Ad Position -->
{#if $storeVercelProductionMode === true} <aside class="layout-cols-aside {classesColRight}">
<!-- Production Ad --> <!-- Production Ad -->
<!-- cspell:disable --> {#if $storeVercelProductionMode === true}
<!-- cspell:disable -->
<!-- cspell:disable -->
<!-- cspell:disable -->
<script <script
async async
type="text/javascript" type="text/javascript"

View File

@@ -86,6 +86,8 @@
]; ];
let currentMessage = ''; let currentMessage = '';
// For some reason, eslint thinks ScrollBehavior is undefined...
// eslint-disable-next-line no-undef
function scrollChatBottom(behavior?: ScrollBehavior): void { function scrollChatBottom(behavior?: ScrollBehavior): void {
elemChat.scrollTo({ top: elemChat.scrollHeight, behavior }); elemChat.scrollTo({ top: elemChat.scrollHeight, behavior });
} }