Start omorphia 2 (#8)

This commit is contained in:
Prospector 2023-02-16 14:02:39 -08:00 committed by GitHub
parent 87251878a5
commit 0faa24d5d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
236 changed files with 6323 additions and 12309 deletions

View File

@ -1,20 +1,15 @@
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = { module.exports = {
root: true, root: true,
parser: '@typescript-eslint/parser', extends: [
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], "plugin:vue/vue3-essential",
plugins: ['svelte3', '@typescript-eslint'], "eslint:recommended",
ignorePatterns: ['*.cjs'], "@vue/eslint-config-typescript",
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], "@vue/eslint-config-prettier",
settings: { ],
'svelte3/typescript': () => require('typescript'),
},
parserOptions: { parserOptions: {
sourceType: 'module', ecmaVersion: "latest",
ecmaVersion: 2020,
}, },
env: { };
browser: true,
es2017: true,
node: true,
},
}

View File

@ -1,7 +0,0 @@
#!/bin/sh
set -e
pnpm install --frozen-lockfile
pnpm lint
pnpm check

View File

@ -1,63 +0,0 @@
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
- uses: pnpm/action-setup@v2.2.2
with:
version: 7
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run build
run: VITE_API_URL="https://staging-api.modrinth.com/v2/" pnpm build
- name: Run package
run: pnpm package
- name: Run lint
run: pnpm lint
- name: Run check
run: pnpm check
release:
needs: [lint]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: pnpm/action-setup@v2.2.2
with:
version: 7
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
cache: pnpm
registry-url: 'https://registry.npmjs.org'
- name: Bump version
run: pnpm version patch --commit-hooks false --git-tag-version false
- uses: EndBug/add-and-commit@v9
with:
message: 'Bump package version [skip ci]'
default_author: github_actions
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Package
run: pnpm package
- name: Publish
run: |
cd package
npm publish --tag alpha
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@ -1,18 +0,0 @@
name: Deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Wait for CF Pages
id: cf-pages
uses: WalshyDev/cf-pages-await@v1
with:
project: 'omorphia'
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: '9ddae624c98677d68d93df6e524a6061'
githubToken: ${{ secrets.GITHUB_TOKEN }}
commitHash: ${{ steps.push-changes.outputs.commit-hash }}

37
.gitignore vendored
View File

@ -1,11 +1,28 @@
.DS_Store # Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules node_modules
/build .DS_Store
/.svelte-kit dist
/package dist-ssr
.env coverage
.env.* *.local
!.env.example
.vercel /cypress/videos/
generated/* /cypress/screenshots/
!/**/.gitkeep
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "locales"]
path = locales
url = https://github.com/modrinth/translations

View File

@ -1,31 +0,0 @@
.DS_Store
node_modules/
build/
.svelte-kit/
package/
.env
.env.*
!.env.example
.vercel
generated/
.githooks/
.github/
.idea/
.vscode/
docs/
generated/
locales/
.eslintrc.cjs
.gitignore
.gitmodules
.npmignore
.npmrc
.prettierignore
.prettierrc
postcss.config.cjs
mdsvex.config.js
svelte.config.js
tsconfig.json
pnpm-lock.yaml
src/

3
.npmrc
View File

@ -1 +1,2 @@
engine-strict = true fetch-retry-mintimeout=20000
fetch-retry-maxtimeout=120000

View File

@ -1,15 +0,0 @@
.DS_Store
node_modules
/.svelte-kit
/package
.mf/
build/
.idea/
.vscode/
.vercel_build_output
.pnpm-debug.log
generated/
.pnpm-store/
locales/
pnpm-lock.yaml
.nuxt/

View File

@ -1,7 +0,0 @@
{
"useTabs": true,
"singleQuote": true,
"printWidth": 100,
"bracketSameLine": true,
"semi": false
}

View File

