Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,10 @@ window.__glpythonMount = (args, send) => {
...codeFiles.map(({ path, source }) => [path, { path, label: path, kind: /\.py$/i.test(path) ? "python" : "text", code: source }]),
])
const heading = frame?.closest(".lia-slide__content")?.querySelector("h1, h2, h3, h4, h5, h6")?.textContent?.trim()
const json = JSON.stringify({ v: libraries.length > 0 ? 2 : 1, name: heading || document.title || strings.ideProject, mainFile: program.mainFile, files })
// The block's own features= (what it shows) set the IDE's parts too; a
// block without features= leaves the IDE as it is.
const features = featuresOption ? requestedFeatures.filter((name) => featureNames.includes(name)) : null
const json = JSON.stringify({ v: libraries.length > 0 ? 2 : 1, name: heading || document.title || strings.ideProject, mainFile: program.mainFile, ...(features ? { features } : {}), files })
const [param, encoded] = fflate
? ["p", base64Url(fflate.deflateSync(new TextEncoder().encode(json), { level: 9 }))]
: ["project", lzString.compressToEncodedURIComponent(json)]
Expand Down Expand Up @@ -1139,7 +1142,12 @@ libraries by their URL - the IDE fetches them, so a block with a library keeps
a short link (an Etappe 4 hand-in measured 1,980 characters in the IDE's old
form and 1,185 in the compact one).
Libraries are read-only in the IDE (a lock, no editing, renaming or deleting),
as they are here. A link longer than 2,083 characters - OneNote, for one, cuts
as they are here. A block with `features=` passes them on: the IDE then shows
the same parts (▶, Tests, Visualisieren, the console's input line, the →
chain export, coverage, `listtree`, «Baum»; `ide` and `reset` mean nothing
there), as the starting state of that IDE tab - its ⋮ «Optionen» can switch
each part, e.g. for a teacher looking at a hand-in. A block without
`features=` passes nothing, and the IDE shows what it always does. A link longer than 2,083 characters - OneNote, for one, cuts
links there - is still copied, with a note to choose «In IDE öffnen» and
download the project there for a hand-in.
A link longer than GitHub Pages accepts (8192 characters of path and query, a
Expand Down
18 changes: 16 additions & 2 deletions scripts/check-ready.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ const blocks = [
{ id: 'empty', mode: 'visual', editors: [{ text: '', fill: null }] },
{ id: 'files', mode: 'eval', editors: [{ text: '', fill: 'start' }, { text: 'import datei1\nz = 3', fill: 'start' }] },
{ id: 'click', mode: 'eval', editors: [{ text: 'w = 4', fill: 1000 }] },
// A block with features= (LiaScript splits the argument at its commas).
{ id: 'feat', mode: 'eval', options: ['features=run', 'repl', 'visualize', 'tests', 'ide', 'coverage', 'listtree', 'tree'], editors: [{ text: 'v = 5', fill: 'start' }] },
]

const escape = (text) => text.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;')
const page = `<!doctype html>
<html><head><meta charset="utf-8"><title>glpython ready check</title></head>
<body>
${blocks.map((block) => `<div class="lia-slide__content" data-block="${block.id}">
${blocks.map((block) => `<div class="lia-slide__content" data-block="${block.id}" data-options="${escape(JSON.stringify(block.options ?? []))}">
<div class="lia-code--block">${block.editors.map((editor) => `<lia-editor data-text="${escape(editor.text)}" data-fill="${editor.fill}"></lia-editor>`).join('')}</div>
${template.replaceAll('@0', block.id).replaceAll('@1', block.mode)}
</div>`).join('\n')}
Expand Down Expand Up @@ -79,7 +81,8 @@ window.addEventListener('message', (event) => {
${onload}
for (const block of document.querySelectorAll('.lia-slide__content')) {
const id = block.dataset.block
window.__glpythonMount([id, block.querySelector('.glpython-embed').className.split('--')[1], '@0', '@1', '@2', '@3', '@4', '@5', '@6', '@7'], { lia: () => {} })
const options = JSON.parse(block.dataset.options)
window.__glpythonMount([id, block.querySelector('.glpython-embed').className.split('--')[1], ...['@0', '@1', '@2', '@3', '@4', '@5', '@6', '@7'].map((placeholder, index) => options[index] ?? placeholder)], { lia: () => {} })
}
</script>
</body></html>`
Expand Down Expand Up @@ -198,8 +201,19 @@ try {
if (compact !== null) assert.match(compact, /^[A-Za-z0-9_-]+$/, 'base64url without padding')
const payload = JSON.parse(compact !== null ? inflateRawSync(Buffer.from(compact, 'base64url')).toString('utf8') : lz.decompressFromEncodedURIComponent(old))
assert.equal(payload.mainFile, 'datei2.py')
assert.equal(payload.features, undefined, 'a block without features= writes none')
assert.deepEqual(Object.values(payload.files).map((file) => [file.path, file.code]), [['datei1.py', ''], ['datei2.py', 'import datei1\nz = 3']])
})
if (fflateLoads) {
await check('«IDE-Link kopieren» carries the block\'s features=', async () => {
await linkTab.waitForFunction(() => document.querySelector('#glpython-ide-feat')?.disabled === false, null, { timeout: 10000 })
await linkTab.locator('#glpython-ide-feat').click()
await linkTab.waitForTimeout(300)
const link = new URL(await linkTab.evaluate(() => navigator.clipboard.readText()))
const payload = JSON.parse(inflateRawSync(Buffer.from(link.searchParams.get('p'), 'base64url')).toString('utf8'))
assert.deepEqual(payload.features, ['run', 'repl', 'visualize', 'tests', 'ide', 'coverage', 'listtree', 'tree'])
})
}
await linkContext.close()
}
} finally {
Expand Down
Loading