mirror of
https://github.com/LukeHagar/sveltesociety.dev.git
synced 2025-12-10 04:21:49 +00:00
Add component snippet generator (#108)
This commit is contained in:
@@ -12,7 +12,7 @@ import prettier from 'prettier';
|
|||||||
const files = [
|
const files = [
|
||||||
'src/routes/components/components.json',
|
'src/routes/components/components.json',
|
||||||
'src/routes/templates/templates.json',
|
'src/routes/templates/templates.json',
|
||||||
'src/routes/tooling/tools.json'
|
'src/routes/tools/tools.json'
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!process.env.GH_TOKEN) {
|
if (!process.env.GH_TOKEN) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
const linksLeft = [
|
const linksLeft = [
|
||||||
['/templates', 'templates'],
|
['/templates', 'templates'],
|
||||||
['/components', 'components'],
|
['/components', 'components'],
|
||||||
['/tooling', 'tooling']
|
['/tools', 'tools']
|
||||||
];
|
];
|
||||||
const linksRight = [
|
const linksRight = [
|
||||||
['/recipes', 'recipes'],
|
['/recipes', 'recipes'],
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="/help/components" class="submit">Submit a component</a>
|
<a href="/help/submitting?type=component" class="submit">Submit a component</a>
|
||||||
<input
|
<input
|
||||||
class="searchbar"
|
class="searchbar"
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
271
src/routes/help/submitting.svelte
Normal file
271
src/routes/help/submitting.svelte
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
<script>
|
||||||
|
import SvelteSelect from 'svelte-select';
|
||||||
|
import components from '../components/components.json';
|
||||||
|
import templates from '../templates/templates.json';
|
||||||
|
import tools from '../tools/tools.json';
|
||||||
|
import { tick } from 'svelte';
|
||||||
|
import { page } from '$app/stores';
|
||||||
|
import { copyToClipboard } from '$lib/utils/clipboard';
|
||||||
|
import { extractUnique } from '$lib/utils/extractUnique';
|
||||||
|
|
||||||
|
const repoURL = 'https://github.com/svelte-society/sveltesociety.dev';
|
||||||
|
const typeQuery = $page.query.get('type');
|
||||||
|
const types = ['Component', 'Template', 'Tool'].map((t) => ({
|
||||||
|
label: t,
|
||||||
|
value: t.toLowerCase()
|
||||||
|
}));
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
component: {
|
||||||
|
tags: extractUnique(components, 'tags'),
|
||||||
|
categories: [...extractUnique(components, 'category').filter((cat) => cat.label !== '')]
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
tags: extractUnique(templates, 'tags'),
|
||||||
|
categories: extractUnique(templates, 'category')
|
||||||
|
},
|
||||||
|
tool: {
|
||||||
|
tags: extractUnique(tools, 'tags'),
|
||||||
|
categories: extractUnique(tools, 'category')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let clipboardCopy = false;
|
||||||
|
const copy = () => {
|
||||||
|
copyToClipboard(JSON.stringify(jsonSnippet, null, 4)).then(() => (clipboardCopy = false));
|
||||||
|
clipboardCopy = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
let type = types.find((t) => t.value == typeQuery) || types[0];
|
||||||
|
let title = 'svelte-lorem-ipsum';
|
||||||
|
let url = 'https://github.com/sveltejs/svelte-lorem-ipsum';
|
||||||
|
let description = 'A dummy text generator that does not exist';
|
||||||
|
let npm = 'svelte-lorem-ipsum';
|
||||||
|
let addedOn = todaysDate();
|
||||||
|
let category;
|
||||||
|
let tags;
|
||||||
|
|
||||||
|
$: pathName = `${type.value}s`;
|
||||||
|
$: jsonSnippet = {
|
||||||
|
title,
|
||||||
|
url,
|
||||||
|
description,
|
||||||
|
npm,
|
||||||
|
addedOn,
|
||||||
|
category: category?.value,
|
||||||
|
tags: tags?.map((tag) => tag.value)
|
||||||
|
};
|
||||||
|
|
||||||
|
$: currentTags = data[type.value].tags;
|
||||||
|
$: currentCategories = data[type.value].categories;
|
||||||
|
|
||||||
|
function padWithZero(date) {
|
||||||
|
return date.toString().padStart(2, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
function todaysDate() {
|
||||||
|
const date = new Date();
|
||||||
|
const day = padWithZero(date.getDate());
|
||||||
|
const month = padWithZero(date.getMonth() + 1);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const sep = '-';
|
||||||
|
return [year, month, day].join(sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function clearCategoryAndTags() {
|
||||||
|
await tick();
|
||||||
|
category = null;
|
||||||
|
tags = null;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>Submitting a new component</h1>
|
||||||
|
<p>
|
||||||
|
To add a new component on the website, the process is rather simple. You have to add a snippet in
|
||||||
|
the appropriate file.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Generating file contents snippet</h2>
|
||||||
|
<p>
|
||||||
|
Each component is represented by a JSON Object. Use the generator below to generate the Object.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><code>*</code> marked fields are required</p>
|
||||||
|
<div class="json-generator">
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="type">Type:</label>
|
||||||
|
<div>
|
||||||
|
<SvelteSelect
|
||||||
|
id="type"
|
||||||
|
items={types}
|
||||||
|
isClearable={false}
|
||||||
|
showIndicator
|
||||||
|
bind:value={type}
|
||||||
|
on:select={clearCategoryAndTags}
|
||||||
|
/>
|
||||||
|
<span class="input-helper">The type of snippet to generate</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="title" class="required">Title:</label>
|
||||||
|
<div>
|
||||||
|
<input id="title" type="text" required bind:value={title} />
|
||||||
|
<span class="input-helper">Name of the component</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="url">URL:</label>
|
||||||
|
<div>
|
||||||
|
<input id="url" type="url" bind:value={url} />
|
||||||
|
<span class="input-helper">The URL where to find it</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="desc">Description:</label>
|
||||||
|
<div>
|
||||||
|
<input id="desc" type="text" bind:value={description} />
|
||||||
|
<span class="input-helper">A short description of the component</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="npm">NPM:</label>
|
||||||
|
<div>
|
||||||
|
<input id="npm" type="text" bind:value={npm} />
|
||||||
|
<span class="input-helper">The npm name of the component</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="adden-on" class="required">Added On:</label>
|
||||||
|
<div>
|
||||||
|
<input id="adden-on" type="date" required bind:value={addedOn} />
|
||||||
|
<span class="input-helper">
|
||||||
|
The date when the component have been added on the website (generally it’s today)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="category">Category:</label>
|
||||||
|
<div>
|
||||||
|
<SvelteSelect
|
||||||
|
id="category"
|
||||||
|
items={currentCategories}
|
||||||
|
isClearable={false}
|
||||||
|
showIndicator
|
||||||
|
bind:value={category}
|
||||||
|
/>
|
||||||
|
<span class="input-helper">The category of the component</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<label for="tags" class="required">Tags:</label>
|
||||||
|
<div>
|
||||||
|
<SvelteSelect id="category" items={currentTags} showIndicator isMulti bind:value={tags} />
|
||||||
|
<span class="input-helper">A list of tags</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>JSON Snippet</h2>
|
||||||
|
<pre>
|
||||||
|
{JSON.stringify(jsonSnippet,null,4)}<button on:click={copy}>{clipboardCopy ? 'Copied' : 'Copy'}</button>
|
||||||
|
</pre>
|
||||||
|
<br />
|
||||||
|
Copy this snippet and add it to
|
||||||
|
<a href="{repoURL}/blob/staging/src/routes/{pathName}/{pathName}.json">{pathName}.json</a>. You can
|
||||||
|
propose your changes
|
||||||
|
<a href="{repoURL}/edit/staging/src/routes/{pathName}/{pathName}.json">directly in GitHub</a>.
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.json-generator,
|
||||||
|
pre {
|
||||||
|
max-width: var(--s-max);
|
||||||
|
padding: var(--s-4);
|
||||||
|
border-radius: 14px;
|
||||||
|
background-color: #f3f6f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-generator {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: var(--s-4) var(--s-20);
|
||||||
|
padding-block: var(--s-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-wrapper {
|
||||||
|
--borderRadius: 5px;
|
||||||
|
--border: 2px solid var(--dark-gray);
|
||||||
|
--borderFocusColor: var(--secondary);
|
||||||
|
--borderHoverColor: var(--secondary);
|
||||||
|
--itemIsActiveBG: var(--secondary);
|
||||||
|
--multiItemActiveBG: var(--secondary);
|
||||||
|
--indicatorColor: var(--dark-gray);
|
||||||
|
--indicatorTop: calc(50% - 13px);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
gap: var(--s-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-wrapper label {
|
||||||
|
min-width: 10ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-wrapper > div {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: var(--s-1);
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--s-2) 16px;
|
||||||
|
border: var(--border);
|
||||||
|
border-radius: var(--borderRadius);
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:hover,
|
||||||
|
input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--borderFocusColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-helper {
|
||||||
|
color: var(--dark-gray);
|
||||||
|
font-size: var(--font-100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.required::after {
|
||||||
|
content: '*';
|
||||||
|
color: var(--error);
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre button {
|
||||||
|
position: absolute;
|
||||||
|
top: var(--s-4);
|
||||||
|
right: var(--s-4);
|
||||||
|
padding: var(--s-1);
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: var(--white);
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 700px) {
|
||||||
|
.json-generator {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 450px) {
|
||||||
|
.input-wrapper {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--s-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
let filterTag = [];
|
let filterTag = [];
|
||||||
let selectedTags = null;
|
let selectedTags = null;
|
||||||
|
|
||||||
const categoryItems = [{ label: 'all', value: null }, ...extractUnique(components, 'category')];
|
const categoryItems = [{ label: 'All', value: null }, ...extractUnique(components, 'category')];
|
||||||
let selectedCategory = null;
|
let selectedCategory = null;
|
||||||
let filterCategory = null;
|
let filterCategory = null;
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
isClearable={false}
|
isClearable={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<a href="/help/components" class="submit">Submit a template</a>
|
<a href="/help/submitting?type=template" class="submit">Submit a template</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
let filterTag = [];
|
let filterTag = [];
|
||||||
let selectedTags = null;
|
let selectedTags = null;
|
||||||
|
|
||||||
const categoryItems = [{ label: 'all', value: null }, ...extractUnique(components, 'category')];
|
const categoryItems = [{ label: 'All', value: null }, ...extractUnique(components, 'category')];
|
||||||
let selectedCategory = null;
|
let selectedCategory = null;
|
||||||
let filterCategory = null;
|
let filterCategory = null;
|
||||||
|
|
||||||
@@ -50,10 +50,10 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Tooling - Svelte Society</title>
|
<title>Tools - Svelte Society</title>
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<SearchLayout title="Tooling">
|
<SearchLayout title="Tools">
|
||||||
<section slot="controls" class="controls">
|
<section slot="controls" class="controls">
|
||||||
<div class="inputs">
|
<div class="inputs">
|
||||||
<Select bind:value={selectedTags} items={tagItems} isMulti label="Tags" />
|
<Select bind:value={selectedTags} items={tagItems} isMulti label="Tags" />
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
showIndicator
|
showIndicator
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
/>
|
/>
|
||||||
<a href="/help/components" class="submit">Submit a tool</a>
|
<a href="/help/submitting?type=tool" class="submit">Submit a tool</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
Reference in New Issue
Block a user