Skip to content

Commit d5c11d1

Browse files
committed
The build page says a damaged link is damaged, and how to bring its source
A chat writes the link out in its reply, and a compressed source survives no wrong character: a link ChatGPT gave held 43 characters of its own in place of 37. The page then said the link had carried the source, over an empty box, with the reason under Build, out of sight. For a link whose source cannot be read, the hero now says the link arrived damaged, and the ways to bring the source are above its box: ask the chat for the link again, open the source file it gave, or paste the source. They go once a source is there. The reason goes to the console. Closes #38.
1 parent e7c3bc1 commit d5c11d1

3 files changed

Lines changed: 62 additions & 6 deletions

File tree

‎src/assets/site.css‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,9 @@ tbody th a:hover code { text-decoration: underline; }
647647
at once for one a chat sent with the source in the link. What is said to one alone is not shown
648648
to the other; the class is on <html> before the page paints (index.njk). */
649649
.linked .when-unlinked, :root:not(.linked) .when-linked { display: none; }
650+
/* A link whose source could not be read: what is said of the source it carried gives way to what
651+
is said of the link, from when build-page.ts has tried it. */
652+
.unread .when-read, :root:not(.unread) .when-unread { display: none; }
650653

651654
/* A bar at the top, then bands the width of the window, each holding a column of the page's width. */
652655
:root {

‎src/h5p/build/build-page.ts‎

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import { formatSource, jsonProblem, place, type Target } from './json-scan'
2626
* a sample that plays (`SAMPLE`), and finds the sample's source in the box, which the first paste
2727
* replaces whole (`prefillSample`). The markup says which words are for whom, and the class
2828
* `linked` on `<html>` shows them, set before the page paints by the script in `index.njk` and
29-
* kept in step with the address here.
29+
* kept in step with the address here. A link whose source cannot be read is said to be damaged,
30+
* with the ways to bring the source (`linkUnread`).
3031
*/
3132

3233
type Opened = Awaited<ReturnType<typeof openPack>>
@@ -41,6 +42,8 @@ const sourceField = $<HTMLTextAreaElement>('source')
4142
const sourceLabel = $('source-label')
4243
const sourceState = $('source-state')
4344
const sourceFile = $<HTMLInputElement>('source-file')
45+
const linkState = $('link-state')
46+
const openSource = $<HTMLButtonElement>('open-source')
4447
const filesStep = $('files-step')
4548
const fileList = $<HTMLUListElement>('file-list')
4649
const filesInput = $<HTMLInputElement>('files')
@@ -117,6 +120,28 @@ function setStatus(text: string, state: 'idle' | 'building' | 'ready' | 'error')
117120
status.dataset.state = state
118121
}
119122

