Skip to content

Commit

Permalink
Merge pull request #60 from appwrite/feat-code-example
Browse files Browse the repository at this point in the history
feat: code example and json view
  • Loading branch information
TorstenDittmann authored Oct 10, 2022
2 parents 31c61a8 + 1f68b1e commit c7f4d2b
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 1 deletion.
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check": "svelte-check --tsconfig ./tsconfig.json --fail-on-warnings --threshold warning",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint .",
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. .",
Expand All @@ -22,6 +22,7 @@
"@aw-labs/icons": "0.0.0-58",
"@aw-labs/ui": "0.0.0-58",
"echarts": "^5.4.0",
"prismjs": "^1.29.0",
"tippy.js": "^6.3.7",
"web-vitals": "^2.1.4"
},
Expand All @@ -34,6 +35,7 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/svelte": "3.1.3",
"@testing-library/user-event": "^14.4.3",
"@types/prismjs": "^1.26.0",
"@types/gtag.js": "^0.0.12",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
Expand Down
159 changes: 159 additions & 0 deletions src/lib/components/code.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<script lang="ts">
import { Pill } from '$lib/elements';
import Prism from 'prismjs';
import 'prismjs/components/prism-dart';
import 'prismjs/components/prism-kotlin';
import 'prismjs/components/prism-json';
import 'prismjs/plugins/autoloader/prism-autoloader';
import 'prismjs/plugins/line-numbers/prism-line-numbers';
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import { afterUpdate } from 'svelte';
import { Copy } from '.';
export let label: string = null;
export let code: string;
export let language: 'js' | 'html' | 'dart' | 'kotlin' | 'json';
export let showLineNumbers = false;
export let showCopy = false;
afterUpdate(async () => {
Prism.highlightAll();
});
</script>

<div class="code">
<div class="controls">
{#if label}
<Pill>{label}</Pill>
{/if}
{#if showCopy}
<Copy value={code}>
<span class="icon-duplicate" aria-hidden="true" style="cursor: pointer;" />
</Copy>
{/if}
</div>
<pre class={`language-${language}`} class:line-numbers={showLineNumbers}><code
>{code}</code></pre>
</div>

<style lang="scss" global>
@import 'prismjs/themes/prism.css';
div.code {
position: relative;
div.controls {
position: absolute;
right: 0.5rem;
top: 0.5rem;
z-index: 1;
}
}
code,
pre {
&[class*='language-'] {
color: #fcfcff;
text-shadow: none;
font-family: 'Source Code Pro';
body.theme-light & {
color: #373b4d;
}
}
::selection,
&::selection {
text-shadow: none;
background: #b3d4fc;
}
&.line-numbers .line-numbers-rows {
border: none;
> span::before {
color: #868ea3;
}
}
}
:not(pre) > code[class*='language-'],
pre[class*='language-'] {
background: #1b1b28;
body.theme-light & {
background: #fcfcff;
}
}
.token {
&.comment,
&.prolog,
&.doctype,
&.cdata {
color: #868ea3;
}
&.punctuation {
color: #fcfcff;
body.theme-light & {
color: #373b4d;
}
}
&.property,
&.tag,
&.boolean,
&.number,
&.constant,
&.symbol,
&.deleted,
&.selector,
&.attr-name,
&.string,
&.char,
&.builtin,
&.inserted {
color: #fdc584;
body.theme-light & {
color: #e49545;
}
}
&.operator,
&.entity,
&.url,
.language-css &.string,
.style &.string {
color: #fcfcff;
background: none;
body.theme-light & {
color: #373b4d;
}
}
&.atrule,
&.attr-value,
&.keyword {
color: #cbb1fc;
body.theme-light & {
color: #6a6af7;
}
}
&.function {
color: #ffa1ce;
body.theme-light & {
color: #f02e7f;
}
}
&.class-name {
color: #a1c4ff;
body.theme-light & {
color: #62aed2;
}
}
&.regex,
&.important,
&.variable {
color: #a1c4ff;
body.theme-light & {
color: #62aed2;
}
}
}
</style>
2 changes: 2 additions & 0 deletions src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,7 @@ export { default as Search } from './search.svelte';
export { default as GridItem1 } from './gridItem1.svelte';
export { default as Steps } from './steps.svelte';
export { default as Step } from './step.svelte';
export { default as Code } from './code.svelte';
export { default as Json } from './json.svelte';
export { default as CustomId } from './customId.svelte';
export { default as Secret } from './secret.svelte';
7 changes: 7 additions & 0 deletions src/lib/components/json.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script lang="ts">
import Code from './code.svelte';
export let code: string;
</script>

<Code showLineNumbers showCopy language="json" {code} />
77 changes: 77 additions & 0 deletions tests/unit/components/code.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import '@testing-library/jest-dom';
import { fireEvent, render } from '@testing-library/svelte';
import { vi } from 'vitest';
import { Code } from '../../../src/lib/components';

test('default props', async () => {
const { container } = render(Code, {
code: 'console.log("test");',
language: 'js'
});

expect(container.querySelector('.controls').children.length).toEqual(0);
});

test('shows label', async () => {
const { container } = render(Code, {
code: 'console.log("test");',
language: 'js',
label: 'My Label'
});

expect(container).toContainHTML('My Label');
});

test('shows line numbers', async () => {
const { container } = render(Code, {
code: 'a\nb;\nc;',
language: 'js',
showLineNumbers: true
});

expect(container.querySelectorAll('.line-numbers').length).toEqual(1);
expect(container.querySelectorAll('.line-numbers-rows').length).toEqual(1);
});

test('shows code highlighted javascript', async () => {
const { container } = render(Code, {
code: 'console.log("test");',
language: 'js'
});

expect(container.querySelectorAll('.token.function').length).toEqual(1);
expect(container.querySelectorAll('.token.string').length).toEqual(1);
expect(container.querySelectorAll('.token.punctuation').length).toEqual(4);
});

test('shows code highlighted json', async () => {
const { container } = render(Code, {
code: JSON.stringify({ key: 'value' }),
language: 'json'
});

expect(container.querySelectorAll('.token.property').length).toEqual(1);
expect(container.querySelectorAll('.token.operator').length).toEqual(1);
expect(container.querySelectorAll('.token.string').length).toEqual(1);
expect(container.querySelectorAll('.token.punctuation').length).toEqual(2);
});

test('copy to clipboard function called on click', async () => {
const { container } = render(Code, {
code: 'console.log("test");',
language: 'js',
showCopy: true
});

Object.assign(window.navigator, {
clipboard: {
writeText: vi.fn().mockImplementation(() => Promise.resolve())
}
});

const button = container.querySelector('.icon-duplicate');

await fireEvent.click(button);

expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith('console.log("test");');
});

1 comment on commit c7f4d2b

@vercel
Copy link

@vercel vercel bot commented on c7f4d2b Oct 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.