Skip to content

Commit 9e1139e

Browse files
authored
Demo by URL in docs (#84)
1 parent f6a2d28 commit 9e1139e

File tree

6 files changed

+210
-23
lines changed

6 files changed

+210
-23
lines changed

docs/astro.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export default defineConfig({
4848
link: '/'
4949
},
5050
{
51-
label: 'Demo',
51+
label: 'Demo 🚀',
5252
link: '/user/demo/'
5353
},
5454
{

docs/src/components/CapoClient.astro

Lines changed: 133 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
import { Icon } from '@astrojs/starlight/components';
3+
import { Tabs, TabItem } from '@astrojs/starlight/components';
34
---
45

56
<script>
@@ -8,22 +9,88 @@ import { Icon } from '@astrojs/starlight/components';
89

910
document.addEventListener('DOMContentLoaded', init);
1011

11-
function init() {
12-
const input = document.querySelector('#input');
13-
const markup = document.querySelector('#markup');
14-
const output = document.querySelector('#output');
12+
let markup, input, output, reminder, virtualConsole, url;
1513

16-
const virtualConsole = new VirtualConsole(output);
14+
function init() {
15+
virtualConsole = new VirtualConsole(output);
16+
input = document.querySelector('#input');
17+
output = document.querySelector('#output');
18+
reminder = document.querySelector('#reminder');
19+
markup = document.querySelector('#markup');
20+
url = document.querySelector('#url');
21+
22+
initUrl();
23+
virtualConsole = new VirtualConsole(output);
1724

1825
input.addEventListener('submit', e => {
1926
try {
20-
run(markup.value, virtualConsole);
27+
handleSubmit();
2128
} catch (e) {
22-
console.error(e);
29+
console.error('Capo error', e);
2330
}
2431
e.preventDefault();
32+
return false;
2533
});
2634
}
35+
36+
async function initUrl() {
37+
const thisUrl = new URL(location.href);
38+
const urlParam = thisUrl.searchParams.get('url');
39+
if (!urlParam) {
40+
return;
41+
}
42+
url.value = urlParam;
43+
document.querySelector('a[role=tab]:not([aria-selected])').click();
44+
try {
45+
await handleSubmit();
46+
} catch (e) {
47+
console.error('Capo error', e);
48+
}
49+
}
50+
51+
function setUrl(urlParam) {
52+
const thisUrl = new URL(location.href);
53+
thisUrl.searchParams.set('url', urlParam);
54+
history.replaceState(null, null, thisUrl);
55+
}
56+
57+
async function handleSubmit() {
58+
reminder.classList.remove('highlight');
59+
const html = await getHtml(virtualConsole);
60+
virtualConsole.clear();
61+
run(html, virtualConsole);
62+
reminder.classList.add('highlight');
63+
}
64+
65+
async function getHtml() {
66+
let html;
67+
const selectedTab = document.querySelector('a[role=tab][aria-selected=true]').innerText;
68+
69+
if (selectedTab === 'URL') {
70+
if (!url.value || !url.validity.valid) {
71+
throw new Error(`Invalid URL "${url.value}"`);
72+
}
73+
if (url.value != url.getAttribute('placeholder')) {
74+
setUrl(url.value);
75+
}
76+
html = await getStaticHTML(url.value);
77+
} else {
78+
html = markup.value;
79+
}
80+
81+
if (!html) {
82+
throw new Error('Unable to run. Invalid HTML.');
83+
}
84+
85+
return html;
86+
}
87+
88+
async function getStaticHTML(url) {
89+
const proxy = new URL('https://capo.rviscomi.workers.dev/');
90+
proxy.searchParams.set('url', url);
91+
const response = await fetch(proxy);
92+
return await response.text();
93+
}
2794
</script>
2895

2996
<style>
@@ -58,11 +125,67 @@ import { Icon } from '@astrojs/starlight/components';
58125
vertical-align: middle;
59126
margin-left: 0.5rem;
60127
}
128+
129+
input {
130+
width: 100%;
131+
}
132+
133+
input:invalid {
134+
border-color: #9e0142;
135+
}
136+
137+
#output .warn {
138+
background-color: rgba(255, 159, 67, 0.1);
139+
color: orange;
140+
}
141+
142+
#output .error {
143+
background-color: rgba(255, 99, 132, 0.1);
144+
color: red;
145+
}
146+
147+
#reminder {
148+
transition: background-color 0.5s;
149+
}
150+
151+
#reminder.highlight {
152+
animation: highlight 1s ease-in-out;
153+
}
154+
155+
@keyframes highlight {
156+
0% {
157+
background-color: transparent;
158+
}
159+
10% {
160+
background-color: rgba(255, 255, 0, 0.4);
161+
}
162+
end {
163+
background-color: transparent;
164+
}
165+
}
61166
</style>
62167