123+
/**
124+
* A link whose source cannot be read. A chat writes the link out in its reply, and a compressed
125+
* source survives no wrong character: a link ChatGPT gave held 43 characters of its own in place
126+
* of 37, near its start, and was the command's output everywhere else. The page then said the link
127+
* had carried the source, over an empty box, with the reason under Build, out of sight in a window
128+
* 800px high. So it says the link is damaged where a person who opened it looks. The class `unread`
129+
* on `<html>` shows what the hero says of such a link in place of what it says of a source the link
130+
* carried, for the rest of the visit, since the link carried none whatever comes after. The words
131+
* above the box are the ways to bring the source, and stay until one is here (`checkSource`).
132+
*/
133+
function linkUnread(unread: boolean): void {
134+
document.documentElement.classList.toggle('unread', unread)
135+
showLinkState(unread)
136+
}
137+
138+
/** The words above the box, and with them the step's marker, which site.css draws from their state. */
139+
function showLinkState(show: boolean): void {
140+
linkState.hidden = !show
141+
if (show) linkState.dataset.state = 'error'
142+
else delete linkState.dataset.state
143+
}
144+
120145
/** Where a problem is in the source, for the button that goes there: its place in the text, or none. */
121146
function target({ path, at }: Problem): Target {
122147
return at === undefined ? { path } : { at }
@@ -316,6 +341,8 @@ player.addEventListener('error', (event) => {
316341
*/
317342
function checkSource(): void {
318343
const text = sourceField.value
344+
// A source came after a link that could not be read, from a file or a paste: the ways to bring one go.
345+
if (!linkState.hidden && compactSource(text)) showLinkState(false)
319346
const problem = jsonProblem(text)
320347
sourceState.dataset.state = problem ? 'error' : text.trim() ? 'ok' : ''
321348
if (!problem) {
@@ -406,6 +433,8 @@ sourceFile.addEventListener('change', async () => {
406433
if (!file) return
407434
setSource(await file.text())
408435
})
436+
// The same file field, from the words above the box on a link that could not be read.
437+
openSource.addEventListener('click', () => sourceFile.click())
409438

410439
// The label is for the textarea, which the editor hides: a click on it goes to the editor.
411440
sourceLabel.addEventListener('click', () => editor?.focus())
@@ -537,9 +566,12 @@ async function fromLink(): Promise<void> {
537566
try {
538567
text = await sourceFromFragment(location.hash)
539568
} catch (error) {
540-
setStatus(error instanceof Error ? error.message : String(error), 'error')
569+
// Why it cannot be read is for whoever looks into it; the person is told what to do.
570+
console.warn(error instanceof Error ? error.message : String(error))
571+
linkUnread(true)
541572
return
542573
}
574+
linkUnread(false)
543575
if (text === null) return
544576
carried = compactSource(text) ?? ''
545577
setSource(text)

‎src/h5p/build/index.njk‎

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ csp: "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' da
3030
(#source=), gets the build at once. One who came with none gets a landing page: what it makes,
3131
a sample that plays, how to make their own. What is said to one alone is marked when-linked or
3232
when-unlinked, and site.css shows it by the class this line puts on <html> before the page
33-
paints; build-page.ts keeps the class in step with the address from then on. -#}
33+
paints; build-page.ts keeps the class in step with the address from then on. A link whose
34+
source cannot be read is a third case, which build-page.ts finds once it has tried: it puts
35+
`unread` on <html>, and what is said of a source the link carried is marked when-read, what is
36+
said in its place when-unread. -#}
3437
<script>if (new URLSearchParams(location.hash.slice(1)).has("source")) document.documentElement.classList.add("linked")</script>
3538
{% include "topbar.njk" %}
3639

@@ -51,11 +54,20 @@ csp: "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' da
5154
<a class="button button-solid button-large" href="#make">Make your own</a>
5255
<a class="button button-large" href="#build-it">Paste your chat's JSON</a>
5356
</div>
54-
<p class="lead when-linked">The link you opened carries an activity an AI chat wrote.</p>
55-
<p class="when-linked">
57+
<p class="lead when-linked when-read">The link you opened carries an activity an AI chat wrote.</p>
58+
<p class="when-linked when-read">
5659
This page builds it in your browser, where you play it and download a
5760
<code>.h5p</code> file that Moodle or any other H5P site takes. Nothing is uploaded.
5861
</p>
62+
{#- A link whose source cannot be read: a chat writes the link out itself, and one wrong
63+
character leaves nothing of a compressed source. The page says so here, first, in place
64+
of saying the link carried an activity, and what to do above the source's box. These
65+
two stay for the visit, so they say what stays true once the source has come another way. -#}
66+
<p class="lead when-unread">The link you opened arrived damaged, so the activity in it cannot be read.</p>
67+
<p class="when-unread">
68+
This page builds an activity in your browser from its source, which
69+
<a href="#source-heading">step 1</a> says how to bring here. Nothing is uploaded.
70+
</p>
5971
</div>
6072
{#- The sample is /h5p/build/sample.h5p, which Vite builds from sample.json beside this file.
6173
build-page.ts gives the player its address only for a visitor who came with no source. -#}
@@ -157,7 +169,16 @@ csp: "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' da
157169
<section class="step" aria-labelledby="source-heading">
158170
<h3 id="source-heading"><span class="step-marker"><span class="step-number">1</span></span> Source</h3>
159171
<p class="when-unlinked">The source is your activity as the chat wrote it. The sample's is here to start with: paste yours over it, or open it from a file.</p>
160-
<p class="when-linked">The source is your activity as the chat wrote it. The link carried it here.</p>
172+
<p class="when-linked">The source is your activity as the chat wrote it. <span class="when-read">The link carried it here.</span></p>
173+
{#- Shown by build-page.ts for a link whose source cannot be read, until a source is here: above
174+
the box, where a person who opened the link looks, with each way to bring the source. -#}
175+
<p class="status" id="link-state" role="status" hidden>
176+
The source this link carried cannot be read: a chat can get characters wrong when it
177+
writes out a long link. Ask it to give the link again. If it gave you a
178+
<code>.source.json</code> file,
179+
<button type="button" class="link-button" id="open-source">open that file here</button>
180+
and choose Build below. Or ask it for the source as JSON and paste it into the box.
181+
</p>
161182
<div class="field">
162183
<label for="source" id="source-label">The source, as JSON</label>
163184
<textarea id="source" rows="12" spellcheck="false" autocomplete="off" placeholder="The source your chat wrote goes here. It starts with { and ends with }."></textarea>

0 commit comments

Comments
 (0)