@ -1,21 +0,0 @@
# MIT License
Copyright © `2022` `Modrinth`
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,62 +1,46 @@
# Omorphia # omorphia
Omorphia is Modrinth's component, style, and utility library for Svelte projects. It includes: This template should help get you started developing with Vue 3 in Vite.
- 🧩 Typed components which enhance HTML elements and provide a consistent UI ## Recommended IDE Setup
- 🎨 CSS classes to easily style elements with a coherent style
- 🧰 Typed utilities to solve common tasks quick and dependably
- ⚙️ Configuration for SvelteKit and PostCSS to simplify setups
- 🚚 A Rollup plugin to generate a cache of heavily used API requests and OpenAPI types
Read the documentation at [omorphia.modrinth.com.](https://omorphia.modrinth.com) [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Developing ## Type Support for `.vue` Imports in TS
The library lives in the `src/` folder, and the documentation lives in the `docs/` folder. TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
### Getting started If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
Install [Node (16.5+)](https://docs.volta.sh/guide/getting-started) and [PNPM](https://pnpm.io/installation) prior to developing. 1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
To start the dev server, install dependencies and run `pnpm dev`: ## Customize configuration
```bash See [Vite Configuration Reference](https://vitejs.dev/config/).
pnpm install # Install dependencies
pnpm dev # Run dev server ## Project Setup
```sh
npm install
``` ```
To use the git hooks in the repo, which will save you waiting for CI to tell you that you forgot to lint, run this: ### Compile and Hot-Reload for Development
```bash ```sh
git config core.hookspath .githooks npm run dev
``` ```
### Adding new components ### Type-Check, Compile and Minify for Production
> Replace `ComponentName` with your component name in the steps below ```sh
npm run build
1. Create a `ComponentName.svelte` file in `src/components` ```
2. Add an export for your component in [./src/index.ts](./src/index.ts)
``` ### Lint with [ESLint](https://eslint.org/)
export { default as ComponentName } from './components/ComponentName.svelte'
``` ```sh
3. Create a `ComponentName.md` file for documentation in `docs/routes/components` npm run lint
4. Add an example of your component in your `ComponentName.md` file, like so:
````md
```svelte example raised
<script lang="ts">
import { ComponentName } from 'omorphia'
</script>
<ComponentName />
```
````
## Building
To build the documentation site, run:
```bash
pnpm build
``` ```

11
docs/app.d.ts vendored
View File

@ -1,11 +0,0 @@
/// <reference types="@sveltejs/kit" />
/// <reference types="unplugin-icons/types/svelte" />
// See https://kit.svelte.dev/docs/types#the-app-namespace
// for information about these interfaces
declare namespace App {
// interface Locals {}
// interface Platform {}
// interface Session {}
// interface Stuff {}
}

View File

@ -1,37 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-color-mode="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="%sveltekit.assets%/omorphia.png" />
<link
rel="preload"
href="/assets/fonts/InterRegular.woff2"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="/assets/fonts/InterBold.woff2"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="/assets/fonts/InterSemiBold.woff2"
as="font"
type="font/woff2"
crossorigin />
<meta name="theme-color" content="#CF1971" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:image" content="https://omorphia.modrinth.com/omorphia.png" />
<meta property="og:site_name" content="Modrinth" />
%sveltekit.head%
</head>
<body>
%sveltekit.body%
</body>
</html>

View File

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 25 25" aria-hidden="true">
<path stroke="var(--accent-color)" stroke-width="2" d="M15.933 18.394c-3.261-.286-11.074-1.466-14.644-8.469m22.422 0c-2.114 4.291-10.8 11.927-16.017 13.026m6.18-21.87C10.268 3.06 5.496 9.72 5.633 14.388m17.732-5.664c-2.232-1.888-9.562-5.15-16.943 1.716m8.652-3.947c1.888 1.087 5.492 3.288 4.806 8.369m-9.956 2.787c-.286-1.888-.103-6.213 2.918-8.41m4.12 4.977a2.43 2.43 0 0 0-.075-.4m0 0c-.528-1.965-2.354-5.652-6.963-5.908m6.963 5.908c-2.856 2.601-6.11 3.11-7.65 2.975m7.65-2.975c.752-.685 1.702-2.374 2.36-3.376m-8.98 2.575c.687.744 3.468 2.369 4.978 2.231M24 12.5C24 18.851 18.851 24 12.5 24S1 18.851 1 12.5 6.149 1 12.5 1 24 6.149 24 12.5Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 747 B

View File

@ -1,76 +0,0 @@
<script lang="ts">
import { Button } from 'omorphia'
import IconMoon from 'virtual:icons/heroicons-outline/moon'
import IconSun from 'virtual:icons/heroicons-outline/sun'
export let meta: { raised: boolean; column: boolean }
let theme = 'light'
let background = meta.raised ? 'var(--color-raised-bg)' : 'var(--color-bg)'
</script>
<div class="example">
<div class="example__preview theme-{theme} base" class:column={meta.column} style:background>
<slot name="example" />
</div>
<div class="example__source">
<div class="example__source__options">
<Button
color="primary-light"
on:click={() => (theme === 'light' ? (theme = 'dark') : (theme = 'light'))}>
{#if theme === 'light'}
<IconMoon />
{:else}
<IconSun />
{/if}
</Button>
</div>
<pre class="example__source__code language-svelte"><slot name="code" /></pre>
</div>
</div>
<style lang="postcss">
.example {
margin: 1rem 0 2rem;
&__preview {
border-radius: var(--rounded-sm-top);
border: solid 2px hsl(0, 0%, 20%);
border-bottom: none;
display: flex;
grid-gap: 1rem;
flex-wrap: wrap;
position: relative;
justify-content: flex-start;
z-index: 1;
padding: 1rem;
&.column {
flex-direction: column;
}
}
&__source {
position: relative;
&__options {
position: absolute;
top: 0;
right: 0;
padding: 1rem;
display: flex;
justify-content: flex-end;
:global(button) {
color: black;
}
}
&__code {
margin: 0;
border-radius: var(--rounded-sm-bottom) !important;
background: hsl(220, 13%, 22%);
}
}
}
</style>

View File

@ -1,111 +0,0 @@
<script lang="ts">
import OmorphiaLogo from '../assets/omorphia.svg?component'
import IconLogoGithub from 'virtual:icons/carbon/logo-github'
import IconChat from 'virtual:icons/heroicons-outline/chat-alt-2'
import { onMount } from 'svelte'
let headerElement: HTMLElement
onMount(() => {
let lastScrollTop: number
window.addEventListener('scroll', () => {
let scrollTop = window.pageYOffset || document.documentElement.scrollTop
if (scrollTop > lastScrollTop && headerElement) {
headerElement.style.top = '-100%'
} else if (headerElement) {
headerElement.style.top = '0'
}
lastScrollTop = scrollTop
})
})
</script>
<header class="header" bind:this={headerElement}>
<OmorphiaLogo class="header__logo" />
<div class="header__title">Omorphia</div>
<div class="header__links">
<a class="hide-sm" href="https://modrinth.com">Modrinth.com</a>
<span class="spacer-dot hide-sm" />
<a href="https://www.npmjs.com/package/omorphia">NPM</a>
<span class="spacer-dot" />
<a href="https://rewrite.modrinth.com/discord">
<IconChat />
</a>
<a href="https://github.com/modrinth/omorphia">
<IconLogoGithub />
</a>
</div>
</header>
<style lang="postcss">
.header {
display: flex;
grid-gap: 0.5rem;
align-items: center;
flex-wrap: wrap;
padding: 1rem 1.5rem;
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 10;
background-color: hsl(0, 0%, 100%);
box-shadow: hsla(221, 39%, 11%, 0.2) 0 2px 4px 0, hsla(221, 39%, 11%, 0.05) 0 -2px 2px 0 inset;
transition: top 0.3s ease-in-out;
@media not (--sm) {
top: 0 !important;
}
@media (--sm) {
padding: 12px 2rem;
}
:global(&__logo) {
max-width: 2rem;
min-width: 2rem;
aspect-ratio: 1 / 1;
}
&__title {
font-size: 20px;
font-weight: 600;
}
&__links {
margin-left: auto;
grid-gap: 1rem;
align-items: center;
justify-content: center;
display: flex;
:global(svg) {
height: 22px;
width: auto;
}
.hide-sm {
display: none;
@media (--sm) {
display: flex;
}
}
a {
text-decoration: none;
&:not(:hover) {
color: unset;
}
}
}
}
.spacer-dot {
background-color: hsla(0, 0%, 0%, 0.2);
border-radius: var(--rounded-max);
width: 5px;
aspect-ratio: 1 / 1;
}
</style>

View File

@ -1,161 +0,0 @@
<script lang="ts">
import { page } from '$app/stores'
import IconMenu from 'virtual:icons/lucide/menu'
const cleanPath = (it: string) => it.replace(/\.\.\/routes\/.*\//, '').replace('.md', '')
const components = Object.keys(import.meta.glob('../routes/components/**'))
.map(cleanPath)
.sort()
const classes = Object.keys(import.meta.glob('../routes/classes/**'))
.map(cleanPath)
.sort()
let slideIn = false
$: if ($page.url.pathname) {
slideIn = false
}
</script>
<nav class="sidebar" class:slideIn>
<div class="sidebar__content">
<div class="section">
<a href="/" class="section__link">Introduction</a>
<a href="/setup" class="section__link">Setup</a>
</div>
<div class="section">
<span class="section__title">Usage</span>
<a href="/usage/icons" class="section__link">Using Icons</a>
<a href="/usage/css" class="section__link">Writing CSS</a>
<a href="/usage/illustrations" class="section__link">Illustrations</a>
<a href="/usage/utils" class="section__link">Built-in utilities</a>
<a href="/usage/generator" class="section__link">Generator plugin</a>
</div>
<div class="section">
<span class="section__title">Components</span>
{#each components as component}
<a href="/components/{component}" class="section__link">{component}</a>
{/each}
</div>
<div class="section">
<span class="section__title">Classes</span>
{#each classes as page}
<a href="/classes/{page}" class="section__link">{page}</a>
{/each}
</div>
</div>
<button class="sidebar__toggle" on:click={() => (slideIn = !slideIn)}>
<IconMenu />
</button>
</nav>
<style lang="postcss">
:root {
--sidebar-color: hsl(220, 15%, 40%);
--title-color: hsl(216, 10%, 80%);
--link-color: hsl(216, 10%, 90%);
--scrollbar-thumb-color: hsl(216, 10%, 70%);
}
.sidebar {
background-color: var(--sidebar-color);
color: var(--title-color);
width: var(--sidebar-width);
max-width: 70vw;
position: fixed;
left: -100%;
top: 0;
z-index: 5;
transition: left 0.2s ease-in-out;
box-shadow: 2px 0px 4px hsla(221, 39%, 11%, 0.2);
@media (--md) {
left: 0;
}
&__content {
mask-image: linear-gradient(to bottom, transparent, hsla(0, 0%, 0%, 1) 5% 95%, transparent);
padding: 88px 2rem 2rem;
height: 100vh;
max-height: 100vh;
overflow-y: auto;
grid-gap: 2.5rem;
display: flex;
flex-direction: column;
.section {
display: flex;
flex-direction: column;
grid-gap: 0.5rem;
&__title {
text-transform: uppercase;
font-size: 12px;
}
&__link {
color: var(--link-color);
text-decoration: none;
&:hover {
color: white;
text-decoration: underline;
}
}
}
}
&__toggle {
position: fixed;
left: 1rem;
bottom: 1rem;
padding: 0.5rem;
aspect-ratio: 1 / 1;
background-color: var(--accent-color);
z-index: 20;
border-radius: var(--rounded);
color: white;
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
transition: left 0.2s cubic-bezier(0.38, 0.52, 0.37, 1.27);
:global(.icon) {
width: 2rem;
height: auto;
}
@media (--md) {
visibility: hidden;
}
}
&.slideIn {
left: 0;
.sidebar__toggle {
left: calc(2rem + min(70vw, var(--sidebar-width)));
}
}
scrollbar-color: var(--scrollbar-thumb-color) var(--sidebar-color);
&::-webkit-scrollbar {
width: 1rem;
}
&::-webkit-scrollbar-track {
background-color: var(--sidebar-color);
}
&::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb-color);
border-radius: var(--rounded-max);
border: 3px solid var(--sidebar-color);
}
}
</style>

View File

@ -1,4 +0,0 @@
import { writable } from 'svelte/store'
// Used in `src/utils/send.ts`
export const token = writable('')

8
docs/global.d.ts vendored
View File

@ -1,8 +0,0 @@
declare module '$assets/images/*'
declare module '$locales/*'
declare module '*.svg?component' {
import type { SvelteComponentTyped } from 'svelte/internal'
class SVGComponent extends SvelteComponentTyped<{ class: string }> {}
export default SVGComponent
}

View File

@ -1,139 +0,0 @@
<script lang="ts">
import IconPencil from 'virtual:icons/heroicons-outline/pencil'
import { page } from '$app/stores'
import COMPONENT_API from '../../generated/COMPONENT_API.json'
import { markdownInline } from 'omorphia/utils'
export let fileName = $page.url.pathname
.substring($page.url.pathname.lastIndexOf('/') + 1)
.replace('.html', '')
export let title = fileName
export let description = 'Learn about Omorphia, the component & style library'
let editUrl = `https://github.com/modrinth/omorphia/edit/main/docs/routes/${
$page.url.pathname.replace('/', '') || 'index'
}.md`
let api = { props: [], events: [], slots: [] }
if ($page.url.pathname.includes('components')) {
api = COMPONENT_API[`${title}.svelte`]
}
</script>
<svelte:head>
<title>{title ? `${title} Omorphia` : 'Omorphia'}</title>
<meta name="description" content={description} />
</svelte:head>
{#if title}<h1>{title}</h1>{/if}
<a class="edit-link" href={editUrl}>
<IconPencil />
Edit this page on GitHub</a>
<slot />
{#if api}
<div class="extra-info">
{#if api.props.length > 0}
<h2>Properties</h2>
<table class="api-table">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{#each api.props as prop}
<tr>
<td><code>{prop.name}</code></td>
<td><code>{prop.type ?? ''}</code></td>
<td><code>{prop.value ?? ''}</code></td>
<td>
{prop.constant ? '[Read only] ' : ''}
{@html markdownInline(prop.description?.replace('null', '') || '')}
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
{#if api.events.length > 0}
<h2>Events</h2>
<table class="api-table">
<thead>
<tr>
<th>Name</th>
<th>Forwarded</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{#each api.events as event}
<tr>
<td><code>{event.name}</code></td>
<td>{!!event.parent}</td>
<td>{event.description?.replace('null', '') || ''}</td>
</tr>
{/each}
</tbody>
</table>
{/if}
{#if api.slots.length > 0}
<h2>Slots</h2>
<table class="api-table">
<thead>
<tr>
<th>Name</th>
<th>Fallback</th>
</tr>
</thead>
<tbody>
{#each api.slots as slot}
<tr>
<td><code>{slot.name}</code></td>
<td>{slot.fallback ?? 'None'}</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
{/if}
<style lang="postcss">
.edit-link {
display: flex;
align-items: center;
grid-gap: 0.5rem;
margin-bottom: 54px;
color: var(--accent-color);
}
.extra-info {
margin-top: 4rem;
}
.api-table {
border-collapse: collapse;
margin-top: -6px;
}
.api-table tr {
background-color: transparent;
border: none;
}
.api-table tbody {
border: 2px solid grey;
}
.api-table th {
text-transform: uppercase;
font-size: 12.5px;
border: none;
}
</style>

View File

@ -1,53 +0,0 @@
import { ComponentParser } from 'sveld'
import * as svelte from 'svelte/compiler'
import fs from 'fs/promises'
import path from 'path'
import { preprocess } from '../../src/config/svelte.js'
export default function sveld() {
return {
name: 'vite-plugin-sveld',
// This generates a `COMPONENT_API.json` with sveld in the `/_app` folder which is used by the docs about components
// TODO: Make more efficient & handle typescript types with `svelte2tsx`
async transform(src, id) {
if (id.includes('/src/components/')) {
await generateComponentApi()
}
},
async buildStart() {
await generateComponentApi()
},
}
}
async function parseRaw(raw, filePath) {
let { code } = await svelte.preprocess(raw, preprocess, {
filename: filePath,
})
return new ComponentParser({
verbose: false,
}).parseSvelteComponent(code, {
filePath,
moduleName: filePath,
})
}
async function generateComponentApi() {
const output = {}
const componentFiles = await fs.readdir(path.resolve('./src/components'))
for (const fileName of componentFiles.filter((name) => name.endsWith('.svelte'))) {
const filePath = path.resolve('./src/components', fileName)
const raw = (await fs.readFile(filePath)).toString()
output[fileName] = await parseRaw(raw, filePath)
}
try {
await fs.mkdir(path.resolve('./generated'))
} catch {
// Do nothing, directory already exists
}
await fs.writeFile(path.resolve('./generated/COMPONENT_API.json'), JSON.stringify(output))
}

View File

@ -1,73 +0,0 @@
<script context="module" lang="ts">
import { addMessages, init } from 'svelte-intl-precompile'
import en from '$locales/en'
addMessages('en', en)
init({
initialLocale: 'en',
fallbackLocale: 'en',
})
</script>
<script lang="ts">
import 'omorphia/styles.postcss'
import '../styles/prism-one-dark.css'
import '../styles/gh-markdown.postcss'
import Sidebar from '../components/Sidebar.svelte'
import Header from '../components/Header.svelte'
</script>
<div class="app theme-light">
<Header />
<Sidebar />
<main class="app__content">
<article>
<slot />
</article>
</main>
</div>
<style lang="postcss">
:global {
html {
overflow-y: scroll;
}
body {
margin: 0;
font-size: var(--font-size);
font-family: var(--body-font);
--accent-color: hsl(331, 80%, 45%);
--accent-color-transparent: hsla(331, 80%, 45%, 0.15);
}
}
.app {
display: flex;
flex-direction: column;
min-height: 100vh;
overflow: hidden;
background-color: var(--color-bg);
--sidebar-width: 275px;
&__content {
@media (--md) {
padding-left: var(--sidebar-width);
}
overflow-x: hidden;
overflow-y: auto;
article {
max-width: 800px;
padding-block: 9rem 4rem;
padding-inline: 24px;
@media (--sm) {
padding-inline: 48px;
padding-block: 9rem 24px;
}
}
}
}
</style>

View File

@ -1,15 +0,0 @@
```svelte example raised
<script>
import { Button } from 'omorphia'
import IconHeartSolid from 'virtual:icons/heroicons-solid/heart'
import IconCalendar from 'virtual:icons/lucide/calendar'
</script>
<div class="actions">
<Button><IconHeartSolid /> Unfollow</Button>
<span class="stat">
<IconCalendar />
Updated 12 days ago
</span>
</div>
```

View File

@ -1,5 +0,0 @@
Base should be applied to a "root" element, like `<body>`, to provide base styles for common things like text. The theme mode, `light-theme`, `dark-theme`, or `oled-theme`, should also be added to this element.
```svelte example
<div class="base theme-light">...</div>
```

View File

@ -1,33 +0,0 @@
### A simple example
```svelte example
<div class="card">
<h3>Moon/Distance to Earth</h3>
<h2>238,900 mi</h2>
<p>
The moon's distance from Earth affects the strength of ocean tides and the appearance of solar
eclipses in our skies. The average distance between the blue planet and its only natural
satellite is about 238,855 miles (384,400 kilometers), according to NASA.
</p>
</div>
```
### A more complex example
```svelte example
<script lang="ts">
import { Button } from 'omorphia'
import IconPencil from 'virtual:icons/heroicons-outline/pencil'
import { Avatar } from 'omorphia'
</script>
<div class="card">
<div class="card__overlay">
<Button raised><IconPencil /> Edit</Button>
</div>
<div class="card__banner card__banner--short card__banner--dark" />
<Avatar size="md" floatUp />
<h1 class="title">Project</h1>
<p class="summary">A project that has a description right here.</p>
</div>
```

View File

@ -1,7 +0,0 @@
```svelte example raised
Some words could go here.
<hr class="divider" />
And some other words could go here.
```

View File

@ -1,14 +0,0 @@
```svelte example raised
<script lang="ts">
import IconFile from 'virtual:icons/lucide/file'
import { Button } from 'omorphia'
</script>
<div class="file file--primary">
<div class="file__tab">
<IconFile />
<div class="file__tab__name"><b>cool-mod.jar</b></div>
<Button raised>Download</Button>
</div>
</div>
```

View File

@ -1,10 +0,0 @@
```svelte example raised
<div class="info-table">
<span class="info-table__label">License</span>
<a href="#mit" class="link">MIT</a>
<span class="info-table__label">Project ID</span>
<span>11223344</span>
<span class="info-table__label">Visibilty</span>
<span>Approved</span>
</div>
```

View File

@ -1,24 +0,0 @@
### Single example
```svelte example raised
<a class="link" href="#place"> Go somewhere! </a>
```
### Group example
```svelte example raised
<script>
import IconIssues from 'virtual:icons/heroicons-outline/exclamation'
import IconCode from 'virtual:icons/heroicons-outline/code'
import IconClock from 'virtual:icons/lucide/flag-triangle-right'
import IconWiki from 'virtual:icons/heroicons-outline/book-open'
</script>
<div class="link-group" style="max-width: 18rem">
<a class="link" href="#issues"><IconIssues /> Issues</a>
<a class="link" href="#source"><IconCode /> Source</a>
<a class="link" href="#wiki"><IconWiki /> Wiki</a>
<a class="link" href="#issues"><IconIssues /> Discord chat</a>
<a class="link" href="#source"><IconCode /> Source link</a>
</div>
```

View File

@ -1,13 +0,0 @@
```svelte example raised
<script lang="ts">
import { Avatar } from 'omorphia'
</script>
<a class="member" href="#user">
<Avatar src="https://avatars1.githubusercontent.com/u/6166773" size="sm" circle />
<div class="member__info">
<span class="member__info__link">Prospector</span>
<span>Owner</span>
</div>
</a>
```

View File

@ -1,32 +0,0 @@
### Single Example
```svelte example raised
<script>
import IconStar from 'virtual:icons/heroicons-outline/star'
</script>
<div class="stat">
<IconStar />
123K stars
</div>
```
### Group Example
```svelte example raised
<script>
import IconDownload from 'virtual:icons/heroicons-outline/download'
import IconHeart from 'virtual:icons/heroicons-outline/heart'
</script>
<div class="stat-group">
<div class="stat">
<IconDownload />
4.1B downloads
</div>
<div class="stat stat--light">
<IconHeart />
3 followers
</div>
</div>
```

View File

@ -1,15 +0,0 @@
```svelte example raised
<script>
import IconCarrot from 'virtual:icons/lucide/carrot'
import IconGlobe from 'virtual:icons/heroicons-outline/globe'
</script>
<div class="tag-group">
<div class="tag">
<IconCarrot /> Food
</div>
<div class="tag">
<IconGlobe /> World generation
</div>
</div>
```

View File

@ -1,5 +0,0 @@
```svelte example raised
<h1 class="title-primary">Tree Mod</h1>
<h2 class="title-secondary">Information</h2>
<h3 class="title-tertiary">Members</h3>
```

View File

@ -1,15 +0,0 @@
Avatars are used for project icons and user profile pictures. Low resolution images are rendered pixelated to preserve pixel art.
```svelte example raised
<script lang="ts">
import { Avatar } from 'omorphia'
</script>
<Avatar size="lg" circle src="https://avatars3.githubusercontent.com/u/44736536?v=4" />
<Avatar size="md" src="https://cdn.modrinth.com/data/AANobbMI/icon.png" />
<Avatar
size="md"
src="https://staging-cdn.modrinth.com/data/d1SqMrzw/9a39b0c80a49976b0c04053682708374e18105fe.png" />
<Avatar size="sm" />
<Avatar size="xs" circle src="https://avatars1.githubusercontent.com/u/6166773?v=4" />
```

View File

@ -1,10 +0,0 @@
```svelte example raised
<script lang="ts">
import { Badge } from 'omorphia'
</script>
<Badge color="red" label="Tomato" />
<Badge color="yellow" label="Squash" />
<Badge color="green" label="Lettuce" />
<Badge label="Onion" />
```

View File

@ -1,46 +0,0 @@
### Single example
```svelte example
<script lang="ts">
import { Button } from 'omorphia'
import IconDownload from 'virtual:icons/heroicons-outline/download'
</script>
<Button raised><IconDownload /> Download</Button>
```
### Color variants example
```svelte example raised
<script lang="ts">
import { Button } from 'omorphia'
import IconDownload from 'virtual:icons/heroicons-outline/download'
</script>
<div class="button-group">
<Button>Default</Button>
<Button color="primary">Primary</Button>
<Button color="primary-light">Light primary</Button>
<Button color="secondary">Secondary</Button>
<Button color="tertiary">Tertiary</Button>
<Button color="danger">Danger</Button>
<Button color="danger-light">Light danger</Button>
<Button color="transparent">Transparent</Button>
<Button disabled>Disabled</Button>
</div>
```
### With icons example
```svelte example
<script lang="ts">
import { Button } from 'omorphia'
import IconDownload from 'virtual:icons/heroicons-outline/download'
import IconHeart from 'virtual:icons/heroicons-outline/heart'
</script>
<div class="button-group">
<Button color="primary" raised><IconDownload /></Button>
<Button raised><IconHeart /> Follow mod</Button>
</div>
```

View File

@ -1,20 +0,0 @@
### Text-only Example
```svelte example raised
<script lang="ts">
import { Checkbox } from 'omorphia'
</script>
<Checkbox>Extra components</Checkbox>
```
### Text with Icon Example
```svelte example raised
<script lang="ts">
import { Checkbox } from 'omorphia'
import IconCarrot from 'virtual:icons/lucide/carrot'
</script>
<Checkbox><IconCarrot /> Food</Checkbox>
```

View File

@ -1,36 +0,0 @@
```svelte example raised
<script lang="ts">
import { CheckboxList } from 'omorphia'
import IconSquare from 'virtual:icons/lucide/square'
import IconCircle from 'virtual:icons/lucide/circle'
import IconTriangle from 'virtual:icons/lucide/triangle'
let selected = ['TRI']
</script>
<CheckboxList
bind:value={selected}
options={[
{
label: 'Circle',
icon: IconCircle,
value: 'CIR',
},
{
label: 'Triangle',
icon: IconTriangle,
value: 'TRI',
},
{
label: 'Square',
icon: IconSquare,
value: 'SQU',
},
{
label: 'Blank',
value: 'BLA',
},
]} />
Selected: {selected}
```

View File

@ -1,20 +0,0 @@
```svelte example raised
<script lang="ts">
import { CheckboxVirtualList } from 'omorphia'
import IconStar from 'virtual:icons/heroicons-outline/star'
let options = Array(100)
.fill({})
.map((option, index) => ({
label: 'Star-' + index,
icon: IconStar,
value: index,
}))
let selected = [22, 24]
</script>
<CheckboxVirtualList bind:value={selected} {options} />
Selected: {selected}
```

View File

@ -1,47 +0,0 @@
### Simple example
```svelte example raised
<script lang="ts">
import { Chips } from 'omorphia'
</script>
<Chips
options={[
{
label: 'One',
value: 'one',
},
{
label: 'Two',
value: 'two',
},
]} />
```
### Force an option to be selected with `neverEmpty`
```svelte example raised
<script lang="ts">
import { Chips } from 'omorphia'
let foo = 'modpack'
</script>
<Chips
neverEmpty
bind:value={foo}
options={[
{
label: 'Mod',
value: 'mod',
},
{
label: 'Modpack',
value: 'modpack',
},
{
label: 'World',
value: 'world',
},
]} />
```

View File

@ -1,7 +0,0 @@
```svelte example raised
<script lang="ts">
import { Code } from 'omorphia'
</script>
<Code text="AaBbCcDd" />
```

View File

@ -1,12 +0,0 @@
```svelte example raised
<script lang="ts">
import { Field, Slider, TextInput } from 'omorphia'
</script>
<Field label="Favorite number" let:id>
<Slider min="0" max="100" value="69" {id} />
</Field>
<Field label="Favorite color" helper="Pick whatever color you like the most" let:id>
<TextInput placeholder="Enter another color..." {id} />
</Field>
```

View File

@ -1,31 +0,0 @@
### Single constrained example
```svelte example raised column
<script lang="ts">
import { Field, FileUpload } from 'omorphia'
let file: File
</script>
<Field label="Upload image">
<FileUpload accept="image/*" constrained bind:file />
</Field>
File name: {file?.name}
```
### Multiple example
```svelte example raised column
<script lang="ts">
import { Field, FileUpload } from 'omorphia'
let files: File[] = []
</script>
<Field label="Upload file">
<FileUpload accept="*" multiple bind:files />
</Field>
Count: {files.length}
```

View File

@ -1,21 +0,0 @@
```svelte example raised
<script lang="ts">
import { Modal, Button } from 'omorphia'
import IconArrowRight from 'virtual:icons/heroicons-outline/arrow-right'
import IconCheck from 'virtual:icons/heroicons-outline/check'
</script>
<Modal title="Example modal" danger let:trigger>
<Button on:click={trigger} slot="trigger">Open modal</Button>
<p>Secret message goes here!</p>
<Button color="primary" slot="button"><IconArrowRight /> Continue</Button>
</Modal>
<Modal let:trigger size="sm">
<Button on:click={trigger} slot="trigger">Confirm modal</Button>
Are you sure you want to delete this gallery image?
<Button color="primary" slot="button"><IconCheck /> Confirm</Button>
</Modal>
```

View File

@ -1,13 +0,0 @@
```svelte example raised
<script lang="ts">
import { ModalDeletion, Button } from 'omorphia'
</script>
<ModalDeletion
type="account"
key="venashial"
let:trigger
on:deletion={() => console.log('Do something...')}>
<Button slot="trigger" color="danger" on:click={trigger}>Delete account</Button>
</ModalDeletion>
```

View File

@ -1,66 +0,0 @@
`NavRow` works well for most horizontal navigation with less than 10 items. It can be used with paths & query params, and supports specific path level (depths).
### Query example
```svelte example
<script lang="ts">
import { NavRow } from 'omorphia'
</script>
<div class="card card--strip card--pad-x">
<NavRow
level={1}
query={'tab'}
links={[
{
href: '',
label: 'All',
},
{
href: 'mods',
label: 'Mods',
},
{
href: 'modpacks',
label: 'Modpacks',
},
{
href: 'textures',
label: 'Textures',
},
{
href: 'shaders',
label: 'Shaders',
},
{
href: 'maps',
label: 'Maps',
},
]} />
</div>
```
### Route example
```svelte example
<script lang="ts">
import { NavRow } from 'omorphia'
</script>
<NavRow
level={1}
links={[
{
href: '/Button',
label: 'Button',
},
{
href: '/Chips',
label: 'Chips',
},
{
href: '/NavRow',
label: 'NavRow',
},
]} />
```

View File

@ -1,9 +0,0 @@
Use pagination to show a set of page numbers and navigation directions to move through paginated data.
```svelte example
<script lang="ts">
import { Pagination } from 'omorphia'
</script>
<Pagination page={20} count={500} />
```

View File

@ -1,36 +0,0 @@
### Default option example
```svelte example raised
<script lang="ts">
import { Select } from 'omorphia'
let sortMethod = 'downloads'
</script>
<Select
options={[
{ value: '', label: 'Relevance' },
{ value: 'downloads', label: 'Downloads' },
{ value: 'follows', label: 'Followers' },
{ value: 'newest', label: 'Recently created' },
{ value: 'updated', label: 'Recently updated' },
]}
bind:value={sortMethod} />
```
### Icon example
```svelte example raised
<script lang="ts">
import { Select } from 'omorphia'
import IconSun from 'virtual:icons/heroicons-outline/sun'
</script>
<Select
options={[
{ value: '1', label: 'Light' },
{ value: '2', label: 'Dark' },
{ value: '3', label: 'OLED' },
]}
icon={IconSun} />
```

View File

@ -1,7 +0,0 @@
```svelte example raised
<script lang="ts">
import { Slider } from 'omorphia'
</script>
<Slider min="0" max="10" value="4" />
```

View File

@ -1,9 +0,0 @@
```svelte example raised
<script lang="ts">
import { TextInput } from 'omorphia'
import IconSearch from 'virtual:icons/heroicons-outline/search'
</script>
<TextInput placeholder="Enter another color..." />
<TextInput icon={IconSearch} placeholder="Search..." />
```

View File

@ -1,25 +0,0 @@
---
title: Introduction
---
## Overview
Omorphia is Modrinth's component, style, and utility library for Svelte projects. It includes:
- 🧩 Typed components which enhance HTML elements and provide a consistent UI
- 🎨 CSS classes to easily style elements with a coherent style
- 🧰 Typed utilities to solve common tasks quick and dependably
- ⚙️ Configuration for SvelteKit and PostCSS to simplify setups
- 🚚 A Rollup plugin to generate a cache of heavily used API requests and OpenAPI types
Omorphia is used in [Knossos](https://github.com/modrinth/knossos) (modrinth.com) and [Theseus](https://github.com/modrinth/theseus) (Minecraft launcher).
It uses [Svelte](https://svelte.dev/) to deliver the best performance with the least boilerplate.
## Try Omorphia online
You can try Omorphia online via [➜ **CodeSandbox** 💻](https://codesandbox.io/s/omorphia-starter-bsbgke).
## Getting started
Follow the instructions on the [➜ **setup page** 🛠️](/setup).

View File

@ -1,210 +0,0 @@
---
title: Setup
---
## `0.` Prerequisites
First install the following:
- [Node 16.x](https://docs.volta.sh/guide/getting-started) or higher
- [PNPM](https://pnpm.io/installation) (required for Modrinth projects)
## `1.` Create a SvelteKit project
Run the following command to create a SvelteKit project:
```bash
pnpm create svelte
```
Follow the instructions to install dependencies and setup git.
## `2.` Add Omorphia to your project
```bash
pnpm add omorphia
```
## `3.` Setup translations
Install the translations submodule:
```bash
git submodule add https://github.com/modrinth/translations locales/
```
Install `svelte-intl-precompile`:
```bash
pnpm add svelte-intl-precompile -D
```
Add translations in `src/routes/__layout.svelte`:
```html
<script context="module" lang="ts">
import { init, waitLocale, t, getLocaleFromAcceptLanguageHeader } from 'svelte-intl-precompile'
import { registerAll, availableLocales } from '$locales'
registerAll()
export const load: import('@sveltejs/kit').Load = async ({ session }) => {
init({
fallbackLocale: 'en',
initialLocale: getLocaleFromAcceptLanguageHeader(session.acceptLanguage, availableLocales),
})
await waitLocale()
return {}
}
</script>
```
## `4.` Configure SvelteKit
Add the following parts to your `svelte.config.js` file:
```js
import adapter from '@sveltejs/adapter-auto'
import { preprocess } from 'omorphia/config/svelte'
import path from 'path'
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [preprocess],
kit: {
adapter: adapter(),
alias: {
$generated: path.resolve('./generated'),
$stores: path.resolve('./src/stores'),
},
},
}
export default config
```
Create a `src/stores/account.ts` file with a `token` store export:
```ts
import { writable } from 'svelte/store'
export const token = writable('')
```
## `5.` Configure Vite
Add the following to your `vite.config.js` file:
```js
import { plugins } from 'omorphia/config/vite.js'
import { Generator } from 'omorphia/plugins'
import precompileIntl from 'svelte-intl-precompile/sveltekit-plugin'
/** @type {import('vite').UserConfig} */
const config = {
plugins: [
...plugins,
precompileIntl('locales'),
Generator({
gameVersions: true,
openapi: true,
// Add more if needed
}),
],
server: {
fs: {
allow: ['generated'],
},
},
}
export default config
```
## `6.` Configure PostCSS
Create a `postcss.config.cjs` file in the root of your project.
Add the following line to that file:
```js
module.exports = require('omorphia/config/postcss.cjs')
```
## `7.` Setup styles
Import styles in `src/routes/__layout.svelte`:
```html
<script lang="ts">
import 'omorphia/styles.postcss'
</script>
```
Add the `base` class and a theme to the `<body>` tag in `src/app.html`:
```html
<body class="base theme-light">
%sveltekit.body%
</body>
```
## `8.` Setup fonts
Copy the the `fonts/` folder from [Omorphia's repository](https://github.com/modrinth/omorphia/blob/main/docs/static/assets/fonts) and place them in the `static/` folder at the root of your project.
Add the following preload tags to your head in `app.html` to speed up font loading:
<!-- prettier-ignore-start -->
```html
<head>
<link rel="preload" href="/fonts/InterRegular.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/InterBold.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/InterSemiBold.woff2" as="font" type="font/woff2" crossorigin>
</head>
```
<!-- prettier-ignore-end -->
## `9.` Using Omorphia
### Developing
Start the development server with:
```bash
pnpm dev
```
> To get Svelte language support in your code editor, [use this list of extensions.](https://sveltesociety.dev/tools#editor-support)
### Components
Use a component by importing from `omorphia`. For example, use the [Button component](/components/Button) like so:
```svelte example raised
<script lang="ts">
import { Button } from 'omorphia'
</script>
<Button color="primary">I'm a button!</Button>
```
### Utils
Use a utility by importing from `omorphia/utils`.
```svelte example raised
<script lang="ts">
import { ago } from 'omorphia/utils'
</script>
{ago(Date.now() - 100000)}
```
### Using icons and styles
Follow the guides on the sidebar to learn how to use [icons](/usage/icons) and general concepts.

View File

@ -1,32 +0,0 @@
---
title: Writing CSS
---
## Conventions
### Avoid inconsistent CSS units
Prefer using `rem` units, using only whole and half units, eg. `2rem` or `1.5rem`. If you need a specific pixel (`px`) measurement, use `px` and add comment explaining why you used it. The one exception is that `0.25rem` is allowed.
> Using `rem` units lets you change the scale of the UI by simply changing the body font size.
### Always use `HSL` colors
### All colors should be theme variables
## Abilities
Omorphia leverages PostCSS to allow you to write in future-standards-compliant CSS. Browse [the CSSWG drafts](https://cssdb.org/) to see what is possible (not including stage 0).
Notable features:
- [Nesting](https://www.w3.org/TR/css-nesting-1/#example-aecb8796)
- [Gap](https://developer.mozilla.org/en-US/docs/Web/CSS/gap)
- [`clamp` function](<https://developer.mozilla.org/en-US/docs/Web/CSS/clamp()>)
- [Custom Media Queries](https://www.w3.org/TR/mediaqueries-5/#example-532b0adb)
- [`:has()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:has)
- [place-content](https://developer.mozilla.org/en-US/docs/Web/CSS/place-content)
## Styles
Conform to [BEM styling](http://getbem.com/introduction/) wherever possible. When working in components, you may want to leverage [Svelte's conditional class shorthand](https://svelte.dev/tutorial/class-shorthand) instead of BEM's modifier class name format.

View File

@ -1,38 +0,0 @@
---
title: Generator plugin
---
The generator plugin creates static files from API responses to increase performance and perform tasks that would not be possible on the client. It regenerates files every 7 days, or when the plugin settings change.
### Current options
- `projectColors` (false) generates colors for every project
- `tags` (false) copies & parses tags from API
- `gameVersions` copies game versions from API
- `landingPage` gets icon urls for top 100 mods
> All options are disabled by default
## Configuration
```js
import Generator from 'omorphia/plugins/generator'
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
vite: {
plugins: [
Generator({
projectColors: true,
tags: true,
gameVersions: true,
landingPage: true,
}),
],
},
},
}
export default config
```

View File

@ -1,27 +0,0 @@
---
title: Icons
---
## Choosing icons
The follwing icon packs are included with omorphia:
`heroicons-outline` `lucide` `fa-regular` `heroicons-solid` `carbon` `simple-icons`
Aim to find icons from `heroicons-outline` first, and then from the following packs if you can't find what you are looking for. [Browse icons...](https://icones.js.org/collection/heroicons-outline)
## Using icons
Import an icon in the `<script>` tag of your component.
Then use the icon as if it were a Svelte component:
> You can style the icon with the `.icon` class. Note, you will have to use the `:global(.icon)` selector in Svelte components.
```svelte example
<script lang="ts">
import IconHeart from 'virtual:icons/heroicons-outline/heart'
</script>
<p>That's lovely! <IconHeart /></p>
```

View File

@ -1,21 +0,0 @@
---
title: Using illustrations
---
Find an illustration from [unDraw](https://undraw.co/illustrations) and download it as an SVG.
Put the illustration in the `src/assets/images/illustrations` folder. Rename it to `undraw_` + the illustration slug.
Replace colors in the SVG with CSS variables such as `var(--color-brand)` and `var(--color-raised)`. For colors that are the same as the font color, use `currentColor`.
Add the `.illustration` class to the SVG
Import the SVG in the `<script>` of your svelte file, and treat the illustration as a Svelte component:
```svelte
<script>
import NoData from '$assets/images/illustrations/undraw_no_data.svg'
</script>
<NoData />
```

View File

@ -1,116 +0,0 @@
---
title: Built-in utilities
---
## API requests
Use the `send` function to make API requests.
```svelte example raised
<script lang="ts">
import { send } from 'omorphia/utils'
const project = send<'getProject'>('GET', 'project/sodium')
</script>
{#await project}
fetching...
{:then project}
{project.downloads} downloads
{/await}
```
## Markdown
Use the markdown utilities to parse markdown text into HTML. Both markdown parsers have HTML sanitization built-in.
### Body parser
The `markdown` parser is designed for bodies of markdown text and supports images, tables, lists, and youtube `<iframe>`s.
> Use the `.markdown` class on the element containing your parsed markdown.
````svelte example
<script lang="ts">
import { markdown } from 'omorphia/utils'
const source =
'## Example markdown \n\
This is **some** *text*! \n\
`console.log("test")` \n\
#### An image \n\
![](https://cdn.modrinth.com/data/YL57xq9U/images/d382106b9a2b943d06107c31c139c77849f1a0e8.png)'
</script>
<div class="card markdown">
{@html markdown(source)}
{@html markdown(
` | Syntax | Description |
| ----------- | ----------- |
| Header | Title |
| Paragraph | Text |`
)}
{@html markdown('```js\nconsole.log("test")\n```')}
</div>
````
### Inline parser
The `markdownInline` parser is perfect for translations and short bios. It doesn't allow complex elements such as images or tables.
```svelte example raised
<script lang="ts">
import { markdownInline } from 'omorphia/utils'
const source = 'This is some **bolded** and *italicized* text.'
</script>
<p>{@html markdownInline(source)}</p>
```
## Human readable "ago" times
```svelte example raised
<script lang="ts">
import { ago } from 'omorphia/utils'
</script>
<p>Something happened {ago(Date.now())}.</p>
<p>Something happened {ago(new Date(Date.now() - 1000 * 60 * 60 * 2))}.</p>
<p>Something happened {ago(new Date(Date.now() - 1000 * 60 * 60 * 24 * 7))}.</p>
<p>Something happened {ago(new Date(Date.now() - 1000 * 60 * 60 * 24 * 7 * 5))}.</p>
```
## Permissions
The `Permissions` class provides an easy way to manage user permissions.
```svelte example raised
<script lang="ts">
import { Permissions } from 'omorphia/utils'
const permissions = new Permissions(128) // Can be integer or 'ALL'
</script>
<p>
<input type="checkbox" bind:checked={permissions.uploadVersions} id="ex-1" />
<label for="ex-1">Can edit versions</label><br />
<input type="checkbox" bind:checked={permissions.deleteProject} id="ex-2" />
<label for="ex-2">Can delete project</label><br /><br />
Integer: {permissions.toInteger()}<br />
Can access settings page: {permissions.settingsPage}
</p>
```
## Versions
The `formatVersions` function provides an easy way to parse a project's versions into a readable string.
```svelte example raised
<script lang="ts">
import { formatVersions } from 'omorphia/utils'
</script>
<p>{formatVersions(['1.18', '1.18.1', '1.18.2', '1.17.1'])}</p>
```

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,392 +0,0 @@
*:not(.example__preview) * {
:where(a):not(.link) {
text-decoration: none;
&.absent {
color: #cc0000;
}
&.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
}
&:where(h1, h2, h3, h4, h5, h6) {
margin: 30px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative;
}
&:where(h2:first-child, h1:first-child, h1:first-child
+ h2, h3:first-child, h4:first-child, h5:first-child, h6:first-child) {
margin-top: 0;
padding-top: 0;
}
&:where(h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover
a.anchor, h6:hover a.anchor) {
text-decoration: none;
}
&:where(h1 tt, h1 code) {
font-size: inherit;
}
&:where(h2 tt, h2 code) {
font-size: inherit;
}
&:where(h3 tt, h3 code) {
font-size: inherit;
}
&:where(h4 tt, h4 code) {
font-size: inherit;
}
&:where(h5 tt, h5 code) {
font-size: inherit;
}
&:where(h6 tt, h6 code) {
font-size: inherit;
}
&:where(h1) {
font-size: 40px;
color: black;
font-weight: 600;
@media (--md) {
font-size: 54px;
}
}
&:where(h2) {
font-size: 24px;
/*border-bottom: 1px solid #cccccc;*/
color: black;
margin-top: 50px;
}
&:where(h3) {
font-size: 18px;
}
&:where(h4) {
font-size: 16px;
}
&:where(h5) {
font-size: 14px;
}
&:where(h6) {
color: #777777;
font-size: 14px;
}
&:where(p, blockquote, ul, ol, dl, li, table, pre) {
margin: 15px 0;
}
&:where(hr) {
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0;
}
&:where(body > h2:first-child) {
margin-top: 0;
padding-top: 0;
}
&:where(body > h1:first-child) {
margin-top: 0;
padding-top: 0;
}
&:where(body > h1:first-child + h2) {
margin-top: 0;
padding-top: 0;
}
&:where(body > h3:first-child, body > h4:first-child, body > h5:first-child, body
> h6:first-child) {
margin-top: 0;
padding-top: 0;
}
&:where(a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child
h5, a:first-child h6) {
margin-top: 0;
padding-top: 0;
}
&:where(h1 p, h2 p, h3 p, h4 p, h5 p, h6 p) {
margin-top: 0;
}
&:where(li p.first) {
display: inline-block;
}
&:where(ul, ol) {
padding-left: 30px;
}
&:where(ul :first-child, ol :first-child) {
margin-top: 0;
}
&:where(ul :last-child, ol :last-child) {
margin-bottom: 0;
}
&:where(dl) {
padding: 0;
}
&:where(dl dt) {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
&:where(dl dt:first-child) {
padding: 0;
}
&:where(dl dt > :first-child) {
margin-top: 0;
}
&:where(dl dt > :last-child) {
margin-bottom: 0;
}
&:where(dl dd) {
margin: 0 0 15px;
padding: 0 15px;
}
&:where(dl dd > :first-child) {
margin-top: 0;
}
&:where(dl dd > :last-child) {
margin-bottom: 0;
}
&:where(blockquote) {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777;
}
&:where(blockquote > :first-child) {
margin-top: 0;
}
&:where(blockquote > :last-child) {
margin-bottom: 0;
}
&:where(table) {
padding: 0;
}
&:where(table tr) {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0;
}
&:where(table tr:nth-child(2n)) {
background-color: #f8f8f8;
}
&:where(table tr th) {
font-weight: bold;
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px;
}
&:where(table tr td) {
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px;
}
&:where(table tr th :first-child, table tr td :first-child) {
margin-top: 0;
}
&:where(table tr th :last-child, table tr td :last-child) {
margin-bottom: 0;
}
&:where(img) {
max-width: 100%;
}
&:where(span.frame) {
display: block;
overflow: hidden;
}
&:where(span.frame > span) {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto;
}
&:where(span.frame span img) {
display: block;
float: left;
}
&:where(span.frame span span) {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0;
}
&:where(span.align-center) {
display: block;
overflow: hidden;
clear: both;
}
&:where(span.align-center > span) {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center;
}
&:where(span.align-center span img) {
margin: 0 auto;
text-align: center;
}
&:where(span.align-right) {
display: block;
overflow: hidden;
clear: both;
}
&:where(span.align-right > span) {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right;
}
&:where(span.align-right span img) {
margin: 0;
text-align: right;
}
&:where(span.float-left) {
display: block;
margin-right: 13px;
overflow: hidden;
float: left;
}
&:where(span.float-left span) {
margin: 13px 0 0;
}
&:where(span.float-right) {
display: block;
margin-left: 13px;
overflow: hidden;
float: right;
}
&:where(span.float-right > span) {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right;
}
&:where(code, tt) {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}
&:where(pre code) {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}
&:where(pre) {
background-color: #f8f8f8;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: var(--rounded-sm) !important;
}
&:where(pre code, pre tt) {
background-color: transparent;
border: none;
}
&:where(h2) {
font-weight: 500;
}
&:where(blockquote) {
border-left: 4px solid var(--accent-color);
padding: 15px 15px;
color: unset;
background-color: var(--accent-color-transparent);
}
&:where(a):not(.link) {
color: var(--accent-color);
&:hover {
text-decoration: underline;
}
}
&:where(p) {
line-height: 1.5;
}
}

View File

@ -1,443 +0,0 @@
/**
* One Dark theme for prism.js
* Based on Atom's One Dark theme: https://github.com/atom/atom/tree/master/packages/one-dark-syntax
*/
/**
* One Dark colours (accurate as of commit 8ae45ca on 6 Sep 2018)
* From colors.less
* --mono-1: hsl(220, 14%, 71%);
* --mono-2: hsl(220, 9%, 55%);
* --mono-3: hsl(220, 10%, 40%);
* --hue-1: hsl(187, 47%, 55%);
* --hue-2: hsl(207, 82%, 66%);
* --hue-3: hsl(286, 60%, 67%);
* --hue-4: hsl(95, 38%, 62%);
* --hue-5: hsl(355, 65%, 65%);
* --hue-5-2: hsl(5, 48%, 51%);
* --hue-6: hsl(29, 54%, 61%);
* --hue-6-2: hsl(39, 67%, 69%);
* --syntax-fg: hsl(220, 14%, 71%);
* --syntax-bg: hsl(220, 13%, 18%);
* --syntax-gutter: hsl(220, 14%, 45%);
* --syntax-guide: hsla(220, 14%, 71%, 0.15);
* --syntax-accent: hsl(220, 100%, 66%);
* From syntax-variables.less
* --syntax-selection-color: hsl(220, 13%, 28%);
* --syntax-gutter-background-color-selected: hsl(220, 13%, 26%);
* --syntax-cursor-line: hsla(220, 100%, 80%, 0.04);
*/
code[class*='language-'],
pre[class*='language-'] {
background: hsl(220, 13%, 18%);
color: hsl(220, 14%, 71%);
font-family: 'Fira Code', 'Fira Mono', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Selection */
code[class*='language-']::-moz-selection,
code[class*='language-'] *::-moz-selection,
pre[class*='language-'] *::-moz-selection {
background: hsl(220, 13%, 28%);
color: inherit;
text-shadow: none;
}
code[class*='language-']::selection,
code[class*='language-'] *::selection,
pre[class*='language-'] *::selection {
background: hsl(220, 13%, 28%);
color: inherit;
text-shadow: none;
}
/* Code blocks */
pre[class*='language-'] {
padding: 16px;
margin: 0.5em 0;
overflow: auto;
border-radius: var(--rounded);
}
/* Inline code */
:not(pre) > code[class*='language-'] {
padding: 0.2em 0.3em;
border-radius: 0.3em;
white-space: normal;
}
/* Print */
@media print {
code[class*='language-'],
pre[class*='language-'] {
text-shadow: none;
}
}
.token.comment,
.token.prolog,
.token.cdata {
color: hsl(220, 10%, 40%);
}
.token.doctype,
.token.punctuation,
.token.entity {
color: hsl(220, 14%, 71%);
}
.token.attr-name,
.token.class-name,
.token.boolean,
.token.constant,
.token.number,
.token.atrule {
color: hsl(29, 54%, 61%);
}
.token.keyword {
color: hsl(286, 60%, 67%);
}
.token.property,
.token.tag,
.token.symbol,
.token.deleted,
.token.important {
color: hsl(355, 65%, 65%) !important;
display: unset;
}
.token.selector,
.token.string,
.token.char,
.token.builtin,
.token.inserted,
.token.regex,
.token.attr-value,
.token.attr-value > .token.punctuation {
color: hsl(95, 38%, 62%);
}
.token.variable,
.token.operator,
.token.function {
color: hsl(207, 82%, 66%);
}
.token.url {
color: hsl(187, 47%, 55%);
}
/* HTML overrides */
.token.attr-value > .token.punctuation.attr-equals,
.token.special-attr > .token.attr-value > .token.value.css {
color: hsl(220, 14%, 71%);
}
/* CSS overrides */
.language-css .token.selector {
color: hsl(355, 65%, 65%);
}
.language-css .token.property {
color: hsl(220, 14%, 71%);
}
.language-css .token.function,
.language-css .token.url > .token.function {
color: hsl(187, 47%, 55%);
}
.language-css .token.url > .token.string.url {
color: hsl(95, 38%, 62%);
}
.language-css .token.important,
.language-css .token.atrule .token.rule {
color: hsl(286, 60%, 67%);
}
/* JS overrides */
.language-javascript .token.operator {
color: hsl(286, 60%, 67%);
}
.language-javascript
.token.template-string
> .token.interpolation
> .token.interpolation-punctuation.punctuation {
color: hsl(5, 48%, 51%);
}
/* JSON overrides */
.language-json .token.operator {
color: hsl(220, 14%, 71%);
}
.language-json .token.null.keyword {
color: hsl(29, 54%, 61%);
}
/* MD overrides */
.language-markdown .token.url,
.language-markdown .token.url > .token.operator,
.language-markdown .token.url-reference.url > .token.string {
color: hsl(220, 14%, 71%);
}
.language-markdown .token.url > .token.content {
color: hsl(207, 82%, 66%);
}
.language-markdown .token.url > .token.url,
.language-markdown .token.url-reference.url {
color: hsl(187, 47%, 55%);
}
.language-markdown .token.blockquote.punctuation,
.language-markdown .token.hr.punctuation {
color: hsl(220, 10%, 40%);
font-style: italic;
}
.language-markdown .token.code-snippet {
color: hsl(95, 38%, 62%);
}
.language-markdown .token.bold .token.content {
color: hsl(29, 54%, 61%);
}
.language-markdown .token.italic .token.content {
color: hsl(286, 60%, 67%);
}
.language-markdown .token.strike .token.content,
.language-markdown .token.strike .token.punctuation,
.language-markdown .token.list.punctuation,
.language-markdown .token.title.important > .token.punctuation {
color: hsl(355, 65%, 65%);
}
/* General */
.token.bold {
font-weight: bold;
}
.token.comment,
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token.namespace {
opacity: 0.8;
}
/* Plugin overrides */
/* Selectors should have higher specificity than those in the plugins' default stylesheets */
/* Show Invisibles plugin overrides */
.token.token.tab:not(:empty):before,
.token.token.cr:before,
.token.token.lf:before,
.token.token.space:before {
color: hsla(220, 14%, 71%, 0.15);
text-shadow: none;
}
/* Toolbar plugin overrides */
/* Space out all buttons and move them away from the right edge of the code block */
div.code-toolbar > .toolbar.toolbar > .toolbar-item {
margin-right: 0.4em;
}
/* Styling the buttons */
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span {
background: hsl(220, 13%, 26%);
color: hsl(220, 9%, 55%);
padding: 0.1em 0.4em;
border-radius: 0.3em;
}
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover,
div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus {
background: hsl(220, 13%, 28%);
color: hsl(220, 14%, 71%);
}
/* Line Highlight plugin overrides */
/* The highlighted line itself */
.line-highlight.line-highlight {
background: hsla(220, 100%, 80%, 0.04);
}
/* Default line numbers in Line Highlight plugin */
.line-highlight.line-highlight:before,
.line-highlight.line-highlight[data-end]:after {
background: hsl(220, 13%, 26%);
color: hsl(220, 14%, 71%);
padding: 0.1em 0.6em;
border-radius: 0.3em;
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); /* same as Toolbar plugin default */
}
/* Hovering over a linkable line number (in the gutter area) */
/* Requires Line Numbers plugin as well */
pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before {
background-color: hsla(220, 100%, 80%, 0.04);
}
/* Line Numbers and Command Line plugins overrides */
/* Line separating gutter from coding area */
.line-numbers.line-numbers .line-numbers-rows,
.command-line .command-line-prompt {
border-right-color: hsla(220, 14%, 71%, 0.15);
}
/* Stuff in the gutter */
.line-numbers .line-numbers-rows > span:before,
.command-line .command-line-prompt > span:before {
color: hsl(220, 14%, 45%);
}
/* Match Braces plugin overrides */
/* Note: Outline colour is inherited from the braces */
.rainbow-braces .token.token.punctuation.brace-level-1,
.rainbow-braces .token.token.punctuation.brace-level-5,
.rainbow-braces .token.token.punctuation.brace-level-9 {
color: hsl(355, 65%, 65%);
}
.rainbow-braces .token.token.punctuation.brace-level-2,
.rainbow-braces .token.token.punctuation.brace-level-6,
.rainbow-braces .token.token.punctuation.brace-level-10 {
color: hsl(95, 38%, 62%);
}
.rainbow-braces .token.token.punctuation.brace-level-3,
.rainbow-braces .token.token.punctuation.brace-level-7,
.rainbow-braces .token.token.punctuation.brace-level-11 {
color: hsl(207, 82%, 66%);
}
.rainbow-braces .token.token.punctuation.brace-level-4,
.rainbow-braces .token.token.punctuation.brace-level-8,
.rainbow-braces .token.token.punctuation.brace-level-12 {
color: hsl(286, 60%, 67%);
}
/* Diff Highlight plugin overrides */
/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */
pre.diff-highlight > code .token.token.deleted:not(.prefix),
pre > code.diff-highlight .token.token.deleted:not(.prefix) {
background-color: hsla(353, 100%, 66%, 0.15);
}
pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection,
pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection,
pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection,
pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection {
background-color: hsla(353, 95%, 66%, 0.25);
}
pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection,
pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection,
pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection,
pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection {
background-color: hsla(353, 95%, 66%, 0.25);
}
pre.diff-highlight > code .token.token.inserted:not(.prefix),
pre > code.diff-highlight .token.token.inserted:not(.prefix) {
background-color: hsla(137, 100%, 55%, 0.15);
}
pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection,
pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection,
pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection,
pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection {
background-color: hsla(135, 73%, 55%, 0.25);
}
pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection,
pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection,
pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection,
pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection {
background-color: hsla(135, 73%, 55%, 0.25);
}
/* Previewers plugin overrides */
/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-dark-ui */
/* Border around popup */
.prism-previewer.prism-previewer:before,
.prism-previewer-gradient.prism-previewer-gradient div {
border-color: hsl(224, 13%, 17%);
}
/* Angle and time should remain as circles and are hence not included */
.prism-previewer-color.prism-previewer-color:before,
.prism-previewer-gradient.prism-previewer-gradient div,
.prism-previewer-easing.prism-previewer-easing:before {
border-radius: 0.3em;
}
/* Triangles pointing to the code */
.prism-previewer.prism-previewer:after {
border-top-color: hsl(224, 13%, 17%);
}
.prism-previewer-flipped.prism-previewer-flipped.after {
border-bottom-color: hsl(224, 13%, 17%);
}
/* Background colour within the popup */
.prism-previewer-angle.prism-previewer-angle:before,
.prism-previewer-time.prism-previewer-time:before,
.prism-previewer-easing.prism-previewer-easing {
background: hsl(219, 13%, 22%);
}
/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */
/* For time, this is the alternate colour */
.prism-previewer-angle.prism-previewer-angle circle,
.prism-previewer-time.prism-previewer-time circle {
stroke: hsl(220, 14%, 71%);
stroke-opacity: 1;
}
/* Stroke colours of the handle, direction point, and vector itself */
.prism-previewer-easing.prism-previewer-easing circle,
.prism-previewer-easing.prism-previewer-easing path,
.prism-previewer-easing.prism-previewer-easing line {
stroke: hsl(220, 14%, 71%);
}
/* Fill colour of the handle */
.prism-previewer-easing.prism-previewer-easing circle {
fill: transparent;
}

@ -1 +0,0 @@
Subproject commit a10e7f264d805e71850730402eeba420d1b8c523

View File

@ -1,29 +0,0 @@
import { defineMDSveXConfig as defineConfig } from 'mdsvex'
import examples from 'mdsvexamples'
import path from 'path'
const config = defineConfig({
extensions: ['.svelte.md', '.md', '.svx'],
smartypants: {
dashes: 'oldschool',
},
remarkPlugins: [
[
examples,
{
defaults: {
Wrapper: path.resolve('./docs/components/Example.svelte'),
},
},
],
],
rehypePlugins: [],
layout: {
_: './docs/layout/page.svelte',
},
})
export default config

4602
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,104 +1,35 @@
{ {
"name": "omorphia", "name": "omorphia",
"version": "0.0.67", "version": "0.0.0",
"description": "A beautiful Svelte component & style library", "private": true,
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite",
"build": "vite build", "build": "run-p type-check build-only",
"package": "svelte-kit package && merge-dirs package/src package", "preview": "vite preview",
"watch:package": "svelte-kit package --watch", "build-only": "vite build",
"preview": "vite preview", "type-check": "vue-tsc --noEmit",
"prepare": "svelte-kit sync", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
"check": "svelte-check --tsconfig ./tsconfig.json", },
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", "dependencies": {
"lint": "prettier --ignore-path .prettierignore --check --plugin-search-dir=. . && eslint --ignore-path .prettierignore .", "vite-svg-loader": "^4.0.0",
"format": "prettier --ignore-path .prettierignore --write --plugin-search-dir=. ." "vue": "^3.2.45",
}, "vue-router": "^4.1.6"
"type": "module", },
"svelte": "index.js", "devDependencies": {
"repository": { "@rushstack/eslint-patch": "^1.1.4",
"type": "git", "@types/node": "^18.11.12",
"url": "https://github.com/modrinth/omorphia.git" "@vitejs/plugin-vue": "^4.0.0",
}, "@vue/eslint-config-prettier": "^7.0.0",
"keywords": [ "@vue/eslint-config-typescript": "^11.0.0",
"UI", "@vue/tsconfig": "^0.1.3",
"framework", "eslint": "^8.22.0",
"components", "eslint-plugin-vue": "^9.3.0",
"library" "npm-run-all": "^4.1.5",
], "prettier": "^2.7.1",
"license": "MIT", "sass": "^1.57.1",
"bugs": { "sass-loader": "^13.2.0",
"url": "https://github.com/modrinth/omorphia/issues" "typescript": "~4.7.4",
}, "vite": "^4.0.0",
"homepage": "https://omorphia.modrinth.com", "vue-tsc": "^1.0.12"
"devDependencies": { }
"@sveltejs/adapter-static": "^1.0.0-next.29",
"@sveltejs/kit": "1.0.0-next.377",
"@types/cli-progress": "^3.11.0",
"@types/marked": "^4.0.3",
"@types/throttle-debounce": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^5.10.1",
"@typescript-eslint/parser": "^5.10.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-svelte3": "^3.2.1",
"mdsvex": "^0.10.5",
"mdsvexamples": "^0.3.1",
"merge-dirs": "^0.2.1",
"nodemon": "^2.0.15",
"prettier": "^2.6.2",
"prettier-plugin-svelte": "^2.7.0",
"sveld": "^0.13.4",
"svelte": "^3.48.0",
"svelte-check": "^2.8.0",
"svelte-intl-precompile": "^0.11.1",
"svelte-preprocess": "^4.10.7",
"svelte2tsx": "^0.5.11",
"tslib": "^2.3.1",
"typescript": "~4.7.4",
"vite": "^3.0.0"
},
"dependencies": {
"@iconify-json/carbon": "^1.1.1",
"@iconify-json/fa-regular": "^1.1.1",
"@iconify-json/heroicons-outline": "^1.1.1",
"@iconify-json/heroicons-solid": "^1.1.1",
"@iconify-json/lucide": "^1.1.7",
"@iconify-json/simple-icons": "^1.1.14",
"@poppanator/sveltekit-svg": "^0.3.1",
"cli-progress": "^3.11.1",
"cssnano": "^5.1.1",
"fast-average-color-node": "^2.2.0",
"highlight.js": "^11.5.1",
"insane": "^2.6.2",
"jimp": "^0.16.1",
"marked": "^4.0.12",
"openapi-typescript": "^5.4.0",
"postcss": "^8.4.8",
"postcss-easy-import": "^4.0.0",
"postcss-extend-rule": "^4.0.0",
"postcss-import": "^14.0.2",
"postcss-import-ext-glob": "^2.0.1",
"postcss-load-config": "^3.1.4",
"postcss-nested": "^5.0.6",
"postcss-preset-env": "^7.7.1",
"postcss-pxtorem": "^6.0.0",
"sanitize.css": "^13.0.0",
"svelte-tiny-virtual-list": "^2.0.5",
"svelte-use-click-outside": "^1.0.0",
"throttle-debounce": "^3.0.1",
"undici": "^5.2.0",
"unplugin-icons": "^0.14.7"
},
"engines": {
"node": ">=16.5.0"
},
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"vite": "^3.0.0",
"//": "TODO: remove after upstream PR is merged (https://github.com/mattjennings/mdsvexamples/pull/16)"
}
}
}
} }

5621
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
module.exports = require('./src/config/postcss.cjs')

1
public/favicon.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;"><path d="M15.933,18.394c-3.261,-0.286 -11.074,-1.466 -14.644,-8.469m22.422,-0c-2.114,4.291 -10.8,11.927 -16.017,13.026m6.18,-21.87c-3.606,1.979 -8.378,8.639 -8.241,13.307m17.732,-5.664c-2.232,-1.888 -9.562,-5.15 -16.943,1.716m8.652,-3.947c1.888,1.087 5.492,3.288 4.806,8.369m-9.956,2.787c-0.286,-1.888 -0.103,-6.213 2.918,-8.41m4.12,4.977c-0.014,-0.135 -0.039,-0.269 -0.075,-0.4m-0,0c-0.528,-1.965 -2.354,-5.652 -6.963,-5.908m6.963,5.908c-2.856,2.601 -6.11,3.11 -7.65,2.975m7.65,-2.975c0.752,-0.685 1.702,-2.374 2.36,-3.376m-8.98,2.575c0.687,0.744 3.468,2.369 4.978,2.231m8.755,-2.746c0,6.351 -5.149,11.5 -11.5,11.5c-6.351,0 -11.5,-5.149 -11.5,-11.5c0,-6.351 5.149,-11.5 11.5,-11.5c6.351,0 11.5,5.149 11.5,11.5Z" style="fill:none;fill-rule:nonzero;stroke:#ff496e;stroke-width:2px;"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="21" y1="6" x2="3" y2="6"></line>
<line x1="15" y1="12" x2="3" y2="12"></line>
<line x1="17" y1="18" x2="3" y2="18"></line>
</svg>

After

Width:  |  Height:  |  Size: 329 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="4" width="20" height="5" rx="2"></rect>
<path d="M4 9v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9"></path>
<path d="M10 13h4"></path>
</svg>

After

Width:  |  Height:  |  Size: 336 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 6v12"></path>
<path d="M17.196 9 6.804 15"></path>
<path d="m6.804 9 10.392 6"></path>
</svg>

After

Width:  |  Height:  |  Size: 296 B

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
<path d="M2 8c0-2.2.7-4.3 2-6"></path>
<path d="M22 8a10 10 0 0 0-2-6"></path>
</svg>

After

Width:  |  Height:  |  Size: 384 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path>
</svg>

After

Width:  |  Height:  |  Size: 301 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 325 B

6
src/assets/icons/box.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
<polyline points="3.29 7 12 12 20.71 7"></polyline>
<line x1="12" y1="22" x2="12" y2="12"></line>
</svg>

After

Width:  |  Height:  |  Size: 434 B

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M8 7V3M16 7V3M7 11H17M5 21H19C20.1046 21 21 20.1046 21 19V7C21 5.89543 20.1046 5 19 5H5C3.89543 5 3 5.89543 3 7V19C3 20.1046 3.89543 21 5 21Z"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 349 B

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 3v18h18"></path>
<path d="M18 17V9"></path>
<path d="M13 17V5"></path>
<path d="M8 17v-3"></path>
</svg>

After

Width:  |  Height:  |  Size: 308 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"></path>
<path d="m9 12 2 2 4-4"></path>
</svg>

After

Width:  |  Height:  |  Size: 316 B

View File

@ -0,0 +1,4 @@
<svg fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M20 6L9 17l-5-5" />
</svg>

After

Width:  |  Height:  |  Size: 197 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="15 18 9 12 15 6"></polyline>
</svg>

After

Width:  |  Height:  |  Size: 239 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>

After

Width:  |  Height:  |  Size: 233 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</svg>

After

Width:  |  Height:  |  Size: 324 B

View File

@ -0,0 +1,4 @@
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>

After

Width:  |  Height:  |  Size: 291 B

View File

@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" /></svg>

After

Width:  |  Height:  |  Size: 299 B

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="8" cy="8" r="6"></circle>
<path d="M18.09 10.37A6 6 0 1 1 10.34 18"></path>
<path d="M7 6h1v4"></path>
<path d="m16.71 13.88.7.71-2.82 2.82"></path>
</svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24" xml:space="preserve"><path d="M9 5v4m0 0H5m4 0L4 4m11 1v4m0 0h4m-4 0 5-5M9 19v-4m0 0H5m4 0-5 5m11-5 5 5m-5-5v4m0-4h4" style="fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round"/></svg>

After

Width:  |  Height:  |  Size: 322 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<path d="M15 9.354a4 4 0 1 0 0 5.292"></path>
</svg>

After

Width:  |  Height:  |  Size: 281 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="2" x2="12" y2="22"></line>
<path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
</svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="7" height="9"></rect>
<rect x="14" y="3" width="7" height="5"></rect>
<rect x="14" y="12" width="7" height="9"></rect>
<rect x="3" y="16" width="7" height="5"></rect>
</svg>

After

Width:  |  Height:  |  Size: 390 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
</svg>

After

Width:  |  Height:  |  Size: 260 B

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 9L12 16L5 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 219 B

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M11 5H6C4.89543 5 4 5.89543 4 7V18C4 19.1046 4.89543 20 6 20H17C18.1046 20 19 19.1046 19 18V13M17.5858 3.58579C18.3668 2.80474 19.6332 2.80474 20.4142 3.58579C21.1953 4.36683 21.1953 5.63316 20.4142 6.41421L11.8284 15H9L9 12.1716L17.5858 3.58579Z"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>

After

Width:  |  Height:  |  Size: 454 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>

After

Width:  |  Height:  |  Size: 274 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
</svg>

After

Width:  |  Height:  |  Size: 287 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>

After

Width:  |  Height:  |  Size: 348 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>

After

Width:  |  Height:  |  Size: 417 B

1
src/assets/icons/eye.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>

After

Width:  |  Height:  |  Size: 275 B

Some files were not shown because too many files have changed in this diff Show More