168+
<p>To see capo.js in action, enter HTML or a URL in the form field below and click <strong>Run</strong>.</p>
169+
170+
<p><strong id="reminder">Results are logged to the DevTools console.</strong></p>
171+
63172
<form id="input">
64-
<textarea id="markup" placeholder="Enter HTML">
65-
<title>test</title>
66-
</textarea>
173+
<Tabs>
174+
<TabItem label="HTML">
175+
<textarea id="markup" placeholder="Enter HTML">
176+
<title>test</title>
177+
<meta charset="utf-8">
178+
<meta name="description" content="Try capo.js">
179+
<style></style>
180+
<meta http-equiv="origin-trial" content="AuNyVoVDAnYrBa2cL89WmgDSi1Os1UAt4SmcY1vXSJKDlIlBNfD4SEpIfg3LNDexEWv6N2kHnJ17MT4cVmRhQgIAAABueyJvcmlnaW4iOiJodHRwczovL3J2aXNjb21pLmdpdGh1Yi5pbzo0NDMiLCJmZWF0dXJlIjoiQmFja0ZvcndhcmRDYWNoZU5vdFJlc3RvcmVkUmVhc29ucyIsImV4cGlyeSI6MTY5MTUzOTE5OX0=">
181+
<script></script>
182+
</textarea>
183+
</TabItem>
184+
<TabItem label="URL">
185+
<input id="url" type="url" value="https://www.example.com/" placeholder="https://www.example.com/">
186+
</TabItem>
187+
</Tabs>
67188
<button>Run <Icon name="rocket" color="inherit" size="1.5rem" /></button>
68189
</form>
190+
191+
<div id="output"></div>

docs/src/content/docs/index.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ hero:
77
image:
88
file: ../../assets/capo256.png
99
actions:
10-
- text: Read the quick start guide
11-
link: /capo.js/user/quick-start/
12-
icon: right-arrow
10+
- text: Try it live
11+
link: /capo.js/user/demo/
12+
icon: rocket
1313
variant: primary
1414
- text: Browse the source
1515
link: https://github.com/rviscomi/capo.js
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
---
2-
title: capo.js demo
2+
title: Try capo.js live 🚀
33
description: Try capo.js
4+
tableOfContents: false
45
---
56

67
import CapoClient from '../../../components/CapoClient.astro';
78

8-
## Try it live
9-
10-
To see capo.js in action, enter some HTML in the form field below and click the "Run" button.
11-
12-
Results are logged to the DevTools console.
13-
149
<CapoClient/>

docs/src/lib/VirtualConsole.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,96 @@ export class VirtualConsole {
22

33
constructor(rootElement) {
44
this.rootElement = rootElement;
5+
this.group = null;
6+
}
7+
8+
clear() {
9+
this.rootElement.innerHTML = '';
10+
}
11+
12+
renderLog(...args) {
13+
let output = [];
14+
args.forEach((arg, i) => {
15+
if (!arg) {
16+
return;
17+
}
18+
19+
if (arg instanceof HTMLElement) {
20+
// Stringify element
21+
output.push(escapeHTML(arg.outerHTML));
22+
return;
23+
}
24+
25+
if (typeof arg == 'string') {
26+
// Handle console styles
27+
const fragments = arg.split('%c');
28+
if (fragments.length == 1) {
29+
output.push(escapeHTML(arg));
30+
return;
31+
}
32+
33+
for (let j = 1; j < fragments.length; j++) {
34+
const fragment = escapeHTML(fragments[j]);
35+
// The subsequent arg is the style for this fragment
36+
fragments[j] = `<span style="${args[i + j]}">${fragment}</span>`;
37+
delete args[i + j];
38+
}
39+
40+
output.push(fragments.map(nlToBr).join(''));
41+
}
42+
});
43+
44+
return output.join(' ');
45+
}
46+
47+
logAtLevel(level, ...args) {
48+
return;
49+
const div = document.createElement('div');
50+
div.classList.add(level);
51+
div.innerHTML = this.renderLog(...args);
52+
53+
if (this.group) {
54+
this.group.appendChild(div);
55+
} else {
56+
this.rootElement.appendChild(div);
57+
}
558
}
659

760
log(...args) {
61+
this.logAtLevel('log', ...args);
862
console.log(...args);
963
}
1064

1165
warn(...args) {
12-
console.log(...args);
66+
this.logAtLevel('warn', ...args);
67+
console.warn(...args);
1368
}
1469

1570
error(...args) {
71+
this.logAtLevel('error', ...args);
1672
console.error(...args);
1773
}
1874

1975
groupCollapsed(...args) {
76+
/* this.group = document.createElement('details');
77+
const summary = document.createElement('summary');
78+
summary.innerHTML = this.renderLog(...args);
79+
this.group.appendChild(summary); */
2080
console.groupCollapsed(...args);
2181
}
2282

2383
groupEnd(...args) {
84+
/* this.rootElement.appendChild(this.group); */
85+
this.group = null;
2486
console.groupEnd(...args);
2587
}
2688

2789
}
90+
91+
function nlToBr(str) {
92+
return str.replace(/\n/g, '<br>');
93+
}
94+
95+
function escapeHTML(str) {
96+
return str.replace(/<([^>]*>)[^<]*(<.*)/g, '<span style="font-family: monospace;">&lt;$1&hellip;');
97+
}

docs/src/lib/capo.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)