diff --git a/.cz.json b/.cz.json new file mode 100644 index 0000000..fd123b5 --- /dev/null +++ b/.cz.json @@ -0,0 +1,7 @@ +{ + "commitizen": { + "name": "cz_conventional_commits", + "version": "1.0.0", + "tag_format": "$version" + } +} \ No newline at end of file diff --git a/.env.EXAMPLE b/.env.EXAMPLE new file mode 100644 index 0000000..ed033eb --- /dev/null +++ b/.env.EXAMPLE @@ -0,0 +1,17 @@ +VITE_CONTACT_EMAIL="ask@rodneylab.com" +VITE_FACEBOOK_PAGE="rodneyLab" +VITE_GITHUB_PAGE="rodneylab" +VITE_LINKEDIN_PROFILE="ask-rodney" +VITE_TELEGRAM_USERNAME="askRodney" +VITE_TIKTOK_USERNAME="@askRodney" +VITE_TWITTER_USERNAME="askRodney" +VITE_TWITTER_USER_ID="1234567890" +VITE_WIRE_USERNAME="@rodneylab" + +VITE_DOMAIN="example.com" +VITE_SITE_URL="https://www.example.com" + +# Sentry +VITE_SENTRY_KEY="123456" +VITE_SENTRY_ORG_ID="9876543" +VITE_SENTRY_PROJECT_ID="01234567891bcdef0123456789abcd" diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..e9ae448 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,15 @@ +module.exports = { + root: true, + extends: ['eslint:recommended', 'prettier'], + plugins: ['svelte3'], + overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], + parserOptions: { + sourceType: 'module', + ecmaVersion: 2019, + }, + env: { + browser: true, + es2017: true, + node: true, + }, +}; diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..461def2 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1 @@ +My name is Rodney. I am a keen developer interested in security and online privacy. I also love building accessible sites in Gatsby. I am equally keen to hear your suggestions for improving this project. Thanks for your interest in the project. Could I ask you to take a look at the project's Code of Conduct before continuing with your contribution? Thanks! A good starting point for getting up-to-speed on the project is the README file. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..6db4c10 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behaviour: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + +- OS: [e.g. iOS] +- Browser [e.g. chrome, safari] +- Version [e.g. 22] + +**Smartphone (please complete the following information):** + +- Device: [e.g. iPhone6] +- OS: [e.g. iOS8.1] +- Browser [e.g. stock browser, safari] +- Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..2f28cea --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..8d2dc4f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,39 @@ +# Description + +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. + +Fixes # (issue) + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +# How Has This Been Tested? + +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration + +- [ ] Test A +- [ ] Test B + +**Test Configuration**: + +- Firmware version: +- Hardware: +- Toolchain: +- SDK: + +# Checklist: + +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..e8db838 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,23 @@ +# SecurityPolicies and Procedures + +## Reporting a Bug + +The Rodney Lab team and community take all security bugs in Rodney Lab repos seriously. Thank you for improving the security of Rodney Lab repos. We appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions. + +Report security bugs by emailing security@rodneylab.com. + +You can encrypt your message using this PGP public key. + +That account will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours indicating the next steps in handling your report. After the initial reply to your report, we will endeavour to keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance. + +## Disclosure Policy + +When we receive a security bug report, we will assign it to a primary handler. This person will coordinate the fix and release process, involving the following steps: + +- Confirm the problem and determine the affected versions. +- Audit code to find any potential similar problems. +- Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible. + +## Comments on this Policy + +If you have suggestions on how this process could be improved please submit a pull request. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..feea69f --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# SvelteKit Files +build/ +functions/ +/.svelte-kit + +# Dependency directories +node_modules/ +/package + +# Optional eslint cache +.eslintcache + +# dotenv environment variable files +.env* +!.env.EXAMPLE + +# Mac files +.DS_Store + +# Local Netlify folder +.netlify \ No newline at end of file diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..0bd658f --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx --no-install commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..a51de7e --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +pnpm run prettier:check && pnpm run lint:scss diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 0000000..18b8797 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx svelte-check --fail-on-warnings diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b6f27f1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +engine-strict=true diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..8351c19 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +14 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..ad773e4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: +- hooks: + - id: commitizen + stages: + - commit-msg + repo: https://github.com/commitizen-tools/commitizen + rev: v2.17.10 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..09a6d07 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +.svelte-kit/** +static/** +build/** +functions/** +node_modules/** +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..6a47eec --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "useTabs": false, + "arrowParens": "always", + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000..783b41b --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,29 @@ +{ + "extends": "stylelint-config-recommended-scss", + "plugins": ["stylelint-a11y"], + "rules": { + "a11y/media-prefers-reduced-motion": true, + "a11y/no-outline-none": true, + "a11y/selector-pseudo-class-focus": true, + "color-named": "never", + "font-family-name-quotes": "always-where-required", + "font-weight-notation": "named-where-possible", + "function-url-no-scheme-relative": true, + "function-url-quotes": "always", + "string-quotes": "single", + "value-keyword-case": "lower", + "unit-disallowed-list": [], + "max-empty-lines": 2, + "no-descending-specificity": true, + "no-duplicate-selectors": true, + "font-family-no-missing-generic-family-keyword": null, + "property-no-unknown": [ + true, + { + "ignoreProperties": ["/^lost-/"] + } + ] + }, + "ignoreFiles": ["node_modules/*", "src/assets/**", "build/**", "src/lib/styles/normalise.css"], + "defaultSeverity": "error" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2c4ce62 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.formatOnSave": true, + "[markdown]": { + "editor.wordWrap": "bounded", + "editor.wordWrapColumn": 80, + "editor.quickSuggestions": false + }, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode" + } +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2c49c5b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behaviour that contributes to a positive environment for our +community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologising to those affected by our mistakes, + and learning from the experience +- Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behaviour include: + +- The use of sexualised language or imagery, and sexual attention or + advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behaviour and will take appropriate and fair corrective action in +response to any behaviour that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +ask@rodneylab.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behaviour deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behaviour was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behaviour. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behaviour. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behaviour, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9f5bc99 --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, Rodney Johnson +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..933e184 --- /dev/null +++ b/README.md @@ -0,0 +1,185 @@ +Rodney Lab sveltekit-blog-mdx Github banner + +

+ + Rodney Lab logo + +

+

+ SvelteKit MDsvex Blog Starter +

