Browse Source

Implements the Source component for loading JavaScript remotely and CodeFormatter for applying Rainbow code formatting to code.

master
Zed A. Shaw 1 week ago
parent
commit
e811b67a75
  1. 3
      client/bando/Components.svelte
  2. 9
      client/bando/demos/Code.svelte
  3. 8
      client/bando/demos/Code.svelte.md
  4. 17
      client/components/BTCPay.svelte
  5. 19
      client/components/Code.svelte
  6. 14
      client/components/CodeFormatter.svelte
  7. 6
      client/components/Paypal.svelte
  8. 37
      client/components/Source.svelte
  9. 3
      client/components/WTVideo.svelte
  10. 9
      client/lib/helpers.js
  11. 13
      static/global.css

3
client/bando/Components.svelte

@ -37,6 +37,7 @@
import Video from "./demos/Video.svelte";
import WTVideo from "./demos/WTVideo.svelte";
import Code from "../components/Code.svelte";
import CodeFormatter from "../components/CodeFormatter.svelte";
import StackLayer from "./demos/StackLayer.svelte";
import AspectRatio from "./demos/AspectRatio.svelte";
@ -188,7 +189,7 @@
</tabs>
<component>
{#if show_code}
<Code src={ selected.code } />
<Code src={ selected.code } format={ true } />
{:else}
<h1>{selected.title}</h1>
<svelte:component this={selected.component} />

9
client/bando/demos/Code.svelte

@ -1,7 +1,7 @@
<script>
import Code from "$/client/components/Code.svelte";
import Spinner from "$/client/components/Spinner.svelte";
import { onMount } from "svelte";
import CodeFormatter from "$/client/components/CodeFormatter.svelte";
let code = "";
let test_code = "/test.js";
@ -26,13 +26,13 @@
<Spinner />
{:then}
<p>You can display code with color, line numbers, and clipboard copying with <code>Code</code>, and you can click on the code to copy it to your clipboard:</p>
<Code content={ code } on:copy={ code_copied } />
<Code content={ code } on:copy={ code_copied } language="javascript" />
<hr>
<p>It's designed similar to the <code>Markdown</code> component in that you can put the code in <code>content=""</code>, the inner slot, or as a <code>src=""</code> url to load.</p>
<Code on:copy={ code_copied }>
<Code on:copy={ code_copied } language="javascript">
{ code }
</Code>
@ -41,7 +41,7 @@
<p>Here is the same code in <code>test.js</code> being loaded via a <code>src=""</code>.<p>
</p>
<Code src={ test_code } on:copy={ code_copied } />
<Code src={ test_code } on:copy={ code_copied } language="javascript"/>
{#if message}
<toast class="bottom-right">
@ -49,4 +49,5 @@
</toast>
{/if}
<CodeFormatter />
{/await}

8
client/bando/demos/Code.svelte.md

@ -2,7 +2,8 @@ The `Code` component simplifies displaying code with line numbers and letting pe
The CSS that makes this magic happen is:
```
<pre>
<code data-language="css">
pre code span::before {
counter-increment: line;
content: counter(line);
@ -17,9 +18,8 @@ pre code span::before {
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
```
}</code></pre>
This uses the `::before`` selector to add a line number counter to the front of each span, and then create a thin line. This is why you can use your mouse to select the lines of code but the _line numbers_ won't be selected (even if some browsers show you they are being selected).
To make it easier on people it will also just copy the code when you click on it and then do a `Toad` alert.
To make it easier on people it will also just copy the code when you click on it and then do a `Toast` alert.

17
client/components/BTCPay.svelte

@ -8,8 +8,8 @@
* The contract with RegisterPanel.svelte is that this component will return:
* internal_id, sys_primary_id, status for use with the register/index.json.js handler.
*/
import { onMount, createEventDispatcher } from 'svelte';
import { inject_remote } from '$/client/lib/helpers.js';
import { createEventDispatcher } from 'svelte';
import Source from './Source.svelte';
let loading_btc = false;
const dispatch = createEventDispatcher();
import Spinner from './Spinner.svelte';
@ -57,7 +57,7 @@
const btcpay_submit = async () => {
if(disabled) return;
if(fake_payments) {
if(fake_payments) {
// do a fake thing just to work on the UI
console.log("fake_payments set, sending finished event");
dispatch('finished', { system: 'btcpay', invoice_id: 'FAKE', sys_primary_id: 11234, status: 'complete'});
@ -86,13 +86,6 @@
}
}
}
onMount(() => {
if(!window.btcpay) {
inject_remote(document, btcpay_url);
}
});
</script>
<style>
@ -114,6 +107,8 @@
}
</style>
<Source src={ btcpay_url } />
<button on:click|preventDefault={ btcpay_submit } data-testid="btcpay-submit" class="btcpay-submit" alt="Pay with ₿itcoin">
{#if loading_btc}
<Spinner />
@ -121,5 +116,3 @@
Pay with <img alt="Bitcoin" class="bitcoin-logo" src="/images/Bitcoin_logo.svg">
{/if}
</button>

19
client/components/Code.svelte

@ -1,6 +1,7 @@
<script>
import { createEventDispatcher, onMount } from "svelte";
import Spinner from "./Spinner.svelte";
import CodeFormatter from "./CodeFormatter.svelte";
const dispatch = createEventDispatcher();
export let content = "";
@ -10,6 +11,8 @@
let slot_content = {textContent: "Loading..."};
let code = [];
let copied = false;
export let language="generic";
export let format = false;
let timer;
let code_promise;
@ -28,7 +31,7 @@
}
// we keep the original content for the copy/past functionality
code = original.trim().split('\n');
code = original.trim();
}
const copy_code = () => {
@ -71,12 +74,11 @@
<Spinner />
{:then}
<pre on:click={ copy_code } class:copied>
<code>
{#each code as line}
<span>{ line }</span>
{/each}
<code data-language={ language }>
{code}
</code>
</pre>
<CodeFormatter />
{/await}
{:else}
<span id="slot-content" bind:this={slot_content}><slot /></span>
@ -84,11 +86,10 @@
<Spinner />
{:then}
<pre on:click={ copy_code } class:copied>
<code>
{#each code as line}
<span>{ line }</span>
{/each}
<code data-language={ language }>
{code}
</code>
</pre>
<CodeFormatter />
{/await}
{/if}

14
client/components/CodeFormatter.svelte

@ -0,0 +1,14 @@
<script>
import Source from "$/client/components/Source.svelte";
const onLoad = (() => {
Rainbow.color(() => {
for(let el of document.getElementsByClassName("rainbow rainbow-show")) {
const lines = el.innerHTML.split("\n");
el.innerHTML = lines.map(l => `<div>${l}</div>`).join("");
}
});
});
</script>
<Source src="/js/rainbow.min.js" on:load={ onLoad }/>

6
client/components/Paypal.svelte

@ -6,7 +6,7 @@
<script>
import { createEventDispatcher } from 'svelte';
import { paypal_public } from '../lib/payments.js';
import { inject_remote } from '../lib/helpers.js';
import { inject_remote } from './Source.svelte';
import Modal from './Modal.svelte';
import Icon from './Icon.svelte';
import { product, fake_payments } from '../config.js';
@ -110,8 +110,8 @@
console.log("fake_payments set to true, sending error");
dispatch("error", { system: "paypal", sys_primary_id: 11333, status: "complete", invoice_id: "FAKE" });
} else if(!window.paypal) {
let disable_funding = ['credit', 'bancontact',
'blik', 'eps', 'giropay', 'ideal', 'mybank',
let disable_funding = ['credit', 'bancontact',
'blik', 'eps', 'giropay', 'ideal', 'mybank',
'p24', 'sepa', 'sofort', 'venmo'];
if(!credit_card) disable_funding.push('card');

37
client/components/Source.svelte

@ -0,0 +1,37 @@
<script context="module">
import { createEventDispatcher, onMount } from "svelte";
// this prevents loading it multiple times
const loaded = {};
const ready = {};
export const inject_remote = (document, url, ready_cb=undefined) => {
if(!loaded[url]) {
let head = document.getElementsByTagName('head')[0];
let script = document.createElement('script');
loaded[url] = true;
if(ready_cb) script.onload = () => {
ready[url] = true;
ready_cb();
}
script.src = url;
script.type = 'text/javascript';
head.append(script);
} else if(ready[url]) {
ready_cb();
}
}
</script>
<script>
export let src = "";
const dispatch = createEventDispatcher();
onMount(() => {
inject_remote(document, src, () => {
dispatch("load");
});
});
</script>

3
client/components/WTVideo.svelte

@ -1,7 +1,8 @@
<script>
import wt from '$/client/wt.js';
import { onMount, onDestroy } from 'svelte';
import { defer, inject_remote, random_numbers } from '$/client/lib/helpers.js';
import { defer, random_numbers } from '$/client/lib/helpers.js';
import { inject_remote } from "./Source.svelte";
import { blur } from 'svelte/transition';
import Icon from './Icon.svelte';
import Spinner from './Spinner.svelte';

9
client/lib/helpers.js

@ -1,13 +1,4 @@
export const inject_remote = (document, url, ready_cb=undefined) => {
let head = document.getElementsByTagName('head')[0];
let script = document.createElement('script');
if(ready_cb) script.onload = ready_cb;
script.src=url;
script.type = 'text/javascript';
head.append(script);
}
/* A simple function that uses the Crypto.getRandomValues to fill an
* array with 32 bit random numbers.
*/

13
static/global.css

@ -1,6 +1,9 @@
/* Heavily modified from the wonderful MVP.css v1.6.2 - https://github.com/andybrewer/mvp */
@import 'color.css';
/* You can remove this if you don't do any code in your project. */
@import '/css/rainbow/theme.css';
body * {
/* This fixes the classic CSS braindead decision that children can explode out
* of their parent's box.
@ -234,11 +237,6 @@ p {
padding: 0;
}
pre {
margin: 1rem 0;
padding: 1rem 0;
}
pre code,
pre samp {
display: block;
@ -574,13 +572,12 @@ pre code {
overflow-x: auto;
}
pre code span {
pre code div {
display: block;
white-space: nowrap;
white-space: pre;
}
pre code span::before {
pre code div::before {
counter-increment: line;
content: counter(line);
display: inline-block;

Loading…
Cancel
Save