Add prism and skeleton www page (#49)
* Add prism and skeleton www page This adds a Prism plugin, a Prism component, and the skeleton of our www site (just for testing the Prism component at the moment). * Remove debugging
This commit is contained in:
parent
c26c244ca2
commit
397b7145cc
12 changed files with 4518 additions and 0 deletions
16
prism-astro/Prism.astro
Normal file
16
prism-astro/Prism.astro
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
import Prism from 'prismjs';
|
||||||
|
import { addAstro } from './index.mjs';
|
||||||
|
|
||||||
|
addAstro(Prism);
|
||||||
|
|
||||||
|
export let lang;
|
||||||
|
export let code;
|
||||||
|
|
||||||
|
const grammar = Prism.languages[lang];
|
||||||
|
let html = Prism.highlight(code, grammar, lang);
|
||||||
|
|
||||||
|
let className = `language-${lang}`;
|
||||||
|
---
|
||||||
|
|
||||||
|
<pre class={className}><code class={className}>{html}</code></pre>
|
165
prism-astro/index.mjs
Normal file
165
prism-astro/index.mjs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
|
||||||
|
export function addAstro(Prism) {
|
||||||
|
if(Prism.languages.astro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let scriptLang;
|
||||||
|
if(Prism.languages.typescript) {
|
||||||
|
scriptLang = 'typescript';
|
||||||
|
} else {
|
||||||
|
scriptLang = 'javascript';
|
||||||
|
console.warn('Prism TypeScript language not loading, Astro scripts will be treated as JavaScript.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let script = Prism.util.clone(Prism.languages[scriptLang]);
|
||||||
|
|
||||||
|
let space = /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source;
|
||||||
|
let braces = /(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source;
|
||||||
|
let spread = /(?:\{<S>*\.{3}(?:[^{}]|<BRACES>)*\})/.source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} source
|
||||||
|
* @param {string} [flags]
|
||||||
|
*/
|
||||||
|
function re(source, flags) {
|
||||||
|
source = source
|
||||||
|
.replace(/<S>/g, function () { return space; })
|
||||||
|
.replace(/<BRACES>/g, function () { return braces; })
|
||||||
|
.replace(/<SPREAD>/g, function () { return spread; });
|
||||||
|
return RegExp(source, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
spread = re(spread).source;
|
||||||
|
|
||||||
|
|
||||||
|
Prism.languages.astro = Prism.languages.extend('markup', script);
|
||||||
|
Prism.languages.astro.tag.pattern = re(
|
||||||
|
/<\/?(?:[\w.:-]+(?:<S>+(?:[\w.:$-]+(?:=(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s{'"/>=]+|<BRACES>))?|<SPREAD>))*<S>*\/?)?>/.source
|
||||||
|
);
|
||||||
|
|
||||||
|
Prism.languages.astro.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i;
|
||||||
|
Prism.languages.astro.tag.inside['attr-value'].pattern = /=(?!\{)(?:"(?:\\[^]|[^\\"])*"|'(?:\\[^]|[^\\'])*'|[^\s'">]+)/i;
|
||||||
|
Prism.languages.astro.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/;
|
||||||
|
Prism.languages.astro.tag.inside['comment'] = script['comment'];
|
||||||
|
|
||||||
|
Prism.languages.insertBefore('inside', 'attr-name', {
|
||||||
|
'spread': {
|
||||||
|
pattern: re(/<SPREAD>/.source),
|
||||||
|
inside: Prism.languages.astro
|
||||||
|
}
|
||||||
|
}, Prism.languages.astro.tag);
|
||||||
|
|
||||||
|
Prism.languages.insertBefore('inside', 'special-attr', {
|
||||||
|
'script': {
|
||||||
|
// Allow for two levels of nesting
|
||||||
|
pattern: re(/=<BRACES>/.source),
|
||||||
|
inside: {
|
||||||
|
'script-punctuation': {
|
||||||
|
pattern: /^=(?={)/,
|
||||||
|
alias: 'punctuation'
|
||||||
|
},
|
||||||
|
rest: Prism.languages.astro
|
||||||
|
},
|
||||||
|
'alias': `language-${scriptLang}`
|
||||||
|
}
|
||||||
|
}, Prism.languages.astro.tag);
|
||||||
|
|
||||||
|
|
||||||
|
// The following will handle plain text inside tags
|
||||||
|
let stringifyToken = function (token) {
|
||||||
|
if (!token) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (typeof token === 'string') {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
if (typeof token.content === 'string') {
|
||||||
|
return token.content;
|
||||||
|
}
|
||||||
|
return token.content.map(stringifyToken).join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
let walkTokens = function (tokens) {
|
||||||
|
let openedTags = [];
|
||||||
|
for (let i = 0; i < tokens.length; i++) {
|
||||||
|
let token = tokens[i];
|
||||||
|
|
||||||
|
// This breaks styles, not sure why
|
||||||
|
if(token.type === 'style') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let notTagNorBrace = false;
|
||||||
|
|
||||||
|
if (typeof token !== 'string') {
|
||||||
|
if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') {
|
||||||
|
// We found a tag, now find its kind
|
||||||
|
|
||||||
|
if (token.content[0].content[0].content === '</') {
|
||||||
|
// Closing tag
|
||||||
|
if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) {
|
||||||
|
// Pop matching opening tag
|
||||||
|
openedTags.pop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (token.content[token.content.length - 1].content === '/>') {
|
||||||
|
// Autoclosed tag, ignore
|
||||||
|
} else {
|
||||||
|
// Opening tag
|
||||||
|
openedTags.push({
|
||||||
|
tagName: stringifyToken(token.content[0].content[1]),
|
||||||
|
openedBraces: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') {
|
||||||
|
|
||||||
|
// Here we might have entered a Astro context inside a tag
|
||||||
|
openedTags[openedTags.length - 1].openedBraces++;
|
||||||
|
|
||||||
|
} else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') {
|
||||||
|
|
||||||
|
// Here we might have left a Astro context inside a tag
|
||||||
|
openedTags[openedTags.length - 1].openedBraces--;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
notTagNorBrace = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (notTagNorBrace || typeof token === 'string') {
|
||||||
|
if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) {
|
||||||
|
// Here we are inside a tag, and not inside a Astro context.
|
||||||
|
// That's plain text: drop any tokens matched.
|
||||||
|
let plainText = stringifyToken(token);
|
||||||
|
|
||||||
|
// And merge text with adjacent text
|
||||||
|
if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) {
|
||||||
|
plainText += stringifyToken(tokens[i + 1]);
|
||||||
|
tokens.splice(i + 1, 1);
|
||||||
|
}
|
||||||
|
if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) {
|
||||||
|
plainText = stringifyToken(tokens[i - 1]) + plainText;
|
||||||
|
tokens.splice(i - 1, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens[i] = new Prism.Token('plain-text', plainText, null, plainText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.content && typeof token.content !== 'string') {
|
||||||
|
walkTokens(token.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Prism.hooks.add('after-tokenize', function (env) {
|
||||||
|
if (env.language !== 'astro') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walkTokens(env.tokens);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
60
prism-astro/package-lock.json
generated
Normal file
60
prism-astro/package-lock.json
generated
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"name": "prism-astro",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"clipboard": {
|
||||||
|
"version": "2.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
|
||||||
|
"integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"good-listener": "^1.2.2",
|
||||||
|
"select": "^1.1.2",
|
||||||
|
"tiny-emitter": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delegate": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"good-listener": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
|
||||||
|
"integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"delegate": "^3.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prismjs": {
|
||||||
|
"version": "1.23.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz",
|
||||||
|
"integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"clipboard": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"select": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"tiny-emitter": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
prism-astro/package.json
Normal file
19
prism-astro/package.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "prism-astro",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.mjs",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": "./index.mjs",
|
||||||
|
"./Prism.astro": "./Prism.astro"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"prismjs": "^1.23.0"
|
||||||
|
}
|
||||||
|
}
|
115
prism-astro/test/demo.html
Normal file
115
prism-astro/test/demo.html
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<title>prism-astro demo</title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.skypack.dev/prismjs/themes/prism-tomorrow.css">
|
||||||
|
|
||||||
|
<pre class="language-astro"><code class="language-astro">---
|
||||||
|
import Card from '../components/Card.jsx';
|
||||||
|
import PokemonLookup from '../components/PokemonLookup.astro';
|
||||||
|
import CompanyLogo from '../components/CompanyLogo.jsx';
|
||||||
|
import NewsAssets from '../components/NewsAssets.svelte';
|
||||||
|
import NewsTitle from '../components/NewsTitle.vue';
|
||||||
|
import BaseHead from '../components/BaseHead.astro';
|
||||||
|
import MainLayout from '../components/MainLayout.astro';
|
||||||
|
|
||||||
|
// Using Snowpack? Want to be featured on snowpack.dev?
|
||||||
|
// Add your project, organization, or company to the end of this list!
|
||||||
|
import news from '../data/news.json';
|
||||||
|
import users from '../data/users.json';
|
||||||
|
|
||||||
|
const title: string = 'Community & News';
|
||||||
|
const description = 'Snowpack community news and companies that use Snowpack.';
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<BaseHead title={title} description={description} permalink="TODO" />
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.intro {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #2e5e82;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<MainLayout>
|
||||||
|
<NewsTitle title={title} />
|
||||||
|
<p>
|
||||||
|
Get the latest news, blog posts, and tutorials on Snowpack. <a href="/feed.xml">Also available via RSS.</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Got something that you think we should feature?
|
||||||
|
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_data/news.js">Submit it!</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<PokemonLookup number={1} />
|
||||||
|
<PokemonLookup number={2} />
|
||||||
|
<PokemonLookup number={3} />
|
||||||
|
|
||||||
|
<div class="card-grid card-grid-3">
|
||||||
|
<article class="discord-banner">
|
||||||
|
<a href="https://discord.gg/snowpack" style="flex-shrink: 0; height: 48px;"><img alt="Join us on Discord!"
|
||||||
|
src="https://img.shields.io/discord/712696926406967308.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2"
|
||||||
|
style="height: 48px; border: none; margin-right: 1rem; filter: brightness(1.2) contrast(1.5);" /></a>
|
||||||
|
<div>Join us on Discord to discuss Snowpack, meet other developers in our community, and show off what you’re
|
||||||
|
working on!</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
{news.reverse().map((item: any) => <Card:idle item={item} />)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<h3>Who's Using Snowpack?</h3>
|
||||||
|
|
||||||
|
<div class="company-logos">
|
||||||
|
|
||||||
|
{users.map((user) =>
|
||||||
|
<CompanyLogo user={user} />)}
|
||||||
|
|
||||||
|
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_template/news.md" target="_blank"
|
||||||
|
title="Add Your Project/Company!" class="add-company-button">
|
||||||
|
<svg style="height: 22px; margin-right: 8px;" aria-hidden="true" focusable="false" data-prefix="fas"
|
||||||
|
data-icon="plus" class="company-logo" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
||||||
|
<path fill="currentColor"
|
||||||
|
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
Add your logo
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<NewsAssets />
|
||||||
|
</div>
|
||||||
|
</MainLayout>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html></code></pre>
|
||||||
|
<script type="module">
|
||||||
|
import Prism from 'https://cdn.skypack.dev/prismjs';
|
||||||
|
import { addAstro } from '../index.mjs';
|
||||||
|
Prism.manual = true;
|
||||||
|
|
||||||
|
async function go() {
|
||||||
|
await import('https://cdn.skypack.dev/prismjs/components/prism-typescript.js');
|
||||||
|
|
||||||
|
addAstro(Prism);
|
||||||
|
|
||||||
|
for(const el of document.querySelectorAll('code')) {
|
||||||
|
Prism.highlightElement(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go();
|
||||||
|
</script>
|
5
www/astro.config.mjs
Normal file
5
www/astro.config.mjs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export default {
|
||||||
|
projectRoot: '.',
|
||||||
|
astroRoot: './astro',
|
||||||
|
dist: './_site',
|
||||||
|
};
|
19
www/astro/layouts/index.astro
Normal file
19
www/astro/layouts/index.astro
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
import 'prismjs/themes/prism-tomorrow.css';
|
||||||
|
|
||||||
|
export let content: any;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>{content.title}</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>{content.title}</h1>
|
||||||
|
|
||||||
|
<main><slot></slot></main>
|
||||||
|
</body>
|
||||||
|
</html>
|
21
www/astro/pages/blog.md
Normal file
21
www/astro/pages/blog.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
layout: ../layouts/index.astro
|
||||||
|
title: Astro
|
||||||
|
import:
|
||||||
|
Prism: prism-astro/Prism.astro
|
||||||
|
---
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* Link one
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```astro
|
||||||
|
<html>
|
||||||
|
<title>Testing</title>
|
||||||
|
<body>
|
||||||
|
<h1>Hello world</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
28
www/astro/pages/index.astro
Normal file
28
www/astro/pages/index.astro
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
import Prism from 'prism-astro/Prism.astro';
|
||||||
|
import 'prismjs/themes/prism-tomorrow.css';
|
||||||
|
|
||||||
|
let title = 'Astro Build';
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
|
||||||
|
<Prism lang="astro" code={`---
|
||||||
|
let title = 'My Site';
|
||||||
|
---
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{title}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</body>
|
||||||
|
</html>`} />
|
||||||
|
</body>
|
||||||
|
</html>
|
4048
www/package-lock.json
generated
Normal file
4048
www/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
18
www/package.json
Normal file
18
www/package.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "www",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "astro dev .",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"astro": "file:../",
|
||||||
|
"prism-astro": "file:../prism-astro/",
|
||||||
|
"prismjs": "^1.23.0"
|
||||||
|
}
|
||||||
|
}
|
4
www/snowpack.config.js
Normal file
4
www/snowpack.config.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
workspaceRoot: '../'
|
||||||
|
};
|
Loading…
Reference in a new issue