+ +[![Netlify Status](https://api.netlify.com/api/v1/badges/8d9d4d4d-6fdf-439c-944f-7a73791b676d/deploy-status)](https://app.netlify.com/sites/zealous-jackson-f2037b/deploys) + +# sveltekit-blog-mdx + +[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/rodneylab/sveltekit-blog-mdx) + +SvelteKit blog starter which helps you hit the ground running when creating a new SvelteKit blog. The project creates a Progressive Web App (PWA) out of the box. You just need to customise with your logos etc. + +Rodney Lab sveltekit-blog-mdx Github banner + +See the [Sveltekit Blog Starter blog post on the Rodney Lab site](https://rodneylab.com/sveltekit-blog-starter/) for some explanation of what's inside and how to customise. Please drop questions into a comment at the bottom of that page. Here's the quick start: + +Everything you need to build a Svelte blog site, powered by [`sveltekit-blog-mdx`](https://github.com/rodneylab/sveltekit-blog-mdx.git). + +## Creating your Own MDsveX Blog Site + +If you're seeing this, you've probably already done this step. Congrats! + +```bash +git clone https://github.com/rodneylab/sveltekit-blog-mdx.git my-new-mdsvex-blog +cd my-new-mdsvex-blog +pnpm install # or npm install +npm run dev +``` + +### Responsive Images + +The starter creates and caches responsive images using the `vite-imagetools` plugin. This is straightforward to use when you know ahead of time which image you want to include. You just import it on the page you want to use it on: + +```javascript +import featuredImageSrc from '$lib/assets/home/home.jpg'; +``` + +The `vite-imagetools` plugin will then generate and hash the image. See examples in `src/routes/index.svelte`. + +The example where you want to have a different featured image for each blog post is a little more complicated, though manageable. In this case, you can run a script (see `generate-responsive-image-data.js`) to iterate though all blog posts, taking the featured image from the blog post front matter. This script can then output the necessary imports into a generated javascript file, one for each blog post (see `src/lib/generated` directory). Finally you can dynamically import that JavaScript file in the blog template load function. + +To run the included script at the command like type: + +```shell +pnpm run gen:images +``` + +This should be done each time you add new blog posts. It also generates a low resolution placeholder, to minimise Content Layout shift during page load. + +For the script to find your blog post images, add them under the `src/lib/assets/blog` folder. In that folder, create a new folder whose name matches the post slug and add the images to the new folder. The name of the file needs to match the name you use is the post frontmatter (for featuredImage, for example). + +The script may need some tweaking for your use case. Let me know how it can be improved. + +### XML Sitemap + +- If your site is completely static, then you can generate an XML sitemap by running + +```shell +npm run generate:sitemap +``` + +this will be output to `static/sitemap.xml`. You can work this into your build process by updating the `build` script in `package.json` to something like: + +```shell + "build": "npm run generate:manifest && npm run generate:sitemap && svelte-kit build", +``` + +The generation JavaScript code is in the file `generate-sitemap.js` in the root folder of the project. + +- Alternatively, the sitemap is automatically served at `https://example.com/sitemap.xml`. It is served by the file at `src/routes/sitemap.xml.js`. + +Either way, make sure your site's URL is defined in `.env` as the `VITE_SITE_URL` variable so the correct URLs are output to the site map. + +### Progressive Web App (PWA) + +The starter mostly generates PWA config automatically, including service worker for offline availability and adding meta to the HTML head section. A PWA needs a manifest file detailing logos (for favicons) in different sizes, compatible with various devices. The starter can generate the logo in different sizes automatically if you create a 512 px × 512 px logo and save it as `static/icon.png`. Then run + +```shell +npm run generate:manifest +``` + +The script outputs the manifest file to `static/manifest.json` and it is then automatically included in your build. + +The HTML meta for PWAs is added in the component at `src/lib/components/PWA.svelte`. + +You can customise the manifest (including icon file path) by editing `src/lib/config/website.js`. The following variables feed into the generated `manifest.json` file: + +- `siteTitle`, +- `siteShortTitle`, +- `siteUrl`, +- `icon` — path to template icon, +- `backgroundColor`, +- `themeColor`. + +See article on Progressive Web Apps in SvelteKit for more. + +## Building + +```bash +npm run build +``` + +> You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production. + +## What's inside? + +``` +. +├── README.md +├── generate-manifest.js +├── generate-sitemap.js +├── jsconfig.json +├── netlify.toml +├── package.json +├── src +│   ├── app.html +│   ├── content +│   │   └── blog +│   │   ├── best-medium-format-camera-for-starting-out +│   │   ├── folding-camera +│   │   └── twin-lens-reflex-camera +│   ├── hooks.js +│   ├── lib +│   │   ├── components +│   │   │   ├── BannerImage.svelte +│   │   │   ├── ... +│   │   ├── config +│   │   │   └── website.js +│   │   ├── constants +│   │   │   └── entities.js +│   │   ├── styles +│   │   └── utilities +│   │   └── blog.js +│   └── routes +│   ├── [slug].json.js +│   ├── [slug].svelte +│   ├── __layout.svelte +│   ├── contact.svelte +│   ├── index.json.js +│   └── index.svelte +└── svelte.config.js +``` + +### `/` + +- `generate-manifest.js` script for generating the PWA manifest.json as well as the icons in different sizes. + +- `generate-sitemap.js` script for generating an XML sitemap, only needed for static sites, otherwise SvelteKit creates an endpoint from which the sitemap is served (see `src/routes/sitemap.xml.js`). + +### `src/content` + +- The `src/content/blog` is where we need to put our blog posts. Just clean out the sample content and replace it with your views on the world! There is a separate folder for each post, which allows you to keep images, video and other related media specific to a post better organised. We set the browser path for the based based on this folder name, so keep that in mind when naming the folders. Write the actual post in a file called `index.md` within post's folder. Although the file has an `.md` extension, you can write Svelte in it. + +### `src` + +- `hooks.js` we define Content Security Policy (CSP) and other HTTP security headers in here. More on this later. + +### `src/components` + +- `src/lib/components` these are the components we use in pages. + +### `src/lib` + +- `src/lib/config/website.js` for convenience we define properties for the site here such as the site title, contact email addresses and social media accounts. Some properties feed from environment variables. See a post on getting started with SvelteKit for more on environment variables in SvelteKit. + +- `src/lib/styles` does what you expect! We use SCSS for styling and source self-hosted fonts in the layouts. + +### `src/utilities` + +- `src/utilities/blog.js` this file contains some code for helping us transform the markdown in blog posts to Svelte. As well as that they help extract fields in the frontmatter (this is the metadata we include at the top fo the blog post `index.md` files). + +### `src/routes` + +- `src/routes/[slug].json.js` this is essentially a template for blog post data. One of these file is generated at build for each blog post. It is used to extract data needed in the Svelte file used to generate the post's HTML. + +- `src/routes/[slug].svelte` similarly to the previous file, one of these is generated for each blog post. This time it is the Svelte code which SvelteKit uses to generate the HTML for our blog posts. + +I mention most of the other files in the Getting Started with SvelteKit blog post, but let me know if I have missed anything which needs more explanation. diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..422b194 --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1 @@ +module.exports = { extends: ['@commitlint/config-conventional'] }; diff --git a/generate-manifest.js b/generate-manifest.js new file mode 100644 index 0000000..32fe7b8 --- /dev/null +++ b/generate-manifest.js @@ -0,0 +1,62 @@ +import fs from 'fs'; +import path from 'path'; +import sharp from 'sharp'; +import website from './src/lib/config/website.js'; + +const __dirname = path.resolve(); +const iconsDirectory = path.join(__dirname, 'static/icons'); +const manifestFile = path.join(__dirname, 'static/manifest.json'); + +const { backgroundColor, icon, siteShortTitle, siteTitle, themeColor } = website; +const DEFAULT_SIZES = [128, 144, 152, 192, 256, 512]; + +const iconImage = sharp(icon); + +const resizeIcon = async ({ size, path }) => { + await iconImage.resize(size).toFile(path, (err) => { + if (err) { + console.error(err); + } + }); +}; + +const main = async () => { + try { + const { height, width } = await iconImage.metadata(); + const maxSize = Math.min(width, height); + const sizes = DEFAULT_SIZES.filter((element) => element <= maxSize); + + const manifest = { + name: siteTitle, + short_name: siteShortTitle, + start_url: '/index.html', + background_color: backgroundColor, + theme_color: themeColor, + display: 'standalone', + icons: sizes.map((size) => { + const path = `icons/icon-${size}x${size}.png`; + resizeIcon({ size, path: `static/${path}` }); + + return { + src: path, + sizes: `${size}x${size}`, + type: 'image/png', + purpose: 'any maskable', + }; + }), + }; + + fs.writeFileSync(manifestFile, JSON.stringify(manifest, null, 2)); + } catch (error) { + console.error(error); + } +}; + +console.log('Generating manifest.json'); +fs.mkdir(iconsDirectory, { recursive: true }, (err) => { + if (err) { + return console.error(err); + } +}); + +main(); diff --git a/generate-responsive-image-data.js b/generate-responsive-image-data.js new file mode 100644 index 0000000..588fbef --- /dev/null +++ b/generate-responsive-image-data.js @@ -0,0 +1,133 @@ +import fm from 'front-matter'; +import fs from 'fs'; +import path from 'path'; +import { BLOG_PATH } from './src/lib/utilities/blog.js'; +import { makeDirectory } from './src/lib/utilities/file.js'; +import { dominantColour, lowResolutionPlaceholder, metadata } from './src/lib/utilities/image.js'; + +const __dirname = path.resolve(); +const formats = ['webp', 'auto']; +const sizes = [672]; +const densities = [1.0, 2.0]; +const maxWidth = sizes[sizes.length - 1]; + +// use sizes and densities arrays to determine the actual output widths needed +const outputSizes = []; +sizes.forEach((sizesElement) => { + densities.forEach((densitiesElement) => outputSizes.push(densitiesElement * sizesElement)); +}); +outputSizes.sort((a, b) => b - a); + +async function generateImageMeta(source) { + const metaPromises = [ + metadata({ source }), + dominantColour({ source }), + lowResolutionPlaceholder({ source }), + ]; + const [metadataResult, dominantColourObject, placeholder] = await Promise.all(metaPromises); + const { format, width, height } = metadataResult; + const { r, g, b } = dominantColourObject; + const dominantColourValue = `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; + return { dominantColour: dominantColourValue, placeholder, format, width, height }; +} + +function getPosts(location) { + const directories = fs + .readdirSync(location) + .filter((element) => fs.lstatSync(`${location}/${element}`).isDirectory()); + const articles = []; + + directories.forEach((element) => { + const contentPath = `${location}/${element}/index.md`; + if (fs.existsSync(contentPath)) { + const content = fs.readFileSync(contentPath, { encoding: 'utf-8' }); + const frontmatter = fm(content); + const { featuredImage, featuredImageAlt, ogImage, ogSquareImage, twitterImage } = + frontmatter.attributes; + articles.push({ + slug: element, + featuredImage, + featuredImageAlt, + ogImage, + ogSquareImage, + twitterImage, + }); + } + }); + return articles; +} + +const main = async () => { + try { + const location = path.join(__dirname, BLOG_PATH); + const posts = getPosts(location); + + const imageMetaPromises = posts.map(async (element) => { + const { featuredImage, slug } = element; + const source = path.join(__dirname, 'src/lib/assets/blog/', slug, featuredImage); + return generateImageMeta(source); + }); + const imageMetadata = await Promise.all(imageMetaPromises); + + console.log(`Generating image metadata for posts`); + const postDataDir = path.join(__dirname, 'src/lib/generated/posts'); + await makeDirectory(postDataDir); + + posts.forEach((element, index) => { + const { featuredImage, featuredImageAlt, ogImage, ogSquareImage, slug, twitterImage } = + element; + const postPath = path.join(postDataDir, `${slug}.js`); + const { dominantColour, format, placeholder, width } = imageMetadata[index]; + const source = `$lib/assets/blog/${slug}/${featuredImage}`; + const ogImageSource = `$lib/assets/blog/${slug}/${ogImage}`; + const ogSquareImageSource = `$lib/assets/blog/${slug}/${ogSquareImage}`; + const twitterImageSource = `$lib/assets/blog/${slug}/${twitterImage}`; + const srcsetImportArray = formats.map( + (formatsElement) => + `import srcset${formatsElement} from '${source}?w=${ + width < outputSizes[0] ? `${width};` : '' + }${outputSizes.filter((outputSizesElement) => outputSizesElement <= width).join(';')}&${ + formatsElement === 'auto' ? format : formatsElement + }&srcset';`, + ); + const sources = `[\n${formats + .map( + (formatsElement) => + ` { srcset: ${`srcset${formatsElement}`}, type: ${ + formatsElement === 'auto' ? `'image/${format}'` : `'image/${formatsElement}'` + } },`, + ) + .join('\n')}\n ]`; + const result = `import meta from '${source}?width=${Math.min(maxWidth, width)}&metadata'; +${srcsetImportArray.join('\n')} +import ogImage from '${ogImageSource}'; +import ogSquareImage from '${ogSquareImageSource}'; +import twitterImage from '${twitterImageSource}'; + +const { height, src, width } = meta; + +const data = { + slug: '${slug}', + alt: '${featuredImageAlt.replace(/'/g, "\\'")}', + width, + height, + src, + sources: ${sources}, + dominantColour: '${dominantColour}', + placeholder: + '${placeholder}', + ogImage, + ogSquareImage, + twitterImage, +}; + +export { data as default }; +`; + fs.writeFileSync(postPath, result, 'utf-8'); + }); + } catch (error) { + console.log(`Error generating blog post responsive image data: ${error}`); + } +}; + +main(); diff --git a/generate-sitemap.js b/generate-sitemap.js new file mode 100644 index 0000000..cd5949b --- /dev/null +++ b/generate-sitemap.js @@ -0,0 +1,90 @@ +import { config } from 'dotenv'; +import fm from 'front-matter'; +import fs from 'fs'; +import path from 'path'; +import { BLOG_PATH } from './src/lib/utilities/blog.js'; + +config(); + +const DEFAULT_BLOG_POST_PRIORITY = 0.7; +const DEFAULT_PAGE_PRIORITY = 0.7; +const siteUrl = process.env.VITE_SITE_URL; + +const TIMESTAMP = new Date().toISOString(); + +const __dirname = path.resolve(); +const sitemapFile = path.join(__dirname, 'static/sitemap.xml'); + +function getPages(location) { + const pages = fs.readdirSync(location).reduce((accumulator, currentValue) => { + if ( + path.extname(currentValue) === '.svelte' && + path.basename(currentValue).indexOf('__') !== 0 + ) { + accumulator.push(`${siteUrl}/${currentValue.replace('.svelte', '/').replace('index/', '')}`); + } + + return accumulator; + }, []); + return pages; +} + +export const getPosts = (location) => { + const directories = fs + .readdirSync(location) + .filter((element) => fs.lstatSync(`${location}/${element}`).isDirectory()); + const articles = []; + + directories.forEach((element) => { + const contentPath = `${location}/${element}/index.md`; + if (fs.existsSync(contentPath)) { + const content = fs.readFileSync(contentPath, { encoding: 'utf-8' }); + const frontmatter = fm(content); + const { lastUpdated } = frontmatter.attributes; + + articles.push({ slug: element, lastUpdated }); + } + }); + return articles; +}; + +const render = (pages, posts) => ` + + ${pages + .map( + (element) => ` + ${element} + ${`${TIMESTAMP}`} + monthly + ${DEFAULT_PAGE_PRIORITY} + `, + ) + .join('')} + ${posts + .map((element) => { + const { lastUpdated, slug } = element; + return ` + ${siteUrl}/${slug}/ + ${`${lastUpdated}`} + daily + ${DEFAULT_BLOG_POST_PRIORITY} + + `; + }) + .join('')}`; + +const location = path.join(__dirname, BLOG_PATH); +const pages = getPages(location); +const posts = getPosts(location); + +fs.writeFileSync(sitemapFile, render(pages, posts)); diff --git a/images/rodneylab-github-sveltekit-blog-mdx-lighthouse-pwa.png b/images/rodneylab-github-sveltekit-blog-mdx-lighthouse-pwa.png new file mode 100644 index 0000000..29e3de6 Binary files /dev/null and b/images/rodneylab-github-sveltekit-blog-mdx-lighthouse-pwa.png differ diff --git a/images/rodneylab-github-sveltekit-blog-mdx-lighthouse.png b/images/rodneylab-github-sveltekit-blog-mdx-lighthouse.png new file mode 100644 index 0000000..1e635a5 Binary files /dev/null and b/images/rodneylab-github-sveltekit-blog-mdx-lighthouse.png differ diff --git a/images/rodneylab-github-sveltekit-blog-mdx.png b/images/rodneylab-github-sveltekit-blog-mdx.png new file mode 100644 index 0000000..fd20d67 Binary files /dev/null and b/images/rodneylab-github-sveltekit-blog-mdx.png differ diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..0588bc6 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "$lib/*": ["src/lib/*"] + } + }, + "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..f73dbdf --- /dev/null +++ b/netlify.toml @@ -0,0 +1,7 @@ +[build] + command = "npm run build" + functions = "functions/" + publish = "build/" + +[dev] + command = "svelte-kit dev" diff --git a/package.json b/package.json new file mode 100644 index 0000000..c1d227a --- /dev/null +++ b/package.json @@ -0,0 +1,62 @@ +{ + "name": "sveltekit-blog-mdx", + "version": "1.0.0", + "scripts": { + "dev": "svelte-kit dev --port 3030", + "build": "npm run generate:manifest && svelte-kit build", + "preview": "svelte-kit preview --port 3000", + "lint": "prettier --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .", + "lint:scss": "stylelint \"src/**/*.{css,scss,svelte}\"", + "format": "prettier --write --plugin-search-dir=. .", + "generate:images": "node ./generate-responsive-image-data.js", + "generate:manifest": "node ./generate-manifest.js", + "generate:sitemap": "node ./generate-sitemap.js", + "prettier:check": "prettier --check --plugin-search-dir=. .", + "prepare": "husky install", + "svelte-check": "svelte-check" + }, + "devDependencies": { + "@fontsource/lato": "^4.5.0", + "@fontsource/lora": "^4.5.0", + "@fontsource/source-sans-pro": "^4.5.0", + "@fortawesome/free-regular-svg-icons": "^5.15.4", + "@fortawesome/free-solid-svg-icons": "^5.15.4", + "@sveltejs/adapter-static": "^1.0.0-next.19", + "@sveltejs/kit": "^1.0.0-next.168", + "dayjs": "^1.10.7", + "dotenv": "^10.0.0", + "eslint": "^7.32.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-svelte3": "^3.2.1", + "front-matter": "^4.0.2", + "husky": "^7.0.2", + "mdsvex": "^0.9.8", + "object-hash": "^2.2.0", + "prettier": "~2.3.2", + "prettier-plugin-svelte": "^2.4.0", + "reading-time": "1.4.0", + "sass": "^1.41.0", + "sharp": "^0.29.1", + "stylelint": "^13.13.1", + "stylelint-a11y": "^1.2.3", + "stylelint-config-recommended-scss": "^4.3.0", + "stylelint-config-standard": "^22.0.0", + "stylelint-scss": "^3.21.0", + "svelte": "^3.42.6", + "svelte-awesome": "^2.3.2", + "svelte-check": "^2.2.6", + "svelte-feather-icons": "^3.5.0", + "svelte-preprocess": "^4.9.4", + "svelte-preprocess-import-assets": "^0.1.3", + "vanilla-lazyload": "^17.4.0", + "vite-imagetools": "^3.6.8" + }, + "repository": { + "type": "git", + "url": "https://github.com/rodneylab/sveltekit-seo" + }, + "bugs": { + "url": "https://github.com/rodneylab/sveltekit-seo/issues" + }, + "type": "module" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..6c01045 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,3187 @@ +lockfileVersion: 5.3 + +specifiers: + '@fontsource/lato': ^4.5.0 + '@fontsource/lora': ^4.5.0 + '@fontsource/source-sans-pro': ^4.5.0 + '@fortawesome/free-regular-svg-icons': ^5.15.4 + '@fortawesome/free-solid-svg-icons': ^5.15.4 + '@sveltejs/adapter-static': ^1.0.0-next.19 + '@sveltejs/kit': ^1.0.0-next.168 + dayjs: ^1.10.7 + dotenv: ^10.0.0 + eslint: ^7.32.0 + eslint-config-prettier: ^8.3.0 + eslint-plugin-svelte3: ^3.2.1 + front-matter: ^4.0.2 + husky: ^7.0.2 + mdsvex: ^0.9.8 + object-hash: ^2.2.0 + prettier: ~2.3.2 + prettier-plugin-svelte: ^2.4.0 + reading-time: 1.4.0 + sass: ^1.41.0 + sharp: ^0.29.1 + stylelint: ^13.13.1 + stylelint-a11y: ^1.2.3 + stylelint-config-recommended-scss: ^4.3.0 + stylelint-config-standard: ^22.0.0 + stylelint-scss: ^3.21.0 + svelte: ^3.42.6 + svelte-awesome: ^2.3.2 + svelte-check: ^2.2.6 + svelte-feather-icons: ^3.5.0 + svelte-preprocess: ^4.9.4 + svelte-preprocess-import-assets: ^0.1.3 + vanilla-lazyload: ^17.4.0 + vite-imagetools: ^3.6.8 + +devDependencies: + '@fontsource/lato': 4.5.0 + '@fontsource/lora': 4.5.0 + '@fontsource/source-sans-pro': 4.5.0 + '@fortawesome/free-regular-svg-icons': 5.15.4 + '@fortawesome/free-solid-svg-icons': 5.15.4 + '@sveltejs/adapter-static': 1.0.0-next.19 + '@sveltejs/kit': 1.0.0-next.168_svelte@3.42.6 + dayjs: 1.10.7 + dotenv: 10.0.0 + eslint: 7.32.0 + eslint-config-prettier: 8.3.0_eslint@7.32.0 + eslint-plugin-svelte3: 3.2.1_eslint@7.32.0+svelte@3.42.6 + front-matter: 4.0.2 + husky: 7.0.2 + mdsvex: 0.9.8_svelte@3.42.6 + object-hash: 2.2.0 + prettier: 2.3.2 + prettier-plugin-svelte: 2.4.0_prettier@2.3.2+svelte@3.42.6 + reading-time: 1.4.0 + sass: 1.41.0 + sharp: 0.29.1 + stylelint: 13.13.1 + stylelint-a11y: 1.2.3_stylelint@13.13.1 + stylelint-config-recommended-scss: 4.3.0_d55469ff7b1b68c43b61270d19a60ab6 + stylelint-config-standard: 22.0.0_stylelint@13.13.1 + stylelint-scss: 3.21.0_stylelint@13.13.1 + svelte: 3.42.6 + svelte-awesome: 2.3.2 + svelte-check: 2.2.6_sass@1.41.0+svelte@3.42.6 + svelte-feather-icons: 3.5.0 + svelte-preprocess: 4.9.4_sass@1.41.0+svelte@3.42.6 + svelte-preprocess-import-assets: 0.1.3_svelte@3.42.6 + vanilla-lazyload: 17.4.0 + vite-imagetools: 3.6.8 + +packages: + + /@babel/code-frame/7.12.11: + resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} + dependencies: + '@babel/highlight': 7.14.5 + dev: true + + /@babel/code-frame/7.14.5: + resolution: {integrity: sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.14.5 + dev: true + + /@babel/compat-data/7.15.0: + resolution: {integrity: sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core/7.15.5: + resolution: {integrity: sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.14.5 + '@babel/generator': 7.15.4 + '@babel/helper-compilation-targets': 7.15.4_@babel+core@7.15.5 + '@babel/helper-module-transforms': 7.15.4 + '@babel/helpers': 7.15.4 + '@babel/parser': 7.15.6 + '@babel/template': 7.15.4 + '@babel/traverse': 7.15.4 + '@babel/types': 7.15.6 + convert-source-map: 1.8.0 + debug: 4.3.2 + gensync: 1.0.0-beta.2 + json5: 2.2.0 + semver: 6.3.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator/7.15.4: + resolution: {integrity: sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + jsesc: 2.5.2 + source-map: 0.5.7 + dev: true + + /@babel/helper-compilation-targets/7.15.4_@babel+core@7.15.5: + resolution: {integrity: sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.15.0 + '@babel/core': 7.15.5 + '@babel/helper-validator-option': 7.14.5 + browserslist: 4.17.0 + semver: 6.3.0 + dev: true + + /@babel/helper-function-name/7.15.4: + resolution: {integrity: sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-get-function-arity': 7.15.4 + '@babel/template': 7.15.4 + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-get-function-arity/7.15.4: + resolution: {integrity: sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-hoist-variables/7.15.4: + resolution: {integrity: sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-member-expression-to-functions/7.15.4: + resolution: {integrity: sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-module-imports/7.15.4: + resolution: {integrity: sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-module-transforms/7.15.4: + resolution: {integrity: sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-module-imports': 7.15.4 + '@babel/helper-replace-supers': 7.15.4 + '@babel/helper-simple-access': 7.15.4 + '@babel/helper-split-export-declaration': 7.15.4 + '@babel/helper-validator-identifier': 7.14.9 + '@babel/template': 7.15.4 + '@babel/traverse': 7.15.4 + '@babel/types': 7.15.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-optimise-call-expression/7.15.4: + resolution: {integrity: sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-replace-supers/7.15.4: + resolution: {integrity: sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-member-expression-to-functions': 7.15.4 + '@babel/helper-optimise-call-expression': 7.15.4 + '@babel/traverse': 7.15.4 + '@babel/types': 7.15.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access/7.15.4: + resolution: {integrity: sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-split-export-declaration/7.15.4: + resolution: {integrity: sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.15.6 + dev: true + + /@babel/helper-validator-identifier/7.14.9: + resolution: {integrity: sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option/7.14.5: + resolution: {integrity: sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers/7.15.4: + resolution: {integrity: sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.15.4 + '@babel/traverse': 7.15.4 + '@babel/types': 7.15.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight/7.14.5: + resolution: {integrity: sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.14.9 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser/7.15.6: + resolution: {integrity: sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==} + engines: {node: '>=6.0.0'} + hasBin: true + dev: true + + /@babel/template/7.15.4: + resolution: {integrity: sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.14.5 + '@babel/parser': 7.15.6 + '@babel/types': 7.15.6 + dev: true + + /@babel/traverse/7.15.4: + resolution: {integrity: sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.14.5 + '@babel/generator': 7.15.4 + '@babel/helper-function-name': 7.15.4 + '@babel/helper-hoist-variables': 7.15.4 + '@babel/helper-split-export-declaration': 7.15.4 + '@babel/parser': 7.15.6 + '@babel/types': 7.15.6 + debug: 4.3.2 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types/7.15.6: + resolution: {integrity: sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.14.9 + to-fast-properties: 2.0.0 + dev: true + + /@eslint/eslintrc/0.4.3: + resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.2 + espree: 7.3.1 + globals: 13.11.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + js-yaml: 3.14.1 + minimatch: 3.0.4 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@fontsource/lato/4.5.0: + resolution: {integrity: sha512-Y1qluoF+5b2U6MWcEz70+euZwl4TEV+9v7nZCmuRgNHb5McYc3VmbNmYNEiLsnb1HHwlAHA70P/LktP9EJ61ag==} + dev: true + + /@fontsource/lora/4.5.0: + resolution: {integrity: sha512-4ThGnMFbktlQqsTW7kCdzT888esMFfnbHE9PJMQCtcP2JUIJXDQpxvmtlsio1AJBnvUxPxegAAp76Q8lm7t1VQ==} + dev: true + + /@fontsource/source-sans-pro/4.5.0: + resolution: {integrity: sha512-+ze+nO9dVN5pAVg9CdQmVgR6f8kDpq/elHMGcyx3qsW4+TN4mI7EuMdNzKP3E1xeZwTHSmHY5bezpfFHX7bQsg==} + dev: true + + /@fortawesome/fontawesome-common-types/0.2.36: + resolution: {integrity: sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==} + engines: {node: '>=6'} + requiresBuild: true + dev: true + + /@fortawesome/free-regular-svg-icons/5.15.4: + resolution: {integrity: sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + '@fortawesome/fontawesome-common-types': 0.2.36 + dev: true + + /@fortawesome/free-solid-svg-icons/5.15.4: + resolution: {integrity: sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + '@fortawesome/fontawesome-common-types': 0.2.36 + dev: true + + /@humanwhocodes/config-array/0.5.0: + resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.0 + debug: 4.3.2 + minimatch: 3.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/object-schema/1.2.0: + resolution: {integrity: sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==} + 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.13.0 + dev: true + + /@rollup/pluginutils/4.1.1: + resolution: {integrity: sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.0 + dev: true + + /@stylelint/postcss-css-in-js/0.37.2_2b33a41d320e3e2012e5b3b0fadc703b: + resolution: {integrity: sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==} + peerDependencies: + postcss: '>=7.0.0' + postcss-syntax: '>=0.36.2' + dependencies: + '@babel/core': 7.15.5 + postcss: 7.0.36 + postcss-syntax: 0.36.2_postcss@7.0.36 + transitivePeerDependencies: + - supports-color + dev: true + + /@stylelint/postcss-markdown/0.36.2_2b33a41d320e3e2012e5b3b0fadc703b: + resolution: {integrity: sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ==} + peerDependencies: + postcss: '>=7.0.0' + postcss-syntax: '>=0.36.2' + dependencies: + postcss: 7.0.36 + postcss-syntax: 0.36.2_postcss@7.0.36 + remark: 13.0.0 + unist-util-find-all-after: 3.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@sveltejs/adapter-static/1.0.0-next.19: + resolution: {integrity: sha512-uZNJNVGCdiLo1XnMbezlAUsNSzB36oqtXvaUiDmy+Lv0jKU7ZukDQnJ0zWAatdqXl9ETlG4YyTWI/i7E8nmLpQ==} + dev: true + + /@sveltejs/kit/1.0.0-next.168_svelte@3.42.6: + resolution: {integrity: sha512-BHVqLp3d8BCPD0kuNueoV5YxyfLfgAC9wU6PCbOGIhn1gw4mvpiVbeEn7NKeVkTkl88bu/QtAITLsIx1+4flTA==} + engines: {node: ^12.20 || >=14.13} + hasBin: true + peerDependencies: + svelte: ^3.39.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 1.0.0-next.24_svelte@3.42.6+vite@2.5.7 + cheap-watch: 1.0.4 + sade: 1.7.4 + svelte: 3.42.6 + vite: 2.5.7 + transitivePeerDependencies: + - diff-match-patch + - supports-color + dev: true + + /@sveltejs/vite-plugin-svelte/1.0.0-next.24_svelte@3.42.6+vite@2.5.7: + resolution: {integrity: sha512-b+n3jcLpk2j/25APQbk5ejCyd0faYTB2bOxR3gY0LX3MFGgdiL8zdf3/aawcPSxLdbL73YVlxNBIATGuvq03uQ==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + diff-match-patch: ^1.0.5 + svelte: ^3.34.0 + vite: ^2.5.3 + peerDependenciesMeta: + diff-match-patch: + optional: true + dependencies: + '@rollup/pluginutils': 4.1.1 + debug: 4.3.2 + kleur: 4.1.4 + magic-string: 0.25.7 + require-relative: 0.8.7 + svelte: 3.42.6 + svelte-hmr: 0.14.7_svelte@3.42.6 + vite: 2.5.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@types/mdast/3.0.10: + resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} + dependencies: + '@types/unist': 2.0.6 + dev: true + + /@types/minimist/1.2.2: + resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} + dev: true + + /@types/node/16.9.1: + resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} + dev: true + + /@types/normalize-package-data/2.4.1: + resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} + dev: true + + /@types/parse-json/4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: true + + /@types/pug/2.0.5: + resolution: {integrity: sha512-LOnASQoeNZMkzexRuyqcBBDZ6rS+rQxUMkmj5A0PkhhiSZivLIuz6Hxyr1mkGoEZEkk66faROmpMi4fFkrKsBA==} + dev: true + + /@types/sass/1.16.1: + resolution: {integrity: sha512-iZUcRrGuz/Tbg3loODpW7vrQJkUtpY2fFSf4ELqqkApcS2TkZ1msk7ie8iZPB86lDOP8QOTTmuvWjc5S0R9OjQ==} + dependencies: + '@types/node': 16.9.1 + dev: true + + /@types/unist/2.0.6: + resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + dev: true + + /acorn-jsx/5.3.2_acorn@7.4.1: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 7.4.1 + dev: true + + /acorn/7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + 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 + + /ajv/8.6.3: + resolution: {integrity: sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-colors/4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + dev: true + + /ansi-regex/2.1.1: + resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /anymatch/3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.0 + dev: true + + /aproba/1.2.0: + resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} + dev: true + + /are-we-there-yet/1.1.7: + resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==} + dependencies: + delegates: 1.0.0 + readable-stream: 2.3.7 + dev: true + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /arrify/1.0.1: + resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=} + engines: {node: '>=0.10.0'} + dev: true + + /astral-regex/2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /autoprefixer/9.8.6: + resolution: {integrity: sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==} + hasBin: true + dependencies: + browserslist: 4.17.0 + caniuse-lite: 1.0.30001257 + colorette: 1.4.0 + normalize-range: 0.1.2 + num2fraction: 1.2.2 + postcss: 7.0.36 + postcss-value-parser: 4.1.0 + dev: true + + /bail/1.0.5: + resolution: {integrity: sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==} + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /balanced-match/2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + dev: true + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + 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 + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist/4.17.0: + resolution: {integrity: sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001257 + colorette: 1.4.0 + electron-to-chromium: 1.3.840 + escalade: 3.1.1 + node-releases: 1.1.75 + dev: true + + /buffer-crc32/0.2.13: + resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} + dev: true + + /buffer/5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-keys/6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.2.1 + quick-lru: 4.0.1 + dev: true + + /camelcase/5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite/1.0.30001257: + resolution: {integrity: sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==} + dev: true + + /chalk/2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + 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 + + /character-entities-legacy/1.1.4: + resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} + dev: true + + /character-entities/1.2.4: + resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} + dev: true + + /character-reference-invalid/1.1.4: + resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} + dev: true + + /cheap-watch/1.0.4: + resolution: {integrity: sha512-QR/9FrtRL5fjfUJBhAKCdi0lSRQ3rVRRum3GF9wDKp2TJbEIMGhUEr2yU8lORzm9Isdjx7/k9S0DFDx+z5VGtw==} + engines: {node: '>=8'} + dev: true + + /chokidar/3.5.2: + resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.1 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /chownr/1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: true + + /clone-regexp/2.2.0: + resolution: {integrity: sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==} + engines: {node: '>=6'} + dependencies: + is-regexp: 2.1.0 + dev: true + + /code-point-at/1.1.0: + resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=} + engines: {node: '>=0.10.0'} + dev: true + + /color-convert/1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + 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.3: + resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} + dev: true + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /color-string/1.6.0: + resolution: {integrity: sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: true + + /color/3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.6.0 + dev: true + + /color/4.0.1: + resolution: {integrity: sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA==} + dependencies: + color-convert: 2.0.1 + color-string: 1.6.0 + dev: true + + /colorette/1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true + + /console-control-strings/1.1.0: + resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} + dev: true + + /convert-source-map/1.8.0: + resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /core-util-is/1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: true + + /cosmiconfig/7.0.1: + resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + + /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 + + /cssesc/3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /dayjs/1.10.7: + resolution: {integrity: sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==} + dev: true + + /debug/4.3.2: + resolution: {integrity: sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decamelize-keys/1.1.0: + resolution: {integrity: sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize/1.2.0: + resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=} + engines: {node: '>=0.10.0'} + dev: true + + /decompress-response/4.2.1: + resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} + engines: {node: '>=8'} + dependencies: + mimic-response: 2.1.0 + dev: true + + /deep-extend/0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /delegates/1.0.0: + resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} + dev: true + + /detect-indent/6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /detect-libc/1.0.3: + resolution: {integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-serializer/0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + dependencies: + domelementtype: 2.2.0 + entities: 2.2.0 + dev: true + + /domelementtype/1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + dev: true + + /domelementtype/2.2.0: + resolution: {integrity: sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==} + dev: true + + /domhandler/2.4.2: + resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} + dependencies: + domelementtype: 1.3.1 + dev: true + + /domutils/1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + dev: true + + /dotenv/10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + dev: true + + /electron-to-chromium/1.3.840: + resolution: {integrity: sha512-yRoUmTLDJnkIJx23xLY7GbSvnmDCq++NSuxHDQ0jiyDJ9YZBUGJcrdUqm+ZwZFzMbCciVzfem2N2AWiHJcWlbw==} + dev: true + + /emoji-regex/8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /end-of-stream/1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + + /enquirer/2.3.6: + resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.1 + dev: true + + /entities/1.1.2: + resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} + dev: true + + /entities/2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: true + + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es6-promise/3.3.1: + resolution: {integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=} + dev: true + + /esbuild/0.12.28: + resolution: {integrity: sha512-pZ0FrWZXlvQOATlp14lRSk1N9GkeJ3vLIwOcUoo3ICQn9WNR4rWoNi81pbn6sC1iYUy7QPqNzI3+AEzokwyVcA==} + hasBin: true + requiresBuild: true + dev: true + + /escalade/3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier/8.3.0_eslint@7.32.0: + resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 7.32.0 + dev: true + + /eslint-plugin-svelte3/3.2.1_eslint@7.32.0+svelte@3.42.6: + resolution: {integrity: sha512-YoBR9mLoKCjGghJ/gvpnFZKaMEu/VRcuxpSRS8KuozuEo7CdBH7bmBHa6FmMm0i4kJnOyx+PVsaptz96K6H/4Q==} + engines: {node: '>=10'} + peerDependencies: + eslint: '>=6.0.0' + svelte: ^3.2.0 + dependencies: + eslint: 7.32.0 + svelte: 3.42.6 + dev: true + + /eslint-scope/5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-utils/2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-visitor-keys/1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys/2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint/7.32.0: + resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} + engines: {node: ^10.12.0 || >=12.0.0} + hasBin: true + dependencies: + '@babel/code-frame': 7.12.11 + '@eslint/eslintrc': 0.4.3 + '@humanwhocodes/config-array': 0.5.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.2 + doctrine: 3.0.0 + enquirer: 2.3.6 + escape-string-regexp: 4.0.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + eslint-visitor-keys: 2.1.0 + espree: 7.3.1 + esquery: 1.4.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.2 + globals: 13.11.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.1 + js-yaml: 3.14.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.0.4 + natural-compare: 1.4.0 + optionator: 0.9.1 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.3.5 + strip-ansi: 6.0.0 + strip-json-comments: 3.1.1 + table: 6.7.1 + text-table: 0.2.0 + v8-compile-cache: 2.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/7.3.1: + resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.2_acorn@7.4.1 + eslint-visitor-keys: 1.3.0 + dev: true + + /esprima/4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery/1.4.0: + resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.2.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.2.0 + dev: true + + /estraverse/4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse/5.2.0: + resolution: {integrity: sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /execall/2.0.0: + resolution: {integrity: sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==} + engines: {node: '>=8'} + dependencies: + clone-regexp: 2.2.0 + dev: true + + /expand-template/2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + dev: true + + /extend/3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob/3.2.7: + resolution: {integrity: sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==} + engines: {node: '>=8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.4 + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} + dev: true + + /fastest-levenshtein/1.0.12: + resolution: {integrity: sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==} + dev: true + + /fastq/1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + 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 + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.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.2 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.2: + resolution: {integrity: sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==} + dev: true + + /front-matter/4.0.2: + resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} + dependencies: + js-yaml: 3.14.1 + dev: true + + /fs-constants/1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} + dev: true + + /fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + dev: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /functional-red-black-tree/1.0.1: + resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} + dev: true + + /gauge/2.7.4: + resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=} + dependencies: + aproba: 1.2.0 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.4 + string-width: 1.0.2 + strip-ansi: 3.0.1 + wide-align: 1.1.3 + dev: true + + /gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-stdin/8.0.0: + resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} + engines: {node: '>=10'} + dev: true + + /github-from-package/0.0.0: + resolution: {integrity: sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=} + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.1 + dev: true + + /glob/7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /global-modules/2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + dependencies: + global-prefix: 3.0.0 + dev: true + + /global-prefix/3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + dev: true + + /globals/11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals/13.11.0: + resolution: {integrity: sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby/11.0.4: + resolution: {integrity: sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.7 + ignore: 5.1.8 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globjoin/0.1.4: + resolution: {integrity: sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=} + dev: true + + /gonzales-pe/4.3.0: + resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==} + engines: {node: '>=0.6.0'} + hasBin: true + dependencies: + minimist: 1.2.5 + dev: true + + /graceful-fs/4.2.8: + resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==} + dev: true + + /hard-rejection/2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-flag/3.0.0: + resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} + engines: {node: '>=4'} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-unicode/2.0.1: + resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hosted-git-info/2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hosted-git-info/4.0.2: + resolution: {integrity: sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /html-tags/3.1.0: + resolution: {integrity: sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==} + engines: {node: '>=8'} + dev: true + + /htmlparser2/3.10.1: + resolution: {integrity: sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==} + dependencies: + domelementtype: 1.3.1 + domhandler: 2.4.2 + domutils: 1.7.0 + entities: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + + /husky/7.0.2: + resolution: {integrity: sha512-8yKEWNX4z2YsofXAMT7KvA1g8p+GxtB1ffV8XtpAEGuXNAbCV5wdNKH+qTpw8SM9fh4aMPDR+yQuKfgnreyZlg==} + engines: {node: '>=12'} + hasBin: true + dev: true + + /ieee754/1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore/4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + dev: true + + /ignore/5.1.8: + resolution: {integrity: sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==} + engines: {node: '>= 4'} + dev: true + + /imagetools-core/2.7.6: + resolution: {integrity: sha512-piffg3nFcu4TRR2zT0252isYkLHzi3HGVNnQcB7KcLREC5+KtrcwkmlLWCczKSUTN9OIOD0aXs6KyAy9UfeRsg==} + engines: {node: '>=12.0.0'} + dependencies: + sharp: 0.28.3 + 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 + + /import-lazy/4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string/4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini/1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /is-alphabetical/1.0.4: + resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} + dev: true + + /is-alphanumerical/1.0.4: + resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} + dependencies: + is-alphabetical: 1.0.4 + is-decimal: 1.0.4 + dev: true + + /is-arrayish/0.2.1: + resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=} + dev: true + + /is-arrayish/0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: true + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-buffer/2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: true + + /is-core-module/2.6.0: + resolution: {integrity: sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-decimal/1.0.4: + resolution: {integrity: sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==} + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point/1.0.0: + resolution: {integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs=} + engines: {node: '>=0.10.0'} + dependencies: + number-is-nan: 1.0.1 + dev: true + + /is-fullwidth-code-point/3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob/4.0.1: + resolution: {integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-hexadecimal/1.0.4: + resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-plain-obj/1.1.0: + resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-obj/2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: true + + /is-regexp/2.1.0: + resolution: {integrity: sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==} + engines: {node: '>=6'} + dev: true + + /is-typedarray/1.0.0: + resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=} + dev: true + + /is-unicode-supported/0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /isarray/1.0.0: + resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml/3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse/1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} + dev: true + + /json5/2.2.0: + resolution: {integrity: sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + minimist: 1.2.5 + dev: true + + /kind-of/6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /kleur/4.1.4: + resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==} + engines: {node: '>=6'} + dev: true + + /known-css-properties/0.21.0: + resolution: {integrity: sha512-sZLUnTqimCkvkgRS+kbPlYW5o8q5w1cu+uIisKpEWkj31I8mx8kNG162DwRav8Zirkva6N5uoFsm9kzK4mUXjw==} + dev: true + + /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 + + /lines-and-columns/1.1.6: + resolution: {integrity: sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=} + dev: true + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash.clonedeep/4.5.0: + resolution: {integrity: sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=} + dev: true + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.truncate/4.4.2: + resolution: {integrity: sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=} + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols/4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /longest-streak/2.0.4: + resolution: {integrity: sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==} + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string/0.25.7: + resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /map-obj/1.0.1: + resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj/4.2.1: + resolution: {integrity: sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==} + engines: {node: '>=8'} + dev: true + + /mathml-tag-names/2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + dev: true + + /mdast-util-from-markdown/0.8.5: + resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-to-string: 2.0.0 + micromark: 2.11.4 + parse-entities: 2.0.0 + unist-util-stringify-position: 2.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /mdast-util-to-markdown/0.6.5: + resolution: {integrity: sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==} + dependencies: + '@types/unist': 2.0.6 + longest-streak: 2.0.4 + mdast-util-to-string: 2.0.0 + parse-entities: 2.0.0 + repeat-string: 1.6.1 + zwitch: 1.0.5 + dev: true + + /mdast-util-to-string/2.0.0: + resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} + dev: true + + /mdsvex/0.9.8_svelte@3.42.6: + resolution: {integrity: sha512-5QvThjRKoKkGH00qdHxLZ5ROd80RgGiJvM2B9opeFreaiGFTLoKKFUgEBCslLrwM24cVGJLmIM3rR83OFDf3tQ==} + peerDependencies: + svelte: 3.x + dependencies: + '@types/unist': 2.0.6 + prism-svelte: 0.4.7 + prismjs: 1.24.1 + svelte: 3.42.6 + vfile-message: 2.0.4 + dev: true + + /meow/9.0.0: + resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} + engines: {node: '>=10'} + dependencies: + '@types/minimist': 1.2.2 + camelcase-keys: 6.2.2 + decamelize: 1.2.0 + decamelize-keys: 1.1.0 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + dev: true + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromark/2.11.4: + resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} + dependencies: + debug: 4.3.2 + parse-entities: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /micromatch/4.0.4: + resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.0 + dev: true + + /mimic-response/2.1.0: + resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} + engines: {node: '>=8'} + dev: true + + /min-indent/1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch/3.0.4: + resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist-options/4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist/1.2.5: + resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} + dev: true + + /mkdirp-classic/0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: true + + /mkdirp/0.5.5: + resolution: {integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==} + hasBin: true + dependencies: + minimist: 1.2.5 + dev: true + + /mri/1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /nanoid/3.1.25: + resolution: {integrity: sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /napi-build-utils/1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} + dev: true + + /node-abi/2.30.1: + resolution: {integrity: sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==} + dependencies: + semver: 5.7.1 + dev: true + + /node-addon-api/3.2.1: + resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + dev: true + + /node-addon-api/4.1.0: + resolution: {integrity: sha512-Zz1o1BDX2VtduiAt6kgiUl8jX1Vm3NMboljFYKQJ6ee8AGfiTvM2mlZFI3xPbqjs80rCQgiVJI/DjQ/1QJ0HwA==} + dev: true + + /node-releases/1.1.75: + resolution: {integrity: sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==} + dev: true + + /normalize-package-data/2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.20.0 + semver: 5.7.1 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-package-data/3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.0.2 + is-core-module: 2.6.0 + semver: 7.3.5 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range/0.1.2: + resolution: {integrity: sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-selector/0.2.0: + resolution: {integrity: sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=} + dev: true + + /npmlog/4.1.2: + resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==} + dependencies: + are-we-there-yet: 1.1.7 + console-control-strings: 1.1.0 + gauge: 2.7.4 + set-blocking: 2.0.0 + dev: true + + /num2fraction/1.2.2: + resolution: {integrity: sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=} + dev: true + + /number-is-nan/1.0.1: + resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=} + engines: {node: '>=0.10.0'} + dev: true + + /object-assign/4.1.1: + resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} + engines: {node: '>=0.10.0'} + dev: true + + /object-hash/2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + dev: true + + /once/1.4.0: + resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} + 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-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + 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 + + /parse-entities/2.0.0: + resolution: {integrity: sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==} + dependencies: + character-entities: 1.2.4 + character-entities-legacy: 1.1.4 + character-reference-invalid: 1.1.4 + is-alphanumerical: 1.0.4 + is-decimal: 1.0.4 + is-hexadecimal: 1.0.4 + dev: true + + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.14.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.1.6 + 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: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picomatch/2.3.0: + resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==} + engines: {node: '>=8.6'} + dev: true + + /postcss-html/0.36.0_2b33a41d320e3e2012e5b3b0fadc703b: + resolution: {integrity: sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==} + peerDependencies: + postcss: '>=5.0.0' + postcss-syntax: '>=0.36.0' + dependencies: + htmlparser2: 3.10.1 + postcss: 7.0.36 + postcss-syntax: 0.36.2_postcss@7.0.36 + dev: true + + /postcss-less/3.1.4: + resolution: {integrity: sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==} + engines: {node: '>=6.14.4'} + dependencies: + postcss: 7.0.36 + dev: true + + /postcss-media-query-parser/0.2.3: + resolution: {integrity: sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=} + dev: true + + /postcss-resolve-nested-selector/0.1.1: + resolution: {integrity: sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=} + dev: true + + /postcss-safe-parser/4.0.2: + resolution: {integrity: sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.36 + dev: true + + /postcss-sass/0.4.4: + resolution: {integrity: sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg==} + dependencies: + gonzales-pe: 4.3.0 + postcss: 7.0.36 + dev: true + + /postcss-scss/2.1.1: + resolution: {integrity: sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==} + engines: {node: '>=6.0.0'} + dependencies: + postcss: 7.0.36 + dev: true + + /postcss-selector-parser/6.0.6: + resolution: {integrity: sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-syntax/0.36.2_postcss@7.0.36: + resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==} + peerDependencies: + postcss: '>=5.0.0' + dependencies: + postcss: 7.0.36 + dev: true + + /postcss-value-parser/4.1.0: + resolution: {integrity: sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==} + dev: true + + /postcss/7.0.36: + resolution: {integrity: sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==} + engines: {node: '>=6.0.0'} + dependencies: + chalk: 2.4.2 + source-map: 0.6.1 + supports-color: 6.1.0 + dev: true + + /postcss/8.3.6: + resolution: {integrity: sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + colorette: 1.4.0 + nanoid: 3.1.25 + source-map-js: 0.6.2 + dev: true + + /prebuild-install/6.1.4: + resolution: {integrity: sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==} + engines: {node: '>=6'} + hasBin: true + dependencies: + detect-libc: 1.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.5 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 2.30.1 + npmlog: 4.1.2 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 3.1.0 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: true + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-plugin-svelte/2.4.0_prettier@2.3.2+svelte@3.42.6: + resolution: {integrity: sha512-JwJ9bOz4XHLQtiLnX4mTSSDUdhu12WH8sTwy/XTDCSyPlah6IcV7NWeYBZscPEcceu2YnW8Y9sJCP40Z2UH9GA==} + peerDependencies: + prettier: ^1.16.4 || ^2.0.0 + svelte: ^3.2.0 + dependencies: + prettier: 2.3.2 + svelte: 3.42.6 + dev: true + + /prettier/2.3.2: + resolution: {integrity: sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /prism-svelte/0.4.7: + resolution: {integrity: sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ==} + dev: true + + /prismjs/1.24.1: + resolution: {integrity: sha512-mNPsedLuk90RVJioIky8ANZEwYm5w9LcvCXrxHlwf4fNVSn8jEipMybMkWUyyF0JhnC+C4VcOVSBuHRKs1L5Ow==} + dev: true + + /process-nextick-args/2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: true + + /progress/2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true + + /pump/3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + + /punycode/2.1.1: + resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + engines: {node: '>=6'} + dev: true + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru/4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /rc/1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.5 + strip-json-comments: 2.0.1 + dev: true + + /read-pkg-up/7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg/5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readable-stream/2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: true + + /readable-stream/3.6.0: + resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.0 + dev: true + + /reading-time/1.4.0: + resolution: {integrity: sha512-0I9aP583rqQhm6T6Y+pYgYaM4w649VHgQPC24xSWXpn/4qRs08Zu6KgXRf0da6/k7IHoC6idm76fU6vz4mmzHQ==} + dev: true + + /redent/3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /remark-parse/9.0.0: + resolution: {integrity: sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==} + dependencies: + mdast-util-from-markdown: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + + /remark-stringify/9.0.1: + resolution: {integrity: sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==} + dependencies: + mdast-util-to-markdown: 0.6.5 + dev: true + + /remark/13.0.0: + resolution: {integrity: sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==} + dependencies: + remark-parse: 9.0.0 + remark-stringify: 9.0.1 + unified: 9.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /repeat-string/1.6.1: + resolution: {integrity: sha1-jcrkcOHIirwtYA//Sndihtp15jc=} + engines: {node: '>=0.10'} + dev: true + + /require-from-string/2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /require-relative/0.8.7: + resolution: {integrity: sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=} + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from/5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve/1.20.0: + resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==} + dependencies: + is-core-module: 2.6.0 + path-parse: 1.0.7 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf/2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + hasBin: true + dependencies: + glob: 7.1.7 + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.1.7 + dev: true + + /rollup/2.56.3: + resolution: {integrity: sha512-Au92NuznFklgQCUcV96iXlxUbHuB1vQMaH76DHl5M11TotjOHwqk9CwcrT78+Tnv4FN9uTBxq6p4EJoYkpyekg==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /sade/1.7.4: + resolution: {integrity: sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==} + engines: {node: '>= 6'} + dependencies: + mri: 1.2.0 + dev: true + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-buffer/5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /sander/0.5.1: + resolution: {integrity: sha1-dB4kXiMfB8r7b98PEzrfohalAq0=} + dependencies: + es6-promise: 3.3.1 + graceful-fs: 4.2.8 + mkdirp: 0.5.5 + rimraf: 2.7.1 + dev: true + + /sass/1.41.0: + resolution: {integrity: sha512-wb8nT60cjo9ZZMcHzG7TzdbFtCAmHEKWrH+zAdScPb4ZxL64WQBnGdbp5nwlenW5wJPcHva1JWmVa0h6iqA5eg==} + engines: {node: '>=8.9.0'} + hasBin: true + dependencies: + chokidar: 3.5.2 + dev: true + + /semver/5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + + /semver/6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver/7.3.5: + resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /set-blocking/2.0.0: + resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} + dev: true + + /sharp/0.28.3: + resolution: {integrity: sha512-21GEP45Rmr7q2qcmdnjDkNP04Ooh5v0laGS5FDpojOO84D1DJwUijLiSq8XNNM6e8aGXYtoYRh3sVNdm8NodMA==} + engines: {node: '>=10'} + requiresBuild: true + dependencies: + color: 3.2.1 + detect-libc: 1.0.3 + node-addon-api: 3.2.1 + prebuild-install: 6.1.4 + semver: 7.3.5 + simple-get: 3.1.0 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: true + + /sharp/0.29.1: + resolution: {integrity: sha512-DpgdAny9TuS+oWCQ7MRS8XyY9x6q1+yW3a5wNx0J3HrGuB/Jot/8WcT+lElHY9iJu2pwtegSGxqMaqFiMhs4rQ==} + engines: {node: '>=12.13.0'} + requiresBuild: true + dependencies: + color: 4.0.1 + detect-libc: 1.0.3 + node-addon-api: 4.1.0 + prebuild-install: 6.1.4 + semver: 7.3.5 + simple-get: 3.1.0 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: true + + /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 + + /signal-exit/3.0.4: + resolution: {integrity: sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==} + dev: true + + /simple-concat/1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + dev: true + + /simple-get/3.1.0: + resolution: {integrity: sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==} + dependencies: + decompress-response: 4.2.1 + once: 1.4.0 + simple-concat: 1.0.1 + dev: true + + /simple-swizzle/0.2.2: + resolution: {integrity: sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=} + dependencies: + is-arrayish: 0.3.2 + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slice-ansi/4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /sorcery/0.10.0: + resolution: {integrity: sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=} + hasBin: true + dependencies: + buffer-crc32: 0.2.13 + minimist: 1.2.5 + sander: 0.5.1 + sourcemap-codec: 1.4.8 + dev: true + + /source-map-js/0.6.2: + resolution: {integrity: sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.5.7: + resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map/0.7.3: + resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==} + engines: {node: '>= 8'} + dev: true + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + dev: true + + /spdx-correct/3.1.1: + resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.10 + dev: true + + /spdx-exceptions/2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse/3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.10 + dev: true + + /spdx-license-ids/3.0.10: + resolution: {integrity: sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==} + dev: true + + /specificity/0.4.1: + resolution: {integrity: sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==} + hasBin: true + dev: true + + /sprintf-js/1.0.3: + resolution: {integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=} + dev: true + + /string-width/1.0.2: + resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=} + engines: {node: '>=0.10.0'} + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: true + + /string-width/4.2.2: + resolution: {integrity: sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.0 + dev: true + + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /string_decoder/1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi/3.0.1: + resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /strip-ansi/6.0.0: + resolution: {integrity: sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-indent/3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments/2.0.1: + resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} + engines: {node: '>=0.10.0'} + dev: true + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /style-search/0.1.0: + resolution: {integrity: sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=} + dev: true + + /stylelint-a11y/1.2.3_stylelint@13.13.1: + resolution: {integrity: sha512-S/iiKFUsYBfa4suxP0pYQqoPB9R1+SnvxVuzHHlz9al0IWxLZzXlnZEqEez0zNOhVh5iO3rATUmDnbZE5wm/pQ==} + engines: {node: '>=8.7.0'} + peerDependencies: + stylelint: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 + dependencies: + stylelint: 13.13.1 + dev: true + + /stylelint-config-recommended-scss/4.3.0_d55469ff7b1b68c43b61270d19a60ab6: + resolution: {integrity: sha512-/noGjXlO8pJTr/Z3qGMoaRFK8n1BFfOqmAbX1RjTIcl4Yalr+LUb1zb9iQ7pRx1GsEBXOAm4g2z5/jou/pfMPg==} + peerDependencies: + stylelint: ^10.1.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 + stylelint-scss: ^3.0.0 + dependencies: + stylelint: 13.13.1 + stylelint-config-recommended: 5.0.0_stylelint@13.13.1 + stylelint-scss: 3.21.0_stylelint@13.13.1 + dev: true + + /stylelint-config-recommended/5.0.0_stylelint@13.13.1: + resolution: {integrity: sha512-c8aubuARSu5A3vEHLBeOSJt1udOdS+1iue7BmJDTSXoCBmfEQmmWX+59vYIj3NQdJBY6a/QRv1ozVFpaB9jaqA==} + peerDependencies: + stylelint: ^13.13.0 + dependencies: + stylelint: 13.13.1 + dev: true + + /stylelint-config-standard/22.0.0_stylelint@13.13.1: + resolution: {integrity: sha512-uQVNi87SHjqTm8+4NIP5NMAyY/arXrBgimaaT7skvRfE9u3JKXRK9KBkbr4pVmeciuCcs64kAdjlxfq6Rur7Hw==} + peerDependencies: + stylelint: ^13.13.0 + dependencies: + stylelint: 13.13.1 + stylelint-config-recommended: 5.0.0_stylelint@13.13.1 + dev: true + + /stylelint-scss/3.21.0_stylelint@13.13.1: + resolution: {integrity: sha512-CMI2wSHL+XVlNExpauy/+DbUcB/oUZLARDtMIXkpV/5yd8nthzylYd1cdHeDMJVBXeYHldsnebUX6MoV5zPW4A==} + engines: {node: '>=8'} + peerDependencies: + stylelint: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 + dependencies: + lodash: 4.17.21 + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.1 + postcss-selector-parser: 6.0.6 + postcss-value-parser: 4.1.0 + stylelint: 13.13.1 + dev: true + + /stylelint/13.13.1: + resolution: {integrity: sha512-Mv+BQr5XTUrKqAXmpqm6Ddli6Ief+AiPZkRsIrAoUKFuq/ElkUh9ZMYxXD0iQNZ5ADghZKLOWz1h7hTClB7zgQ==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + '@stylelint/postcss-css-in-js': 0.37.2_2b33a41d320e3e2012e5b3b0fadc703b + '@stylelint/postcss-markdown': 0.36.2_2b33a41d320e3e2012e5b3b0fadc703b + autoprefixer: 9.8.6 + balanced-match: 2.0.0 + chalk: 4.1.2 + cosmiconfig: 7.0.1 + debug: 4.3.2 + execall: 2.0.0 + fast-glob: 3.2.7 + fastest-levenshtein: 1.0.12 + file-entry-cache: 6.0.1 + get-stdin: 8.0.0 + global-modules: 2.0.0 + globby: 11.0.4 + globjoin: 0.1.4 + html-tags: 3.1.0 + ignore: 5.1.8 + import-lazy: 4.0.0 + imurmurhash: 0.1.4 + known-css-properties: 0.21.0 + lodash: 4.17.21 + log-symbols: 4.1.0 + mathml-tag-names: 2.1.3 + meow: 9.0.0 + micromatch: 4.0.4 + normalize-selector: 0.2.0 + postcss: 7.0.36 + postcss-html: 0.36.0_2b33a41d320e3e2012e5b3b0fadc703b + postcss-less: 3.1.4 + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.1 + postcss-safe-parser: 4.0.2 + postcss-sass: 0.4.4 + postcss-scss: 2.1.1 + postcss-selector-parser: 6.0.6 + postcss-syntax: 0.36.2_postcss@7.0.36 + postcss-value-parser: 4.1.0 + resolve-from: 5.0.0 + slash: 3.0.0 + specificity: 0.4.1 + string-width: 4.2.2 + strip-ansi: 6.0.0 + style-search: 0.1.0 + sugarss: 2.0.0 + svg-tags: 1.0.0 + table: 6.7.1 + v8-compile-cache: 2.3.0 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /sugarss/2.0.0: + resolution: {integrity: sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==} + dependencies: + postcss: 7.0.36 + dev: true + + /supports-color/5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color/6.1.0: + resolution: {integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==} + engines: {node: '>=6'} + dependencies: + has-flag: 3.0.0 + 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-awesome/2.3.2: + resolution: {integrity: sha512-odkwkVSYEARI/4CskjwoI7KIhds1Ui74H1VFAifWuDoczY+JpPeJuBwDqgo8imM7Bd76U+ns7Yf1iQqveHnx5Q==} + dependencies: + svelte: 3.42.6 + dev: true + + /svelte-check/2.2.6_sass@1.41.0+svelte@3.42.6: + resolution: {integrity: sha512-oJux/afbmcZO+N+ADXB88h6XANLie8Y2rh2qBlhgfkpr2c3t/q/T0w2JWrHqagaDL8zeNwO8a8RVFBkrRox8gg==} + hasBin: true + peerDependencies: + svelte: ^3.24.0 + dependencies: + chalk: 4.1.2 + chokidar: 3.5.2 + fast-glob: 3.2.7 + import-fresh: 3.3.0 + minimist: 1.2.5 + sade: 1.7.4 + source-map: 0.7.3 + svelte: 3.42.6 + svelte-preprocess: 4.9.4_9493159d4f4ad9e3e8deb8d577a9601b + typescript: 4.4.3 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - node-sass + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + dev: true + + /svelte-feather-icons/3.5.0: + resolution: {integrity: sha512-AO6vwbI+WH8xouZRIxyenUV2olSAjp0QFgBa4esyS9ZxvBmKkRu9VTfgbMW0F1N7QTOWbMpgaForsnOcFGfXeg==} + dependencies: + svelte: 3.42.6 + dev: true + + /svelte-hmr/0.14.7_svelte@3.42.6: + resolution: {integrity: sha512-pDrzgcWSoMaK6AJkBWkmgIsecW0GChxYZSZieIYfCP0v2oPyx2CYU/zm7TBIcjLVUPP714WxmViE9Thht4etog==} + peerDependencies: + svelte: '>=3.19.0' + dependencies: + svelte: 3.42.6 + dev: true + + /svelte-preprocess-import-assets/0.1.3_svelte@3.42.6: + resolution: {integrity: sha512-ikGQn2FzY6vnvyYseAMV4ECjBtKqxmw5yT3Ukq7LgHTVeWZm8TD5CnWIFHyKSjLEKSGU7pnhSN+fXqsd4jroIw==} + peerDependencies: + svelte: ^3.37.0 + dependencies: + magic-string: 0.25.7 + svelte: 3.42.6 + dev: true + + /svelte-preprocess/4.9.4_9493159d4f4ad9e3e8deb8d577a9601b: + resolution: {integrity: sha512-Z0mUQBGtE+ZZSv/HerRSHe7ukJokxjiPeHe7iPOIXseEoRw51H3K/Vh6OMIMstetzZ11vWO9rCsXSD/uUUArmA==} + engines: {node: '>= 9.11.2'} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 + node-sass: '*' + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.54.7 + sugarss: ^2.0.0 + svelte: ^3.23.0 + typescript: ^3.9.5 || ^4.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + node-sass: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.5 + '@types/sass': 1.16.1 + detect-indent: 6.1.0 + magic-string: 0.25.7 + sass: 1.41.0 + sorcery: 0.10.0 + strip-indent: 3.0.0 + svelte: 3.42.6 + typescript: 4.4.3 + dev: true + + /svelte-preprocess/4.9.4_sass@1.41.0+svelte@3.42.6: + resolution: {integrity: sha512-Z0mUQBGtE+ZZSv/HerRSHe7ukJokxjiPeHe7iPOIXseEoRw51H3K/Vh6OMIMstetzZ11vWO9rCsXSD/uUUArmA==} + engines: {node: '>= 9.11.2'} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 + node-sass: '*' + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.54.7 + sugarss: ^2.0.0 + svelte: ^3.23.0 + typescript: ^3.9.5 || ^4.0.0 + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + node-sass: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.5 + '@types/sass': 1.16.1 + detect-indent: 6.1.0 + magic-string: 0.25.7 + sass: 1.41.0 + sorcery: 0.10.0 + strip-indent: 3.0.0 + svelte: 3.42.6 + dev: true + + /svelte/3.42.6: + resolution: {integrity: sha512-lAcryr9Do2PeGtbodspX5I4kWj4yWYAa2WGpDCwzNkP3y8WZTxigMd4/TMO1rBZEOkMYGn4ZXrbAlSEGhK6q3w==} + engines: {node: '>= 8'} + dev: true + + /svg-tags/1.0.0: + resolution: {integrity: sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=} + dev: true + + /table/6.7.1: + resolution: {integrity: sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==} + engines: {node: '>=10.0.0'} + dependencies: + ajv: 8.6.3 + lodash.clonedeep: 4.5.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.2 + strip-ansi: 6.0.0 + dev: true + + /tar-fs/2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: true + + /tar-stream/2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + + /text-table/0.2.0: + resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} + engines: {node: '>=4'} + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /trim-newlines/3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + + /trough/1.0.5: + resolution: {integrity: sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==} + dev: true + + /tunnel-agent/0.6.0: + resolution: {integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=} + dependencies: + safe-buffer: 5.2.1 + 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.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest/0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest/0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /typedarray-to-buffer/3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: true + + /typescript/4.4.3: + resolution: {integrity: sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /unified/9.2.2: + resolution: {integrity: sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==} + dependencies: + bail: 1.0.5 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 2.1.0 + trough: 1.0.5 + vfile: 4.2.1 + dev: true + + /unist-util-find-all-after/3.0.2: + resolution: {integrity: sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ==} + dependencies: + unist-util-is: 4.1.0 + dev: true + + /unist-util-is/4.1.0: + resolution: {integrity: sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==} + dev: true + + /unist-util-stringify-position/2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + dependencies: + '@types/unist': 2.0.6 + dev: true + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.1.1 + dev: true + + /util-deprecate/1.0.2: + resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=} + dev: true + + /v8-compile-cache/2.3.0: + resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} + dev: true + + /validate-npm-package-license/3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.1.1 + spdx-expression-parse: 3.0.1 + dev: true + + /vanilla-lazyload/17.4.0: + resolution: {integrity: sha512-4IVX93uLEgQGBdSCaSE1XJgeNNT1+sV8PKiImM21EkDGJBH3tTWL9wYrMA4xT5C2EIEfw8WkinUxUG+uMY2ZyA==} + dev: true + + /vfile-message/2.0.4: + resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} + dependencies: + '@types/unist': 2.0.6 + unist-util-stringify-position: 2.0.3 + dev: true + + /vfile/4.2.1: + resolution: {integrity: sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==} + dependencies: + '@types/unist': 2.0.6 + is-buffer: 2.0.5 + unist-util-stringify-position: 2.0.3 + vfile-message: 2.0.4 + dev: true + + /vite-imagetools/3.6.8: + resolution: {integrity: sha512-hGtUhcvSIMXBe/yg215ccrszXG/LqU4aaFonfa2Oq5GLTZ91MJIaX7UWWF9cl+siZJ456ZUawpYqCeYIuurdmQ==} + engines: {node: '>=12.0.0'} + dependencies: + '@rollup/pluginutils': 4.1.1 + imagetools-core: 2.7.6 + magic-string: 0.25.7 + dev: true + + /vite/2.5.7: + resolution: {integrity: sha512-hyUoWmRPhjN1aI+ZSBqDINKdIq7aokHE2ZXiztOg4YlmtpeQtMwMeyxv6X9YxHZmvGzg/js/eATM9Z1nwyakxg==} + engines: {node: '>=12.2.0'} + hasBin: true + dependencies: + esbuild: 0.12.28 + postcss: 8.3.6 + resolve: 1.20.0 + rollup: 2.56.3 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /which/1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.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 + + /wide-align/1.1.3: + resolution: {integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==} + dependencies: + string-width: 1.0.2 + 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: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} + dev: true + + /write-file-atomic/3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.4 + typedarray-to-buffer: 3.1.5 + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml/1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true + + /yargs-parser/20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /zwitch/1.0.5: + resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} + dev: true diff --git a/src/app.html b/src/app.html new file mode 100644 index 0000000..e11746b --- /dev/null +++ b/src/app.html @@ -0,0 +1,13 @@ + + + + + + + + %svelte.head% + + +
%svelte.body%
+ + diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..63908c6 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/hooks.js b/src/hooks.js new file mode 100644 index 0000000..232e1f7 --- /dev/null +++ b/src/hooks.js @@ -0,0 +1,97 @@ +// https://gist.github.com/acoyfellow/d8e86979c66ebea25e1643594e38be73 +// https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP +// https://scotthelme.co.uk/content-security-policy-an-introduction/ +// scanner: https://securityheaders.com/ + +const rootDomain = import.meta.env.VITE_DOMAIN; // or your server IP for dev + +const directives = { + 'base-uri': ["'self'"], + 'child-src': ["'self'"], + 'connect-src': ["'self'", 'ws://localhost:*', process.env['WORKER_URL']], + // 'connect-src': ["'self'", 'ws://localhost:*', 'https://hcaptcha.com', 'https://*.hcaptcha.com'], + 'img-src': ["'self'", 'data:'], + 'font-src': ["'self'", 'data:'], + 'form-action': ["'self'"], + 'frame-ancestors': ["'self'"], + 'frame-src': [ + "'self'", + // "https://*.stripe.com", + // "https://*.facebook.com", + // "https://*.facebook.net", + // 'https://hcaptcha.com', + // 'https://*.hcaptcha.com', + ], + 'manifest-src': ["'self'"], + 'media-src': ["'self'", 'data:'], + 'object-src': ["'none'"], + 'style-src': ["'self'", "'unsafe-inline'"], + // 'style-src': ["'self'", "'unsafe-inline'", 'https://hcaptcha.com', 'https://*.hcaptcha.com'], + 'default-src': [ + "'self'", + rootDomain, + `ws://${rootDomain}`, + // 'https://*.google.com', + // 'https://*.googleapis.com', + // 'https://*.firebase.com', + // 'https://*.gstatic.com', + // 'https://*.cloudfunctions.net', + // 'https://*.algolia.net', + // 'https://*.facebook.com', + // 'https://*.facebook.net', + // 'https://*.stripe.com', + // 'https://*.sentry.io', + ], + 'script-src': [ + "'self'", + "'unsafe-inline'", + // 'https://*.stripe.com', + // 'https://*.facebook.com', + // 'https://*.facebook.net', + // 'https://hcaptcha.com', + // 'https://*.hcaptcha.com', + // 'https://*.sentry.io', + // 'https://polyfill.io', + ], + 'worker-src': ["'self'"], + // remove report-to & report-uri if you do not want to use Sentry reporting + 'report-to': ["'csp-endpoint'"], + 'report-uri': [ + `https://sentry.io/api/${import.meta.env.VITE_SENTRY_PROJECT_ID}/security/?sentry_key=${ + import.meta.env.VITE_SENTRY_KEY + }`, + ], +}; + +const csp = Object.entries(directives) + .map(([key, arr]) => key + ' ' + arr.join(' ')) + .join('; '); + +export async function handle({ request, resolve }) { + const response = await resolve(request); + console.log('handle', { ...response.headers }); + return { + ...response, + headers: { + ...response.headers, + 'X-Frame-Options': 'SAMEORIGIN', + 'Referrer-Policy': 'no-referrer', + 'Permissions-Policy': + 'accelerometer=(), autoplay=(), camera=(), document-domain=(), encrypted-media=(), fullscreen=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), sync-xhr=(), usb=(), xr-spatial-tracking=(), geolocation=()', + 'X-Content-Type-Options': 'nosniff', + /* Switch from Content-Security-Policy-Report-Only to Content-Security-Policy once you are satisifed policy is what you want + * on switch comment out the Report-Only line + */ + 'Content-Security-Policy-Report-Only': csp, + // 'Content-Security-Policy': csp, + 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload', + // remove/change lines below if you do not want to use sentry for reporting + 'Expect-CT': `max-age=86400, report-uri="https://sentry.io/api/${ + import.meta.env.VITE_SENTRY_PROJECT_ID + }/security/?sentry_key=${import.meta.env.VITE_SENTRY_KEY}"`, + 'Report-To': `{group: "csp-endpoint", "max_age": 10886400, "endpoints": [{"url": "https://sentry.io/api/${ + import.meta.env.VITE_SENTRY_PROJECT_ID + }/security/?sentry_key=${import.meta.env.VITE_SENTRY_KEY}"}]}`, + }, + }; +} diff --git a/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph-square.jpg b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph-square.jpg new file mode 100644 index 0000000..2007949 Binary files /dev/null and b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph-square.jpg differ diff --git a/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph.jpg b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph.jpg new file mode 100644 index 0000000..5f7059b Binary files /dev/null and b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph.jpg differ diff --git a/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-twitter.jpg b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-twitter.jpg new file mode 100644 index 0000000..5034341 Binary files /dev/null and b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-twitter.jpg differ diff --git a/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out.jpg b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out.jpg new file mode 100644 index 0000000..3f07145 Binary files /dev/null and b/src/lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out.jpg differ diff --git a/src/lib/assets/blog/folding-camera/folding-camera-open-graph-square.jpg b/src/lib/assets/blog/folding-camera/folding-camera-open-graph-square.jpg new file mode 100644 index 0000000..31b996a Binary files /dev/null and b/src/lib/assets/blog/folding-camera/folding-camera-open-graph-square.jpg differ diff --git a/src/lib/assets/blog/folding-camera/folding-camera-open-graph.jpg b/src/lib/assets/blog/folding-camera/folding-camera-open-graph.jpg new file mode 100644 index 0000000..cf2ebb7 Binary files /dev/null and b/src/lib/assets/blog/folding-camera/folding-camera-open-graph.jpg differ diff --git a/src/lib/assets/blog/folding-camera/folding-camera-twitter.jpg b/src/lib/assets/blog/folding-camera/folding-camera-twitter.jpg new file mode 100644 index 0000000..4e6eed5 Binary files /dev/null and b/src/lib/assets/blog/folding-camera/folding-camera-twitter.jpg differ diff --git a/src/lib/assets/blog/folding-camera/folding-camera.jpg b/src/lib/assets/blog/folding-camera/folding-camera.jpg new file mode 100644 index 0000000..4fbfb2f Binary files /dev/null and b/src/lib/assets/blog/folding-camera/folding-camera.jpg differ diff --git a/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph-square.jpg b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph-square.jpg new file mode 100644 index 0000000..2174e1d Binary files /dev/null and b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph-square.jpg differ diff --git a/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph.jpg b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph.jpg new file mode 100644 index 0000000..ab84e97 Binary files /dev/null and b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph.jpg differ diff --git a/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-twitter.jpg b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-twitter.jpg new file mode 100644 index 0000000..a0ee6ac Binary files /dev/null and b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-twitter.jpg differ diff --git a/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera.jpg b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera.jpg new file mode 100644 index 0000000..6754ac8 Binary files /dev/null and b/src/lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera.jpg differ diff --git a/src/lib/assets/home/home-open-graph-square.jpg b/src/lib/assets/home/home-open-graph-square.jpg new file mode 100644 index 0000000..84e305d Binary files /dev/null and b/src/lib/assets/home/home-open-graph-square.jpg differ diff --git a/src/lib/assets/home/home-open-graph.jpg b/src/lib/assets/home/home-open-graph.jpg new file mode 100644 index 0000000..a95ebe5 Binary files /dev/null and b/src/lib/assets/home/home-open-graph.jpg differ diff --git a/src/lib/assets/home/home-twitter.jpg b/src/lib/assets/home/home-twitter.jpg new file mode 100644 index 0000000..ce5d264 Binary files /dev/null and b/src/lib/assets/home/home-twitter.jpg differ diff --git a/src/lib/assets/home/home.jpg b/src/lib/assets/home/home.jpg new file mode 100644 index 0000000..dfc77bc Binary files /dev/null and b/src/lib/assets/home/home.jpg differ diff --git a/src/lib/components/BannerImage.svelte b/src/lib/components/BannerImage.svelte new file mode 100644 index 0000000..bcf8935 --- /dev/null +++ b/src/lib/components/BannerImage.svelte @@ -0,0 +1,40 @@ + + + + {#each sources as { srcset, type }} + + {/each} + + + + diff --git a/src/lib/components/BlogPost.svelte b/src/lib/components/BlogPost.svelte new file mode 100644 index 0000000..800f018 --- /dev/null +++ b/src/lib/components/BlogPost.svelte @@ -0,0 +1,75 @@ + + + + + +

{title}

diff --git a/src/lib/components/BlogPostSummary.svelte b/src/lib/components/BlogPostSummary.svelte new file mode 100644 index 0000000..63b6cc7 --- /dev/null +++ b/src/lib/components/BlogPostSummary.svelte @@ -0,0 +1,84 @@ + + +
+
+

+ {postTitle} +

+

{dateString}

+

{seoMetaDescription}

+ +
+
+ + diff --git a/src/lib/components/BlogRoll.svelte b/src/lib/components/BlogRoll.svelte new file mode 100644 index 0000000..9954b9b --- /dev/null +++ b/src/lib/components/BlogRoll.svelte @@ -0,0 +1,34 @@ + + +
+

BLOG POSTS

+ {#each displayPosts as post, index} +
+ +
+ {:else} +

No posts yet!

+ {/each} + {#if showPosts < postCount} + + {/if} +
diff --git a/src/lib/components/Card.svelte b/src/lib/components/Card.svelte new file mode 100644 index 0000000..8f0531d --- /dev/null +++ b/src/lib/components/Card.svelte @@ -0,0 +1,25 @@ + + +
+
+ +
+
+ + diff --git a/src/lib/components/ExternalLink.svelte b/src/lib/components/ExternalLink.svelte new file mode 100644 index 0000000..d181c0d --- /dev/null +++ b/src/lib/components/ExternalLink.svelte @@ -0,0 +1,8 @@ + + + diff --git a/src/lib/components/Icons/Camera.svelte b/src/lib/components/Icons/Camera.svelte new file mode 100644 index 0000000..f0492be --- /dev/null +++ b/src/lib/components/Icons/Camera.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/Icons/Email.svelte b/src/lib/components/Icons/Email.svelte new file mode 100644 index 0000000..7c3d77e --- /dev/null +++ b/src/lib/components/Icons/Email.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/Icons/Facebook.svelte b/src/lib/components/Icons/Facebook.svelte new file mode 100644 index 0000000..9272cb3 --- /dev/null +++ b/src/lib/components/Icons/Facebook.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/Icons/GitHub.svelte b/src/lib/components/Icons/GitHub.svelte new file mode 100644 index 0000000..b9ea766 --- /dev/null +++ b/src/lib/components/Icons/GitHub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/Icons/HeartOutline.svelte b/src/lib/components/Icons/HeartOutline.svelte new file mode 100644 index 0000000..a6e9d98 --- /dev/null +++ b/src/lib/components/Icons/HeartOutline.svelte @@ -0,0 +1,6 @@ + + + diff --git a/src/lib/components/Icons/HeartSolid.svelte b/src/lib/components/Icons/HeartSolid.svelte new file mode 100644 index 0000000..9131e4d --- /dev/null +++ b/src/lib/components/Icons/HeartSolid.svelte @@ -0,0 +1,6 @@ + + + diff --git a/src/lib/components/Icons/LinkedIn.svelte b/src/lib/components/Icons/LinkedIn.svelte new file mode 100644 index 0000000..7e21aef --- /dev/null +++ b/src/lib/components/Icons/LinkedIn.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/Icons/Telegram.svelte b/src/lib/components/Icons/Telegram.svelte new file mode 100644 index 0000000..da3fcc3 --- /dev/null +++ b/src/lib/components/Icons/Telegram.svelte @@ -0,0 +1,25 @@ + + + + + + + diff --git a/src/lib/components/Icons/Tiktok.svelte b/src/lib/components/Icons/Tiktok.svelte new file mode 100644 index 0000000..36d9032 --- /dev/null +++ b/src/lib/components/Icons/Tiktok.svelte @@ -0,0 +1,25 @@ + + + + + + + diff --git a/src/lib/components/Icons/Twitter.svelte b/src/lib/components/Icons/Twitter.svelte new file mode 100644 index 0000000..ff3b57f --- /dev/null +++ b/src/lib/components/Icons/Twitter.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/Icons/View.svelte b/src/lib/components/Icons/View.svelte new file mode 100644 index 0000000..acd3c58 --- /dev/null +++ b/src/lib/components/Icons/View.svelte @@ -0,0 +1,6 @@ + + + diff --git a/src/lib/components/Icons/Wire.svelte b/src/lib/components/Icons/Wire.svelte new file mode 100644 index 0000000..cbbdb24 --- /dev/null +++ b/src/lib/components/Icons/Wire.svelte @@ -0,0 +1,14 @@ + + + + + + + diff --git a/src/lib/components/Icons/index.js b/src/lib/components/Icons/index.js new file mode 100644 index 0000000..d85186f --- /dev/null +++ b/src/lib/components/Icons/index.js @@ -0,0 +1 @@ +export const DEFAULT_ICON_SIZE = '24'; diff --git a/src/lib/components/Link.svelte b/src/lib/components/Link.svelte new file mode 100644 index 0000000..ca857c8 --- /dev/null +++ b/src/lib/components/Link.svelte @@ -0,0 +1,8 @@ + + + diff --git a/src/lib/components/PWA.svelte b/src/lib/components/PWA.svelte new file mode 100644 index 0000000..1225e11 --- /dev/null +++ b/src/lib/components/PWA.svelte @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/lib/components/PostViewsLikes.svelte b/src/lib/components/PostViewsLikes.svelte new file mode 100644 index 0000000..0e9ff21 --- /dev/null +++ b/src/lib/components/PostViewsLikes.svelte @@ -0,0 +1,77 @@ + + +{views} +{#if liked} + +{:else} + +{/if} +{#await likesPromise} + {likes} +{:then updatedLikes} + {updatedLikes.count ?? likes} +{:catch} + {likes} +{/await} diff --git a/src/lib/components/RodneyLabCredit.svelte b/src/lib/components/RodneyLabCredit.svelte new file mode 100644 index 0000000..1970172 --- /dev/null +++ b/src/lib/components/RodneyLabCredit.svelte @@ -0,0 +1,33 @@ + + +
+ A project by Rodney Lab Logo + RODNEY LAB. +
+ + diff --git a/src/lib/components/SEO/OpenGraph.svelte b/src/lib/components/SEO/OpenGraph.svelte new file mode 100644 index 0000000..2c8e758 --- /dev/null +++ b/src/lib/components/SEO/OpenGraph.svelte @@ -0,0 +1,41 @@ + + + + + + + + + + {#if image} + + + + + {/if} + {#if squareImage} + + + + + {/if} + {#if article} + + + + + {/if} + diff --git a/src/lib/components/SEO/SchemaOrg.svelte b/src/lib/components/SEO/SchemaOrg.svelte new file mode 100644 index 0000000..f11030b --- /dev/null +++ b/src/lib/components/SEO/SchemaOrg.svelte @@ -0,0 +1,208 @@ + + + + {@html jsonLdScript} + diff --git a/src/lib/components/SEO/Twitter.svelte b/src/lib/components/SEO/Twitter.svelte new file mode 100644 index 0000000..ab04cce --- /dev/null +++ b/src/lib/components/SEO/Twitter.svelte @@ -0,0 +1,29 @@ + + + + + {#if image} + + {/if} + {#if twitterUsername} + + + {/if} + + + {#if article && timeToRead > 0} + + + {/if} + diff --git a/src/lib/components/SEO/index.svelte b/src/lib/components/SEO/index.svelte new file mode 100644 index 0000000..8045afc --- /dev/null +++ b/src/lib/components/SEO/index.svelte @@ -0,0 +1,123 @@ + + + + {pageTitle} + + + + + + + + diff --git a/src/lib/config/website.js b/src/lib/config/website.js new file mode 100644 index 0000000..f8fda32 --- /dev/null +++ b/src/lib/config/website.js @@ -0,0 +1,25 @@ +const facebookPageName = import.meta.env ? import.meta.env.VITE_FACEBOOK_PAGE : ''; + +const website = { + author: 'Rodney Johnson', + ogLanguage: 'en_GB', + siteLanguage: 'en-GB', + siteTitle: 'SvelteKit Blog Mdx', + siteShortTitle: 'SvelteKit Blog', + siteUrl: import.meta.env ? import.meta.env.VITE_SITE_URL : '', + icon: 'static/icon.png', + backgroundColor: '#1b4079', + themeColor: '#d62828', + contactEmail: import.meta.env ? import.meta.env.VITE_CONTACT_EMAIL : '', + facebookPage: `https://www.facebook.com/${facebookPageName}`, + facebookPageName, + githubPage: import.meta.env ? import.meta.env.VITE_GITHUB_PAGE : '', + linkedinProfile: import.meta.env ? import.meta.env.VITE_LINKEDIN_PROFILE : '', + telegramUsername: import.meta.env ? import.meta.env.VITE_TELEGRAM_USERNAME : '', + tiktokUsername: import.meta.env ? import.meta.env.VITE_TIKTOK_USERNAME : '', + twitterUsername: import.meta.env ? import.meta.env.VITE_TWITTER_USERNAME : '', + twitterUserId: import.meta.env ? import.meta.env.VITE_TWITTER_ID : '', + wireUsername: import.meta.env ? import.meta.env.VITE_WIRE_USERNAME : '', +}; + +export { website as default }; diff --git a/src/lib/constants/entities.js b/src/lib/constants/entities.js new file mode 100644 index 0000000..4458710 --- /dev/null +++ b/src/lib/constants/entities.js @@ -0,0 +1,3 @@ +export const COPYRIGHT_ENTITY = '\u00a9'; // (c) +export const H_ELLIPSIS_ENTITY = '\u2026'; // ... +export const VERTICAL_LINE_ENTITY = '\u007c'; // | diff --git a/src/lib/generated/posts/best-medium-format-camera-for-starting-out.js b/src/lib/generated/posts/best-medium-format-camera-for-starting-out.js new file mode 100644 index 0000000..84b3d02 --- /dev/null +++ b/src/lib/generated/posts/best-medium-format-camera-for-starting-out.js @@ -0,0 +1,28 @@ +import meta from '$lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out.jpg?width=672&metadata'; +import srcsetwebp from '$lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out.jpg?w=1344;672&webp&srcset'; +import srcsetauto from '$lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out.jpg?w=1344;672&jpeg&srcset'; +import ogImage from '$lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph.jpg'; +import ogSquareImage from '$lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-open-graph-square.jpg'; +import twitterImage from '$lib/assets/blog/best-medium-format-camera-for-starting-out/best-medium-format-camera-for-starting-out-twitter.jpg'; + +const { height, src, width } = meta; + +const data = { + slug: 'best-medium-format-camera-for-starting-out', + alt: 'Photograph of a Hasselblad medium format camera with the focusing screen exposed', + width, + height, + src, + sources: [ + { srcset: srcsetwebp, type: 'image/webp' }, + { srcset: srcsetauto, type: 'image/jpeg' }, + ], + dominantColour: '#484848', + placeholder: + 'data:image/jpeg;base64,/9j/2wBDAAwREhMUFBUUFBofGhUaHiIcGhohKC4jJB4hMzg/PTouKC5CRFpMPi5XRTc3VmBRVlpgZmRkQklveXFmeFtlaWf/2wBDAQgMDQwNDw8PDxFgEBIaVmBaYFpgY2NjY2BjYGBiY2NjY2NjY2NjY2NjY2JjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwX/2gAMAwEAAhADEAAAAM+Cev8A/8QAHBABAAEEAwAAAAAAAAAAAAAAAQIAAxMhEZGh/9oACAEBAAE/AM5u2kZDIkS48rMmtnTX/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQIA/9oACAECAQE/AKtkkDf/xAAXEQEAAwAAAAAAAAAAAAAAAAABABEh/9oACAEDAQE/AHKZ/9k=', + ogImage, + ogSquareImage, + twitterImage, +}; + +export { data as default }; diff --git a/src/lib/generated/posts/folding-camera.js b/src/lib/generated/posts/folding-camera.js new file mode 100644 index 0000000..0e4dcc0 --- /dev/null +++ b/src/lib/generated/posts/folding-camera.js @@ -0,0 +1,28 @@ +import meta from '$lib/assets/blog/folding-camera/folding-camera.jpg?width=672&metadata'; +import srcsetwebp from '$lib/assets/blog/folding-camera/folding-camera.jpg?w=1344;672&webp&srcset'; +import srcsetauto from '$lib/assets/blog/folding-camera/folding-camera.jpg?w=1344;672&jpeg&srcset'; +import ogImage from '$lib/assets/blog/folding-camera/folding-camera-open-graph.jpg'; +import ogSquareImage from '$lib/assets/blog/folding-camera/folding-camera-open-graph-square.jpg'; +import twitterImage from '$lib/assets/blog/folding-camera/folding-camera-twitter.jpg'; + +const { height, src, width } = meta; + +const data = { + slug: 'folding-camera', + alt: 'Photograph of a classic folding camera', + width, + height, + src, + sources: [ + { srcset: srcsetwebp, type: 'image/webp' }, + { srcset: srcsetauto, type: 'image/jpeg' }, + ], + dominantColour: '#f8f8f8', + placeholder: + 'data:image/jpeg;base64,/9j/2wBDAAwREhMUFBUUFBofGhUaHiIcGhohKC4jJB4hMzg/PTouKC5CRFpMPi5XRTc3VmBRVlpgZmRkQklveXFmeFtlaWf/2wBDAQgMDQwNDw8PDxFgEBIaVmBaYFpgY2NjY2BjYGBiY2NjY2NjY2NjY2NjY2JjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAACzoQf/xAAcEAABBAMBAAAAAAAAAAAAAAACAQMEIQUQEXH/2gAIAQEAAT8AZSYOSfUrimI8uh8TX//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Af//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Af//Z', + ogImage, + ogSquareImage, + twitterImage, +}; + +export { data as default }; diff --git a/src/lib/generated/posts/twin-lens-reflex-camera.js b/src/lib/generated/posts/twin-lens-reflex-camera.js new file mode 100644 index 0000000..600063a --- /dev/null +++ b/src/lib/generated/posts/twin-lens-reflex-camera.js @@ -0,0 +1,28 @@ +import meta from '$lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera.jpg?width=672&metadata'; +import srcsetwebp from '$lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera.jpg?w=1344;672&webp&srcset'; +import srcsetauto from '$lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera.jpg?w=1344;672&jpeg&srcset'; +import ogImage from '$lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph.jpg'; +import ogSquareImage from '$lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-open-graph-square.jpg'; +import twitterImage from '$lib/assets/blog/twin-lens-reflex-camera/twin-lens-reflex-camera-twitter.jpg'; + +const { height, src, width } = meta; + +const data = { + slug: 'twin-lens-reflex-camera', + alt: 'Photograph of a Rolleicord twin Lens reflex camera', + width, + height, + src, + sources: [ + { srcset: srcsetwebp, type: 'image/webp' }, + { srcset: srcsetauto, type: 'image/jpeg' }, + ], + dominantColour: '#382828', + placeholder: + 'data:image/jpeg;base64,/9j/2wBDAAwREhMUFBUUFBofGhUaHiIcGhohKC4jJB4hMzg/PTouKC5CRFpMPi5XRTc3VmBRVlpgZmRkQklveXFmeFtlaWf/2wBDAQgMDQwNDw8PDxFgEBIaVmBaYFpgY2NjY2BjYGBiY2NjY2NjY2NjY2NjY2JjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMG/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwT/2gAMAwEAAhADEAAAAMtYCr//xAAbEAABBQEBAAAAAAAAAAAAAAABAAIDESFBcf/aAAgBAQABPwCN0eiuZ6i42V//xAAVEQEBAAAAAAAAAAAAAAAAAAABAP/aAAgBAgEBPwBUv//EABYRAQEBAAAAAAAAAAAAAAAAAAEAAv/aAAgBAwEBPwAyN//Z', + ogImage, + ogSquareImage, + twitterImage, +}; + +export { data as default }; diff --git a/src/lib/shared/stores/postViewsLikes.js b/src/lib/shared/stores/postViewsLikes.js new file mode 100644 index 0000000..4ffe5e4 --- /dev/null +++ b/src/lib/shared/stores/postViewsLikes.js @@ -0,0 +1,10 @@ +import { browser } from '$app/env'; +import { writable } from 'svelte/store'; + +export const postViewsLikes = writable(browser ? localStorage.liked || '' : ''); + +postViewsLikes.subscribe((value) => { + if (browser) { + localStorage.liked = value; + } +}); diff --git a/src/lib/styles/index.scss b/src/lib/styles/index.scss new file mode 100644 index 0000000..90e69d7 --- /dev/null +++ b/src/lib/styles/index.scss @@ -0,0 +1 @@ +@import './styles.scss'; diff --git a/src/lib/styles/normalise.css b/src/lib/styles/normalise.css new file mode 100644 index 0000000..2768db4 --- /dev/null +++ b/src/lib/styles/normalise.css @@ -0,0 +1,351 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/src/lib/styles/styles.scss b/src/lib/styles/styles.scss new file mode 100644 index 0000000..eebce19 --- /dev/null +++ b/src/lib/styles/styles.scss @@ -0,0 +1,313 @@ +@charset "UTF-8"; +@use 'sass:math'; + +@import './variables.scss'; + +/* HTML elements */ +*, +:after, +:before { + box-sizing: border-box; +} + +html { + line-height: $line-height-normal; + font-size: $font-size-root; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + font-family: $font-body; + font-size: $font-size-1; + color: $color-text; + text-rendering: optimizeLegibility; +} + +footer { + padding: $spacing-6 $spacing-0; +} + +hr { + background: $color-accent; + height: 1px; + border: 0; +} + +/* Heading */ +h1, +h2, +h3, +h4, +h5, +h6 { + // check imported weights and styles in gatsby-browser.jsx + font-family: $font-heading; + margin: $spacing-12 0 $spacing-6; + line-height: $line-height-tight; +} + +h3, +h4, +h5, +h6 { + font-weight: $font-weight-bold; + color: $color-heading; +} + +h1 { + margin-top: 0; + font-weight: $font-weight-black; + font-size: $font-size-6; + font-style: italic; + color: $color-heading-black; +} + +h2 { + font-size: $font-size-5; + font-weight: $font-weight-semibold; + color: $color-heading; +} + +h3 { + font-size: $font-size-4; +} + +h4 { + font-size: $font-size-3; +} + +h5 { + font-size: $font-size-2; +} + +h6 { + font-size: $font-size-1; +} + +/* Prose */ +p { + line-height: $line-height-relaxed; + $baseline-multiplier: 0.179; + $x-height-multiplier: 0.35; + margin: $spacing-0 $spacing-0 $spacing-4 $spacing-0; + padding: $spacing-0; +} + +ul, +ol { + margin-left: $spacing-0; + margin-right: $spacing-0; + padding: $spacing-0; + margin-bottom: $spacing-8; + list-style-position: inside; + list-style-image: none; +} + +li p { + display: inline; +} + +ul li, +ol li { + padding-left: $spacing-0; + margin-bottom: math.div($spacing-8, 2); +} + +li > p { + margin-bottom: math.div($spacing-8, 2); +} + +li *:last-child { + margin-bottom: $spacing-0; +} + +li > ul { + margin-left: $spacing-8; + margin-top: math.div($spacing-8, 2); +} + +blockquote { + color: $color-theme-4; + margin-left: calc(#{-1 + $spacing-6}); + margin-right: $spacing-8; + padding: $spacing-0 $spacing-0 $spacing-0 $spacing-6; + border-left: $spacing-1 solid $color-primary; + font-size: $font-size-2; + font-style: italic; + margin-bottom: $spacing-8; +} + +blockquote > :last-child { + margin-bottom: $spacing-0; +} + +blockquote > ul, +blockquote > ol { + list-style-position: inside; +} + +table { + width: 100%; + margin-bottom: $spacing-8; + border-collapse: collapse; + border-spacing: 0.25rem; +} + +table thead tr th { + border-bottom: 1px solid $color-accent; +} + +/* Link */ +a { + color: $color-theme-4; +} + +a, +button { + // browser will not anticipate double click so proceeds with action quicker (300 ms quicker) + touch-action: manipulation; +} + +h1 > a { + color: inherit; + text-decoration: none; +} +h2 > a, +h3 > a, +h4 > a, +h5 > a, +h6 > a { + text-decoration: none; + color: inherit; +} + +a:hover, +a:focus { + text-decoration: none; +} + +/* Custom classes */ +.global-wrapper { + margin: $spacing-0 auto; + max-width: $max-width-wrapper; + padding: $spacing-10 $spacing-5; +} + +.global-header { + margin-bottom: $spacing-12; +} + +.post-list-item { + margin-bottom: $spacing-8; + margin-top: $spacing-8; +} + +.post-list-item p { + margin-bottom: $spacing-0; +} + +.post-list-item h2 { + font-size: $font-size-4; + color: $color-primary; + margin-bottom: $spacing-2; + margin-top: $spacing-0; +} + +.post-list-item header { + margin-bottom: $spacing-4; +} + +.bio { + display: flex; + margin-bottom: $spacing-16; +} + +.global-wrapper[data-is-root-path='true'] .bio { + margin-bottom: $spacing-20; +} + +.bio p { + margin-bottom: $spacing-0; +} + +.bio-avatar { + margin-right: $spacing-4; + margin-bottom: $spacing-0; + min-width: 50px; + border-radius: 100%; +} + +.blog-post header h1 { + margin: $spacing-0 $spacing-0 $spacing-4 $spacing-0; +} + +.blog-post header p { + font-size: $font-size-2; + font-family: $font-heading; +} + +.blog-post-nav ul { + margin: $spacing-0; +} + +.gatsby-highlight { + margin-bottom: $spacing-8; +} + +.screen-reader-text { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + margin: -1px; + width: 1px; + overflow: hidden; + position: absolute !important; + word-wrap: normal !important; +} + +figure { + margin-bottom: $spacing-6; + padding-bottom: $spacing-6; +} + +figure figcaption { + margin-top: $spacing-2; +} + +/* Media queries */ +@media (max-width: $desktop-breakpoint) { + h1 { + font-size: $mobile-font-size-6; + } + + h2 { + font-size: $mobile-font-size-5; + } + + h3 { + font-size: $mobile-font-size-4; + } + + h4 { + font-size: $mobile-font-size-3; + } + + h5 { + font-size: $mobile-font-size-2; + } + + h6 { + font-size: $mobile-font-size-1; + } + + blockquote { + padding: $spacing-0 $spacing-0 $spacing-0 $spacing-4; + margin-left: $spacing-0; + } + ul, + ol { + list-style-position: inside; + } +} diff --git a/src/lib/styles/variables.scss b/src/lib/styles/variables.scss new file mode 100644 index 0000000..04658a5 --- /dev/null +++ b/src/lib/styles/variables.scss @@ -0,0 +1,91 @@ +@charset "UTF-8"; + +/* SCSS Custom Properties Definitions */ +// Widths +$max-width-none: 'none'; +$max-width-xs: 20rem; +$max-width-sm: 24rem; +$max-width-md: 28rem; +$max-width-lg: 32rem; +$max-width-xl: 36rem; +$max-width-2xl: 42rem; +$max-width-3xl: 48rem; +$max-width-4xl: 56rem; +$max-width-full: '100%'; +$max-width-wrapper: $max-width-2xl; +$desktop-breakpoint: 42rem; + +// Spacing +$spacing-px: 0.0625rem; +$spacing-px-2: 0.125rem; +$spacing-0: 0; +$spacing-1: 0.25rem; +$spacing-2: 0.5rem; +$spacing-3: 0.75rem; +$spacing-4: 1rem; +$spacing-5: 1.25rem; +$spacing-6: 1.5rem; +$spacing-8: 2rem; +$spacing-10: 2.5rem; +$spacing-12: 3rem; +$spacing-16: 4rem; +$spacing-20: 5rem; +$spacing-24: 6rem; +$spacing-32: 8rem; + +// Fonts +$font-family-serif: 'Source Sans Pro', 'Lustria', 'Noto Serif', 'Merriweather', 'Georgia', 'Cambria', + 'Times New Roman', 'Times', serif; +$font-body: $font-family-serif; +$font-heading: 'Lora', $font-family-serif; + +// Font Weight +// check imported weights and styles in gatsby-browser.jsx +$font-weight-light: 300; +$font-weight-normal: 400; +$font-weight-medium: 500; +$font-weight-semibold: 600; +$font-weight-bold: 700; +$font-weight-extrabold: 800; +$font-weight-black: 900; + +// Font Size +$font-size-root: 16px; +$font-size-0: 0.8rem; +$font-size-1: 1rem; +$font-size-2: 1.25rem; +$font-size-3: 1.563rem; +$font-size-4: 1.953rem; +$font-size-5: 2.441rem; +$font-size-6: 3.052rem; +$font-size-7: 3.815rem; + +// $mobile-font-size-root: 16px; +$mobile-font-size-0: 0.8889rem; +$mobile-font-size-1: 1rem; +$mobile-font-size-2: 1.125rem; +$mobile-font-size-3: 1.266rem; +$mobile-font-size-4: 1.424rem; +$mobile-font-size-5: 1.602rem; +$mobile-font-size-6: 1.802rem; +$mobile-font-size-7: 3.815rem; + +// Line Height +$line-height-none: 1; +$line-height-tight: 1.3; +$line-height-normal: 1.5; +$line-height-relaxed: 1.75; + +// Colours +$color-theme-1: #d62828; // maximum red +$color-theme-2: #5cc8ff; // maya blue +$color-theme-3: #fff275; // corn +$color-theme-4: #1b4079; // dark cornflower blue + +$color-primary: #005b99; +$color-text: #0d1821; // rich black FOGRA 29 +$color-heading: $color-theme-4; +$color-heading-black: $color-theme-4; +$color-accent: #fdfffc; // baby powder +$color-success: #2ec4b6; // tiffany blue +$color-danger: #e71d36; // rose madder diff --git a/src/lib/utilities/blog.js b/src/lib/utilities/blog.js new file mode 100644 index 0000000..b3164e3 --- /dev/null +++ b/src/lib/utilities/blog.js @@ -0,0 +1,70 @@ +import fs from 'fs'; +import { compile } from 'mdsvex'; + +export const BLOG_PATH = 'src/routes'; + +export const getPostsContent = (location) => { + const directories = fs + .readdirSync(location) + .filter((element) => fs.lstatSync(`${location}/${element}`).isDirectory()); + const articles = []; + + directories.forEach((element) => { + const contentPath = `${location}/${element}/index.md`; + if (fs.existsSync(contentPath)) { + const content = fs.readFileSync(contentPath, { encoding: 'utf-8' }); + articles.push({ slug: element, content }); + } + }); + return articles; +}; + +/** + * Returns an array of post metadata, with optional post body too. Array is sort in reverse + * chrononological order + * @param {string} postsContent - The title of the book. + * @param {bool} body - if true the HTML post body is returned as well as meta + */ +export const getPosts = async (postsContent, body = false) => { + let result = postsContent.map(async (element) => { + const { content, slug } = element; + const transformedContent = await compile(content); + const { datePublished, lastUpdated, postTitle, seoMetaDescription } = + transformedContent.data.fm; + let resultElement = { datePublished, lastUpdated, postTitle, seoMetaDescription, slug }; + if (body) { + resultElement = { ...resultElement, body: transformedContent.code }; + } + return resultElement; + }); + result = await Promise.all(result); + return result.sort((a, b) => Date.parse(b.datePublished) - Date.parse(a.datePublished)); +}; + +export const getPost = async (content, body = true) => { + const transformedContent = await compile(content); + const { + datePublished, + featuredImage, + featuredImageAlt, + ogImage, + ogSquareImage, + postTitle, + seoMetaDescription, + twitterImage, + } = transformedContent.data.fm; + let result = { + datePublished, + featuredImage, + featuredImageAlt, + ogImage, + ogSquareImage, + postTitle, + seoMetaDescription, + twitterImage, + }; + if (body) { + result = { ...result, body: transformedContent.code }; + } + return result; +}; diff --git a/src/lib/utilities/file.js b/src/lib/utilities/file.js new file mode 100644 index 0000000..84e1ec1 --- /dev/null +++ b/src/lib/utilities/file.js @@ -0,0 +1,9 @@ +import { promises as fsp } from 'fs'; + +export async function makeDirectory(directoryPath) { + await fsp.mkdir(directoryPath, { recursive: true }, (err) => { + if (err) { + return console.error(err); + } + }); +} diff --git a/src/lib/utilities/image.js b/src/lib/utilities/image.js new file mode 100644 index 0000000..af4cfd4 --- /dev/null +++ b/src/lib/utilities/image.js @@ -0,0 +1,41 @@ +import sharp from 'sharp'; + +export async function dominantColour({ source }) { + try { + const image = sharp(source); + const { dominant } = await image.stats(); + return dominant; + } catch (error) { + console.error('Error determining dominant colour: ', source); + } +} + +export async function lowResolutionPlaceholder({ source }) { + try { + const image = sharp(source); + const buffer = await image + .resize(10) + .jpeg({ + quality: 50, + progressive: true, + optimiseScans: true, + chromaSubsampling: '4:2:0', + trellisQuantisation: true, + quantisationTable: 2, + }) + .toBuffer({ resolveWithObject: false }); + return `data:image/jpeg;base64,${(await buffer).toString('base64')}`; + } catch (error) { + console.error('Error generating low resolution placeholder: ', source); + } +} + +export async function metadata({ source }) { + try { + const image = sharp(source); + const { format, height, width } = await image.metadata(); + return { format, height, width }; + } catch (error) { + console.error('Error determining image meta: ', source); + } +} diff --git a/src/routes/[slug].json.js b/src/routes/[slug].json.js new file mode 100644 index 0000000..503d031 --- /dev/null +++ b/src/routes/[slug].json.js @@ -0,0 +1,16 @@ +import path from 'path'; +import { getPost, getPostsContent } from '$lib/utilities/blog'; + +export async function get({ params }) { + const { slug } = params; + const __dirname = path.resolve(); + const location = path.join(__dirname, './src/routes/'); + const articles = await getPostsContent(location); + const article = articles.find((element) => element.slug === slug); + const post = await getPost(article.content, true); + if (post) { + return { + body: JSON.stringify({ post: { ...post, slug } }), + }; + } +} diff --git a/src/routes/__error.svelte b/src/routes/__error.svelte new file mode 100644 index 0000000..e460636 --- /dev/null +++ b/src/routes/__error.svelte @@ -0,0 +1,18 @@ + + + + + + {title} + +

{title}

diff --git a/src/routes/__layout.svelte b/src/routes/__layout.svelte new file mode 100644 index 0000000..7c2effd --- /dev/null +++ b/src/routes/__layout.svelte @@ -0,0 +1,242 @@ + + + + + +
+
+ + +
+
+ {#if isBlogPost} + + {/if} + + +
+
+
+ Created by Rodney Lab. Copyright {COPYRIGHT_ENTITY} 2021. +
+ + +
+
+ + diff --git a/src/routes/api/post/data.json.js b/src/routes/api/post/data.json.js new file mode 100644 index 0000000..102436c --- /dev/null +++ b/src/routes/api/post/data.json.js @@ -0,0 +1,25 @@ +export const post = async (request) => { + try { + const { slug } = request.body; + const response = await fetch(`${process.env['WORKER_URL']}/post/data`, { + method: 'POST', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + slug, + }), + }); + const { count } = await response.json(); + return { + body: JSON.stringify({ count }), + }; + } catch (err) { + console.log('Error: ', err); + return { + status: 500, + error: 'Error retreiving data', + }; + } +}; diff --git a/src/routes/api/post/like.json.js b/src/routes/api/post/like.json.js new file mode 100644 index 0000000..f793ae7 --- /dev/null +++ b/src/routes/api/post/like.json.js @@ -0,0 +1,26 @@ +export const post = async (request) => { + try { + const { slug, unlike } = request.body; + await fetch(`${process.env['WORKER_URL']}/post/like`, { + method: 'POST', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + slug, + unlike, + }), + }); + return { + status: 400, + body: 'Like added.', + }; + } catch (err) { + console.error('Error: ', err); + return { + status: 500, + error: 'Error retreiving data', + }; + } +}; diff --git a/src/routes/best-medium-format-camera-for-starting-out/index.md b/src/routes/best-medium-format-camera-for-starting-out/index.md new file mode 100644 index 0000000..a2f8538 --- /dev/null +++ b/src/routes/best-medium-format-camera-for-starting-out/index.md @@ -0,0 +1,49 @@ +--- +postTitle: 'Best Medium Format Camera for Starting Out' +focusKeyphrase: 'best medium format camera' +datePublished: '2021-04-07T16:04:42.000+0100' +lastUpdated: '2021-04-14T10:17:52.000+0100' +seoMetaDescription: "Best medium format camera for starting out is probably a question at the front of your mind right now! Let's take a look." +featuredImage: 'best-medium-format-camera-for-starting-out.jpg' +featuredImageAlt: 'Photograph of a Hasselblad medium format camera with the focusing screen exposed' +ogImage: 'best-medium-format-camera-for-starting-out-open-graph.jpg' +ogSquareImage: 'best-medium-format-camera-for-starting-out-open-graph-square.jpg' +twitterImage: 'best-medium-format-camera-for-starting-out-twitter.jpg' +categories: '' +tags: '' +--- + + + +## What is a Medium Format Camera? + +If you are old enough to remember the analogue film camera era, chances are it is the 35 mm canisters with the track cut down the side that first come to mind. Shots normally had a 3:2 aspect ratio measuring 36×24 mm. Medium format film is a whole lot bigger. There is no single prevalent form factor, the film is 60mm across and depending on the camera you can shoot negative frames from 60×60 mm to 60 × 170  mm. That said 1:1 and roughly 4:5 (from 60 × 70 frames) are probably most common. With 35mm film you could nominally get 24 or 36 exposures onto a film. Medium format film is most common in the 120 variety, which lets you shoot 12 exposures. Double length 220 film is less common now. If you do find a roll, you might need to adjust your camera when you load it. Cameras ,like the Pentax 67 have a pressure plate to hold the film flat in the camera. Since 220 film does not have backing paper, it needs a different pressure setting. + +Another fact worth remembering is that a roll of 120 film contains around the same surface area as a roll of 36 exposure 35mm   you will find this useful if developing at home. + +## Why shoot a Medium Format Camera? + +Back to the best medium format film camera. The main reason for using it is the size of the negatives. They are larger even that the sensors in modern digital medium format cameras. This means you can capture a whole lot more detail and create far larger images than you can with even a full frame digital sensor. What if you are just taking photographs to share on Instagram? Another benefit is that the lenses naturally have a longer focal length. A consequence of this is that for the same field of vision, you get a shallower depth of field. Depth-of-field is jut a measure of how much of the photograph is in focus. For a portrait, you might just want to have the eyes in focus, to bring attention to them and have hair and the background blurred. This effect is much easier to achieve with a medium format camera. + +The final advantage I will mention here is that even using the same film stock (e.g. Ilford Delta 100, Fuji Acros II or Kodak Portra 400), medium format can have a different look and feel to 35 mm. That said you will need to experiment with different films to find which ones best suits your aesthetic. + +## Best Medium Format Camera + +The best medium format camera really depends on you. If you have come from using a Canon 5D with an army of lenses, you probably want to consider a system camera, so you do not feel too limited. Good choices here are the Mamiya RZ67 or older RB67. These have a lot of accessories available. Just be careful if you go for the RZ67 or RZ67 II as some accessories are not cross-compatible and you need to make sure you get tones to match your exact model. The cameras are very modular, so you can get backs which let take 6×6 film, 6×7 or even 6×45 shots. There are many lenses with great optics. Just be warned that these are big cameras, the RB67 has a metal body and is heavier. + +An alternative system camera is the Pentax 67. This is another quality camera with lenses perhaps even better than the Mamiya ones. Both cameras heavily used by professional fashion photographer. The Pentax looks like a big SLR. Not everybody is comfortable with its size but it is technically an amazing camera if you are able to handle it! + +It doesn't stop there. If you are new to professional level cameras and doing things manually, it might help just to have one lens. If you are someone who is out-and0about a lot consider a folding camera. These are quite portable and again have very good lenses. Not having a zoom lens can help you make more interesting composures. The Fuji 670 is the newest model you will find but they are quite expensive. You could consider an Agfa Isolette or Mamiya 6. The Isolette is a camera from the 1950s while the Mamiya 6 is a little newer. The Mamiya 6 has three different lenses but does not fold down as small as the Isolette. That site it is quite compact and can be packed into a small camera bag. Both cameras are rangefinders, which means the viewfinder view will not exactly match what is captured. The advantage though is that they come with superior optics. + +Another family of cameras to consider is the Twin Lens Reflex. These make it easy to shoot from waist level and are not as heavy as their mirrored cousins, which need bigger lenses. + +If you want something really simple, but also quality, consider the Fuji 6×9. These are much more rare than some of the other cameras listed here but can be found relatively cheaper. They shoot wider negatives. They have a single lens but a little bigger than the folding cameras. They also have fantastic optics. + +The only remaining question is which film to load into your new camera! + +## Feedback + +I hope you have found this post interesting. If you did please destroy the twitter share button! Don't forget to follow me on Twitter and tell everyone you meet about how good I am! diff --git a/src/routes/contact.svelte b/src/routes/contact.svelte new file mode 100644 index 0000000..70ffc8f --- /dev/null +++ b/src/routes/contact.svelte @@ -0,0 +1,104 @@ + + + + +

Contact me

+

I would love to hear from you. Please get in touch!

+
+
    +
  • + + {contactEmail} +
  • +
  • + + {facebookPageName} + +
  • +
  • + + @{twitterUsername} + +
  • +
  • + + {telegramUsername} + +
  • +
  • + + {wireUsername} +
  • +
+
+ + diff --git a/src/routes/folding-camera/index.md b/src/routes/folding-camera/index.md new file mode 100644 index 0000000..f8199f1 --- /dev/null +++ b/src/routes/folding-camera/index.md @@ -0,0 +1,36 @@ +--- +postTitle: 'Folding Camera' +focusKeyphrase: 'folding camera best kept secret' +datePublished: '2021-04-05T15:38:49.000+0100' +lastUpdated: '2021-04-14T10:17:52.000+0100' +seoMetaDescription: 'Folding cameras have the benefits of high resolution negatives but are so much more compact and often have amazing optics' +featuredImage: 'folding-camera.jpg' +featuredImageAlt: 'Photograph of a classic folding camera' +ogImage: 'folding-camera-open-graph.jpg' +ogSquareImage: 'folding-camera-open-graph-square.jpg' +twitterImage: 'folding-camera-twitter.jpg' +categories: '' +tags: '' +--- + + + +## What is a Folding Camera? + +Folding cameras are a well kept secret. Typically the optics are amazing, in fact often better than modern mirrorless and high end DSLR lenses. This is related to the physics, put simply, it is easier to make a good small lens than a large one. On top they are compact, something like the Agfa Isolette can fit into a pocket (they are expensive and quite old cameras so a padded camera bag would be safer!). One drawback is that you cannot usually swap lenses. If you want a halfway-house, try the Mamiya 6. It has a wide angle, normal and telephoto lens, though it does not collapse to as flat a profile as the Isolette. + +## Why shoot a Folding Camera? + +They are great cameras to take on family holidays, or just use when out and about. If you are popping out for a walk it is not a lot of extra weight. On top the lenses are fantastic. Compared to the various lenses and accessories you might want to take with a Mamiya 67 and Pentax 67, you are kind of limited to one lens, with the main choice being what film you want to use. These kinds of limitations can make you more creative. + +You might also choose a folding camera for street photography. You can get the same quality as with Pentax67 but be for less conspicuous and hopefully capture more natural images. + +## Top Folding Cameras + +There is quite a range still available. Although folding cameras perhaps had their heyday half a century ago, you were still able to buy brand new Fuji GF 670 a few years ago. Released in 2008, the camera takes medium format film and can shoot square or 6×7 frames. The 80mm lens is very sharp, equivalent to 40-44 mm on 35 mm. A classic favourite is the Agfa Isolette, which has one of the sharpest lenses ever made. These were produced in the 1950s so if you do get hold of one, make sure it has a clean, lube and service. + +## Feedback + +I hope you have found this post interesting. If you did please destroy the twitter share button! Don't forget to follow me on Twitter and tell everyone you meet about how good I am! diff --git a/src/routes/index.json.js b/src/routes/index.json.js new file mode 100644 index 0000000..ff376e7 --- /dev/null +++ b/src/routes/index.json.js @@ -0,0 +1,11 @@ +import path from 'path'; + +import { BLOG_PATH, getPosts, getPostsContent } from '$lib/utilities/blog'; + +export async function get() { + const __dirname = path.resolve(); + const location = path.join(__dirname, BLOG_PATH); + const postsContent = await getPostsContent(location); + const posts = await getPosts(postsContent, false); + return { body: JSON.stringify({ posts }) }; +} diff --git a/src/routes/index.svelte b/src/routes/index.svelte new file mode 100644 index 0000000..651c553 --- /dev/null +++ b/src/routes/index.svelte @@ -0,0 +1,104 @@ + + + + + +
+

Climate — Sveltekit Starter

+

SvelteKit MDsveX (Markdown for Svelte) Blog

+
+ +

About me

+

+ I live and breathe analogue photography. I show you my favourite analogue film cameras on this + site. Hopefully if you are not into analogue photography yet, some of my enthusiasm will rub off + onto you. +

+
+ + + diff --git a/src/routes/sitemap.xml.js b/src/routes/sitemap.xml.js new file mode 100644 index 0000000..c4d9def --- /dev/null +++ b/src/routes/sitemap.xml.js @@ -0,0 +1,83 @@ +/* This sitemap will be served by SSR sites only, for static sites, incorporate the command + * + * node ./generate-sitemap.js + * + * into your build script (before build). This will create sitemap.xml in the static/ folder + * + * alternatively run + * + * pnpm run generate:sitemap + * + * as and when static sitemap needs creating/updating + */ + +import website from '$lib/config/website'; +import { BLOG_PATH, getPosts, getPostsContent } from '$lib/utilities/blog'; +import path from 'path'; + +const { siteUrl } = website; + +const render = (pages, posts) => ` + + + ${pages + .map( + (element) => ` + + ${element} + ${`${process.env.VITE_BUILD_TIME}`} + monthly + 0.7 + `, + ) + .join('\n')} + + ${posts + .map((element) => { + const { lastUpdated, slug } = element; + return ` + + ${siteUrl}/${slug}/ + ${`${lastUpdated}`} + daily + 0.7 + + `; + }) + .join('')} +`; + +export async function get() { + const __dirname = path.resolve(); + const location = path.join(__dirname, BLOG_PATH); + const postsContent = await getPostsContent(location); + const posts = await getPosts(postsContent, false); + + const pages = Object.keys(import.meta.glob('/src/routes/**/!(_)*.svelte')) + .filter((page) => { + const filters = ['slug]', '_', 'private']; + + return !filters.find((filter) => page.includes(filter)); + }) + .map((page) => + page.replace('/src/routes', siteUrl).replace('/index.svelte', '').replace('.svelte', ''), + ); + + return { + body: render(pages, posts), + headers: { + 'Cache-Control': `max-age=0, s-max-age=${600}`, + 'Content-Type': 'application/xml', + }, + }; +} diff --git a/src/routes/twin-lens-reflex-camera/index.md b/src/routes/twin-lens-reflex-camera/index.md new file mode 100644 index 0000000..c40538b --- /dev/null +++ b/src/routes/twin-lens-reflex-camera/index.md @@ -0,0 +1,36 @@ +--- +postTitle: 'Twin Lens Reflex Camera' +focusKeyphrase: 'Twin Lens Reflex love' +datePublished: '2021-04-06T10:31:48.000+0100' +lastUpdated: '2021-04-14T10:17:52.000+0100' +seoMetaDescription: 'TLR or Twin Lens Reflex Cameras have the benefit of you being able to hold the camera at waist level to take a picture and get a more engaging camera angle.' +featuredImage: 'twin-lens-reflex-camera.jpg' +featuredImageAlt: 'Photograph of a Rolleicord twin Lens reflex camera' +ogImage: 'twin-lens-reflex-camera-open-graph.jpg' +ogSquareImage: 'twin-lens-reflex-camera-open-graph-square.jpg' +twitterImage: 'twin-lens-reflex-camera-twitter.jpg' +categories: '' +tags: '' +--- + + + +## What is a Twin Lens Reflex Camera? + +Traditionally, the most common type of camera was a Single Lens Reflex camera. Today digital mirrorless cameras are becoming more prevalent. These cameras have an electronic viewfinder which lets you see exactly what will appear in the capture. Things weren't that easy with earlier film cameras. The image needs to be captured on light sensitive film, which must be kept in alight-sealed compartment until you press the shutter release. Since the lens is aligned for capturing your image on the film, you need another way to preview and line up your shot. Single Lens Reflex cameras have view finder, normally at the top of the camera. A mirror inside the camera reflects the image into the viewfinder, deflecting from the film, while you line up your shot. When you fire the shutter, the camera automatically lifts the mirror out of the way before opening the shutter, so that the image can be captured. + +TLR cameras do things differently. As the name suggests, there is a second lens. This second lens is used, just for you framing the shot with the main lens used for exposing the film to your scene. Using two lenses gets rid of the need for a mirror. This is good, because the mirror movement can cause vibrations in the camera and make your shot appear less focussed. It's not all good though. Firstly, the two lenses need to be calibrated, otherwise you will lineup your shit, have the focus just as you want it, then not realise until you process the film that your once-in-a-lifetime shot is out of focus and unusable! Another issue is an effect called parallax. The two lenses are slightly separated. When you focus on a ship on the horizon, parallax won't have a noticeable impact. For closer objects there will be some parallax. To appreciate this close one eye and then focus on a point on edge of your phone or screen, taking in what is behind. Now swap eyes and (still focusing on the same point) you will notice the background has shifted. Parallax means each of the two lenses on the TLR will take in a slightly different frame. When tightly framing a shot, you need to adjust for parallax. + +## Why shoot a Twin Lens Reflex Camera? + +With parallax and calibration to worry about, why would you use a TLR camera. Well one nice feature is that you can shoot from waist height and get quite a different perspective. Vivian Maier is a photographer who used a TLR camera extensively and often shot surreptitiously from wait height. Check out some Vivian Maier work on Huxley Parlour gallery website. If you haven't heard of Vivian Maier before, the story of how her work was discovered is quite interesting, I recommend you read up — you will not be disappointed! + +## Top TLR Cameras + +Vivian Maier used a Rolleiflex camera. They are probably the best known TLR camera. Unfortunately, they are currently highly sought after. If you are not able to borrow one to try out, you should investigate a cheaper alternative on eBay. If it is the waist-level shooting that you are after, you can get a similar experience using a Pentax 67 with the prism taken off or other medium format cameras like the Mamiya RZ67 or RB67 or Bronica. If you have a 35mm Nikon F3, there are waist level viewfinder attachments, though the frame is much smaller. + +## Feedback + +I hope you have found this post interesting. If you did please destroy the twitter share button! Don't forget to follow me on Twitter and tell everyone you meet about how good I am! diff --git a/src/service-worker.js b/src/service-worker.js new file mode 100644 index 0000000..41ab6e1 --- /dev/null +++ b/src/service-worker.js @@ -0,0 +1,52 @@ +// based on https://github.com/tretapey/svelte-pwa/blob/master/public/service-worker.js +import { build, files, timestamp } from '$service-worker'; + +const worker = self; +const CACHE_NAME = `static-cache-${timestamp}`; + +const to_cache = build.concat(files); + +worker.addEventListener('install', (event) => { + console.log('[ServiceWorker] Install'); + + event.waitUntil( + caches.open(CACHE_NAME).then((cache) => { + console.log('[ServiceWorker] Pre-caching offline page'); + return cache.addAll(to_cache).then(() => { + worker.skipWaiting(); + }); + }), + ); +}); + +worker.addEventListener('activate', (event) => { + console.log('[ServiceWorker] Activate'); + // Remove previous cached data from disk + event.waitUntil( + caches.keys().then(async (keys) => + Promise.all( + keys.map((key) => { + if (key !== CACHE_NAME) { + console.log('[ServiceWorker] Removing old cache', key); + return caches.delete(key); + } + }), + ), + ), + ); + worker.clients.claim(); +}); + +self.addEventListener('fetch', (event) => { + console.log('[ServiceWorker] Fetch', event.request.url); + if (event.request.mode !== 'navigate') { + return; + } + event.respondWith( + fetch(event.request).catch(() => { + return caches.open(CACHE_NAME).then((cache) => { + return cache.match('offline.html'); + }); + }), + ); +}); diff --git a/static/assets/images/best-medium-format-camera-for-starting-out-open-graph-square.jpg b/static/assets/images/best-medium-format-camera-for-starting-out-open-graph-square.jpg new file mode 100644 index 0000000..2007949 Binary files /dev/null and b/static/assets/images/best-medium-format-camera-for-starting-out-open-graph-square.jpg differ diff --git a/static/assets/images/best-medium-format-camera-for-starting-out-open-graph.jpg b/static/assets/images/best-medium-format-camera-for-starting-out-open-graph.jpg new file mode 100644 index 0000000..5f7059b Binary files /dev/null and b/static/assets/images/best-medium-format-camera-for-starting-out-open-graph.jpg differ diff --git a/static/assets/images/best-medium-format-camera-for-starting-out-twitter.jpg b/static/assets/images/best-medium-format-camera-for-starting-out-twitter.jpg new file mode 100644 index 0000000..5034341 Binary files /dev/null and b/static/assets/images/best-medium-format-camera-for-starting-out-twitter.jpg differ diff --git a/static/assets/images/best-medium-format-camera-for-starting-out.jpg b/static/assets/images/best-medium-format-camera-for-starting-out.jpg new file mode 100644 index 0000000..3f07145 Binary files /dev/null and b/static/assets/images/best-medium-format-camera-for-starting-out.jpg differ diff --git a/static/assets/images/folding-camera-open-graph-square.jpg b/static/assets/images/folding-camera-open-graph-square.jpg new file mode 100644 index 0000000..31b996a Binary files /dev/null and b/static/assets/images/folding-camera-open-graph-square.jpg differ diff --git a/static/assets/images/folding-camera-open-graph.jpg b/static/assets/images/folding-camera-open-graph.jpg new file mode 100644 index 0000000..cf2ebb7 Binary files /dev/null and b/static/assets/images/folding-camera-open-graph.jpg differ diff --git a/static/assets/images/folding-camera-twitter.jpg b/static/assets/images/folding-camera-twitter.jpg new file mode 100644 index 0000000..4e6eed5 Binary files /dev/null and b/static/assets/images/folding-camera-twitter.jpg differ diff --git a/static/assets/images/folding-camera.jpg b/static/assets/images/folding-camera.jpg new file mode 100644 index 0000000..4fbfb2f Binary files /dev/null and b/static/assets/images/folding-camera.jpg differ diff --git a/static/assets/images/home-open-graph-square.jpg b/static/assets/images/home-open-graph-square.jpg new file mode 100644 index 0000000..84e305d Binary files /dev/null and b/static/assets/images/home-open-graph-square.jpg differ diff --git a/static/assets/images/home-open-graph.jpg b/static/assets/images/home-open-graph.jpg new file mode 100644 index 0000000..a95ebe5 Binary files /dev/null and b/static/assets/images/home-open-graph.jpg differ diff --git a/static/assets/images/home-twitter.jpg b/static/assets/images/home-twitter.jpg new file mode 100644 index 0000000..ce5d264 Binary files /dev/null and b/static/assets/images/home-twitter.jpg differ diff --git a/static/assets/images/twin-lens-reflex-camera-open-graph-square.jpg b/static/assets/images/twin-lens-reflex-camera-open-graph-square.jpg new file mode 100644 index 0000000..2174e1d Binary files /dev/null and b/static/assets/images/twin-lens-reflex-camera-open-graph-square.jpg differ diff --git a/static/assets/images/twin-lens-reflex-camera-open-graph.jpg b/static/assets/images/twin-lens-reflex-camera-open-graph.jpg new file mode 100644 index 0000000..ab84e97 Binary files /dev/null and b/static/assets/images/twin-lens-reflex-camera-open-graph.jpg differ diff --git a/static/assets/images/twin-lens-reflex-camera-twitter.jpg b/static/assets/images/twin-lens-reflex-camera-twitter.jpg new file mode 100644 index 0000000..a0ee6ac Binary files /dev/null and b/static/assets/images/twin-lens-reflex-camera-twitter.jpg differ diff --git a/static/assets/images/twin-lens-reflex-camera.jpg b/static/assets/images/twin-lens-reflex-camera.jpg new file mode 100644 index 0000000..6754ac8 Binary files /dev/null and b/static/assets/images/twin-lens-reflex-camera.jpg differ diff --git a/static/assets/rodneylab-logo.png b/static/assets/rodneylab-logo.png new file mode 100644 index 0000000..a9f592a Binary files /dev/null and b/static/assets/rodneylab-logo.png differ diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..54db451 Binary files /dev/null and b/static/favicon.png differ diff --git a/static/icon.png b/static/icon.png new file mode 100644 index 0000000..a9f592a Binary files /dev/null and b/static/icon.png differ diff --git a/static/icons/icon-128x128.png b/static/icons/icon-128x128.png new file mode 100644 index 0000000..7832fa6 Binary files /dev/null and b/static/icons/icon-128x128.png differ diff --git a/static/icons/icon-144x144.png b/static/icons/icon-144x144.png new file mode 100644 index 0000000..2a6b950 Binary files /dev/null and b/static/icons/icon-144x144.png differ diff --git a/static/icons/icon-152x152.png b/static/icons/icon-152x152.png new file mode 100644 index 0000000..2c2a32a Binary files /dev/null and b/static/icons/icon-152x152.png differ diff --git a/static/icons/icon-192x192.png b/static/icons/icon-192x192.png new file mode 100644 index 0000000..5cf4197 Binary files /dev/null and b/static/icons/icon-192x192.png differ diff --git a/static/icons/icon-256x256.png b/static/icons/icon-256x256.png new file mode 100644 index 0000000..a6b1827 Binary files /dev/null and b/static/icons/icon-256x256.png differ diff --git a/static/icons/icon-512x512.png b/static/icons/icon-512x512.png new file mode 100644 index 0000000..6ec31a7 Binary files /dev/null and b/static/icons/icon-512x512.png differ diff --git a/static/manifest.json b/static/manifest.json new file mode 100644 index 0000000..fb01a29 --- /dev/null +++ b/static/manifest.json @@ -0,0 +1,46 @@ +{ + "name": "SvelteKit Blog Mdx", + "short_name": "SvelteKit Blog", + "start_url": "/index.html", + "background_color": "#1b4079", + "theme_color": "#d62828", + "display": "standalone", + "icons": [ + { + "src": "icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "icons/icon-256x256.png", + "sizes": "256x256", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ] +} \ No newline at end of file diff --git a/static/robots.txt b/static/robots.txt new file mode 100644 index 0000000..6f27bb6 --- /dev/null +++ b/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: \ No newline at end of file diff --git a/static/sitemap.xml b/static/sitemap.xml new file mode 100644 index 0000000..1263961 --- /dev/null +++ b/static/sitemap.xml @@ -0,0 +1,42 @@ + + + + https://sveltekit-mdx-starter.rodneylab.com/contact/ + 2021-08-16T17:51:04.461Z + monthly + 0.7 + + https://sveltekit-mdx-starter.rodneylab.com/ + 2021-08-16T17:51:04.461Z + monthly + 0.7 + + + https://sveltekit-mdx-starter.rodneylab.com/best-medium-format-camera-for-starting-out/ + 2021-04-14T10:17:52.000+0100 + daily + 0.7 + + + https://sveltekit-mdx-starter.rodneylab.com/folding-camera/ + 2021-04-14T10:17:52.000+0100 + daily + 0.7 + + + https://sveltekit-mdx-starter.rodneylab.com/twin-lens-reflex-camera/ + 2021-04-14T10:17:52.000+0100 + daily + 0.7 + + \ No newline at end of file diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..03240e5 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,34 @@ +/** @type {import('@sveltejs/kit').Config} */ +import adapter from '@sveltejs/adapter-static'; +import 'dotenv/config'; +import { mdsvex } from 'mdsvex'; +import preprocess from 'svelte-preprocess'; +import { imagetools } from 'vite-imagetools'; + +const config = { + extensions: ['.svelte', '.md', '.svelte.md'], + preprocess: [ + mdsvex({ extensions: ['.svelte.md', '.md', '.svx'] }), + preprocess({ + scss: { + prependData: "@import 'src/lib/styles/variables.scss';", + }, + }), + ], + kit: { + adapter: adapter(), + files: { + hooks: 'src/hooks', + }, + // hydrate the
element in src/app.html + target: '#svelte', + vite: { + define: { + 'process.env.VITE_BUILD_TIME': JSON.stringify(new Date().toISOString()), + }, + plugins: [imagetools({ force: true })], + }, + }, +}; + +export default config;