forked from didirus/AstralRinth
Update utilities and documentation
This commit is contained in:
@@ -1,35 +1,38 @@
|
||||
<script lang="ts">
|
||||
import { Button } from 'omorphia'
|
||||
import IconMoon from 'virtual:icons/heroicons-outline/moon'
|
||||
import IconSun from 'virtual:icons/heroicons-outline/sun'
|
||||
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 };
|
||||
|
||||
let theme = 'light'
|
||||
let background = meta.raised ? 'var(--color-raised-bg)' : 'var(--color-bg)'
|
||||
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" style:background={background}>
|
||||
<slot name="example"/>
|
||||
<div class="example__preview theme-{theme} base" 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'}>
|
||||
<Button
|
||||
color="primary-light"
|
||||
on:click={() => (theme === 'light' ? (theme = 'dark') : (theme = 'light'))}
|
||||
>
|
||||
{#if theme === 'light'}
|
||||
<IconMoon/>
|
||||
<IconMoon />
|
||||
{:else}
|
||||
<IconSun/>
|
||||
<IconSun />
|
||||
{/if}
|
||||
</Button>
|
||||
</div>
|
||||
<pre class="example__source__code language-svelte"><slot name="code"/></pre>
|
||||
<pre class="example__source__code language-svelte"><slot name="code" /></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
.example {
|
||||
margin-bottom: 32px;
|
||||
margin: 15px 0 32px;
|
||||
|
||||
&__preview {
|
||||
border-radius: var(--rounded-sm-top);
|
||||
|
||||
@@ -1,157 +1,162 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/stores';
|
||||
|
||||
import IconMenu from 'virtual:icons/lucide/menu';
|
||||
import IconMenu from 'virtual:icons/lucide/menu';
|
||||
|
||||
const components = Object.keys(import.meta.glob('../../components/**'))
|
||||
.map((it) => it.replace('../../components/', '').replace('.md', ''))
|
||||
.sort();
|
||||
const components = Object.keys(import.meta.glob('../../components/**'))
|
||||
.map((it) => it.replace('../../components/', '').replace('.md', ''))
|
||||
.sort();
|
||||
|
||||
const classes = Object.keys(import.meta.glob('../../classes/**'))
|
||||
.map((it) => it.replace('../../classes/', '').replace('.md', ''))
|
||||
.sort();
|
||||
const classes = Object.keys(import.meta.glob('../../classes/**'))
|
||||
.map((it) => it.replace('../../classes/', '').replace('.md', ''))
|
||||
.sort();
|
||||
|
||||
let slideIn = false;
|
||||
let slideIn = false;
|
||||
|
||||
$: if ($page.url.pathname) {
|
||||
slideIn = false;
|
||||
}
|
||||
$: if ($page.url.pathname) {
|
||||
slideIn = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav class="sidebar" class:slideIn>
|
||||
<div class="sidebar__content">
|
||||
<div class="section">
|
||||
<span class="section__title">Getting started</span>
|
||||
<a href="/" class="section__link">Introduction</a>
|
||||
<a href="/getting-started/configure" class="section__link">Configure</a>
|
||||
<a href="/getting-started/icons" class="section__link">Using Icons</a>
|
||||
<a href="/getting-started/css" class="section__link">Writing CSS</a>
|
||||
<a href="/getting-started/illustrations" class="section__link">Illustrations</a>
|
||||
<a href="/getting-started/utils" class="section__link">Built-in utilities</a>
|
||||
<a href="/getting-started/generator" class="section__link">Generator plugin</a>
|
||||
<div class="sidebar__content">
|
||||
<div class="section">
|
||||
<span class="section__title">Getting started</span>
|
||||
<a href="/" class="section__link">Introduction</a>
|
||||
<a href="/getting-started/configure" class="section__link">Configure</a>
|
||||
<a href="/getting-started/icons" class="section__link">Using Icons</a>
|
||||
<!-- <a href="/getting-started/css" class="section__link">Writing CSS</a> -->
|
||||
<a href="/getting-started/illustrations" class="section__link">Illustrations</a>
|
||||
<a href="/getting-started/utils" class="section__link">Built-in utilities</a>
|
||||
<a href="/getting-started/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>
|
||||
|
||||
<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>
|
||||
<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;
|
||||
: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%);
|
||||
}
|
||||
|
||||
&__content {
|
||||
mask-image: linear-gradient(to bottom, transparent, hsla(0, 0%, 0%, 1) 5% 95%, transparent);
|
||||
padding: 88px 32px 32px;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
grid-gap: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.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);
|
||||
|
||||
.section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-gap: 0.5rem;
|
||||
|
||||
&__title {
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
@media (--md) {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&__link {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
&__content {
|
||||
mask-image: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
hsla(0, 0%, 0%, 1) 5% 95%,
|
||||
transparent
|
||||
);
|
||||
padding: 88px 32px 32px;
|
||||
height: 100vh;
|
||||
max-height: 100vh;
|
||||
overflow-y: auto;
|
||||
grid-gap: 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&:hover {
|
||||
.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: 16px;
|
||||
bottom: 16px;
|
||||
padding: 8px;
|
||||
aspect-ratio: 1 / 1;
|
||||
background-color: var(--accent-color);
|
||||
z-index: 20;
|
||||
border-radius: var(--rounded);
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
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: 32px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media (--md) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.slideIn {
|
||||
left: 0;
|
||||
|
||||
.sidebar__toggle {
|
||||
left: calc(32px + min(70vw, var(--sidebar-width)));
|
||||
}
|
||||
}
|
||||
|
||||
scrollbar-color: var(--scrollbar-thumb-color) var(--sidebar-color);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: var(--sidebar-color);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb-color);
|
||||
border-radius: 999px;
|
||||
border: 3px solid var(--sidebar-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
position: fixed;
|
||||
left: 16px;
|
||||
bottom: 16px;
|
||||
padding: 8px;
|
||||
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: 32px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media (--md) {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.slideIn {
|
||||
left: 0;
|
||||
|
||||
.sidebar__toggle {
|
||||
left: calc(32px + min(70vw, var(--sidebar-width)));
|
||||
}
|
||||
}
|
||||
|
||||
scrollbar-color: var(--scrollbar-thumb-color) var(--sidebar-color);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: var(--sidebar-color);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb-color);
|
||||
border-radius: 999px;
|
||||
border: 3px solid var(--sidebar-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
&:where(h1, h2, h3, h4, h5, h6) {
|
||||
margin: 20px 0 10px;
|
||||
margin: 30px 0 10px;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
@@ -76,6 +76,8 @@
|
||||
font-size: 24px;
|
||||
/*border-bottom: 1px solid #cccccc;*/
|
||||
color: black;
|
||||
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
&:where(h3) {
|
||||
|
||||
@@ -2,25 +2,82 @@
|
||||
title: Built-in utilities
|
||||
---
|
||||
|
||||
TODO
|
||||
## Markdown
|
||||
|
||||
## ... ago
|
||||
Use the markdown utilities to parse markdown text into HTML. Both markdown parsers have HTML sanitization built-in.
|
||||
|
||||
## Simplify number
|
||||
### Body parser
|
||||
|
||||
## Markdown & XSS
|
||||
The `markdown` parser is designed for bodies of markdown text and supports images, tables, lists, and youtube `<iframe>`s.
|
||||
|
||||
### Parsers
|
||||
> Use the `.markdown` class on the element containing your parsed markdown.
|
||||
|
||||
- sanitize
|
||||
- markdown
|
||||
- markdownInline
|
||||
- markdownXSS
|
||||
```svelte example
|
||||
<script lang="ts">
|
||||
import { markdown } from "omorphia"
|
||||
|
||||
### Markdown
|
||||
const source = '## Example markdown \n\
|
||||
This is **some** *text*! \n\
|
||||
#### An image \n\
|
||||
<img src="https://cdn.modrinth.com/data/YL57xq9U/images/d382106b9a2b943d06107c31c139c77849f1a0e8.png" />'
|
||||
</script>
|
||||
|
||||
Put parsed HTML into a `<div>` with `class="markdown"`.
|
||||
<div class="card markdown">
|
||||
{@html markdown(source)}
|
||||
</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"
|
||||
|
||||
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';
|
||||
</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.
|
||||
|
||||
```ts
|
||||
import { Permissions } from 'omorphia';
|
||||
|
||||
const adminLevel = new Permissions('ALL');
|
||||
const memberLevel = new Permissions(member.permissions); /* `member` from API */
|
||||
const userLevel = new Permissions(0);
|
||||
|
||||
if (memberLevel.data.uploadVersions) {
|
||||
console.log('Can upload versions!');
|
||||
}
|
||||
```
|
||||
|
||||
## 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';
|
||||
</script>
|
||||
|
||||
<p>{formatVersions(["1.18", "1.18.1", "1.18.2", "1.17.1"])}</p>
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user