prolog-notebook 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/package.json +3 -2
- package/src/browser.js +11 -0
- package/src/build-info.json +2 -2
- package/src/build.js +21 -1
- package/src/notebook.js +17 -6
- package/src/version.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.7.1] — 2026-08-31
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`build` could not find the engine when the tool was installed.** It looked for swipl-wasm at
|
|
8
|
+
`<this package>/node_modules/swipl-wasm/…`, and npm **hoists** — the dependency is installed as
|
|
9
|
+
a *sibling* of `prolog-notebook`, not inside it. Nesting is what npm falls back to on a version
|
|
10
|
+
conflict, so the one layout that path assumed is the one npm avoids:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Error: ENOENT: no such file or directory, copyfile
|
|
14
|
+
'.../node_modules/prolog-notebook/node_modules/swipl-wasm/dist/swipl/swipl-bundle.js'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This was never a 0.7.0 regression — 0.6.5 fails identically from a real install. `build` has
|
|
18
|
+
only ever worked from a checkout, where that path happens to exist, which is the only way we
|
|
19
|
+
had ever run it. The engine is now located through Node's own resolution, which finds the
|
|
20
|
+
package wherever it was put: hoisted, nested, in pnpm's store, or in a workspace.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **A test that uses the package the way somebody else receives it** — `npm run test:packaged`
|
|
25
|
+
packs the tarball, installs it elsewhere, and builds and runs a chapter with it, asserting
|
|
26
|
+
first that swipl-wasm really was hoisted so the test cannot pass vacuously. Every other test
|
|
27
|
+
runs against the checkout, where `node_modules` sits exactly where a relative path expects it,
|
|
28
|
+
which is precisely why this class of bug was invisible twice. CI runs it on every push and
|
|
29
|
+
before every publish.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **A chapter with no saved answers no longer offers a disabled *Restore outputs*.** Run a cell in
|
|
34
|
+
such a chapter, clear it, and the panel offered to put back answers that never existed — greyed
|
|
35
|
+
out, because there was nothing to put back. A disabled control says *this could happen, but not
|
|
36
|
+
now*, and there was no now. The button now reads *Clear all outputs*, disabled, which is the
|
|
37
|
+
page's opening state and the truth: nothing on screen, nothing to clear. The count still says
|
|
38
|
+
*1 output cleared*, because that part was never a lie — it is why the page looks empty.
|
|
39
|
+
|
|
40
|
+
Most chapters ship without saved answers, since `hold` is how an author keeps them from
|
|
41
|
+
students, so this was the common chapter's common path rather than an edge case.
|
|
42
|
+
|
|
3
43
|
## [0.7.0] — 2026-08-31
|
|
4
44
|
|
|
5
45
|
A site of notebooks, rather than a folder of unrelated pages.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prolog-notebook",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Jupyter-style notebooks for Prolog. Runs in the browser, installs nothing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/node.js",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"test": "node --test test/*.test.mjs",
|
|
32
32
|
"dev": "python3 -m http.server 8777",
|
|
33
|
-
"prepublishOnly": "npm test"
|
|
33
|
+
"prepublishOnly": "npm test",
|
|
34
|
+
"test:packaged": "node --test test/packaged.mjs"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
|
36
37
|
"prolog",
|
package/src/browser.js
CHANGED
|
@@ -8,6 +8,17 @@ import { ConsultLog, defaultCellName, unconsult } from './session.js';
|
|
|
8
8
|
export * from './engine.js';
|
|
9
9
|
export { ConsultLog } from './session.js';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* WHERE A PAGE SERVED OUT OF THIS REPO FINDS THE ENGINE — and only such a page.
|
|
13
|
+
*
|
|
14
|
+
* The same-looking literal in build.js was a bug: it guessed at a node_modules
|
|
15
|
+
* layout npm does not use, so `build` could not find the engine when the tool was
|
|
16
|
+
* installed (869erzf1j). This one is NOT that bug, and must not be "fixed" into a
|
|
17
|
+
* new one. There is no module resolution in a browser to ask instead, and every
|
|
18
|
+
* caller that ships — the app.js of a built page — passes `swiplUrl` outright. So
|
|
19
|
+
* this default is reached in exactly one situation: a page served from the repo
|
|
20
|
+
* root by `npm run dev`, where `../node_modules/…` from `/src/` is the truth.
|
|
21
|
+
*/
|
|
11
22
|
const DEFAULT_SWIPL_URL = new URL(
|
|
12
23
|
'../node_modules/swipl-wasm/dist/swipl/swipl-bundle.js',
|
|
13
24
|
import.meta.url
|
package/src/build-info.json
CHANGED
package/src/build.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
// `view` can serve it, and a test can read it, without any of the three
|
|
17
17
|
// disagreeing about what a page is.
|
|
18
18
|
import { createRequire } from 'node:module';
|
|
19
|
+
import { pathToFileURL } from 'node:url';
|
|
19
20
|
import { parse } from './format.js';
|
|
20
21
|
import { renderNotebook } from './render.js';
|
|
21
22
|
|
|
@@ -31,6 +32,25 @@ import { renderNotebook } from './render.js';
|
|
|
31
32
|
const require = createRequire(import.meta.url);
|
|
32
33
|
export const ENGINE_VERSION = require('swipl-wasm/package.json').version;
|
|
33
34
|
|
|
35
|
+
/**
|
|
36
|
+
* WHERE THE ENGINE ACTUALLY IS — asked for, never guessed (869erzf1j).
|
|
37
|
+
*
|
|
38
|
+
* This was `new URL('../node_modules/swipl-wasm/dist/swipl/', import.meta.url)`,
|
|
39
|
+
* which is true in a checkout and false in every install: npm HOISTS, so
|
|
40
|
+
* swipl-wasm lands as a SIBLING of this package rather than inside it, and
|
|
41
|
+
* `build` died on a missing file for anybody who had installed the tool rather
|
|
42
|
+
* than cloned it. Nested is the exception npm resorts to on a version conflict —
|
|
43
|
+
* the one layout that literal assumed was the one npm avoids.
|
|
44
|
+
*
|
|
45
|
+
* Node's own resolution finds the package wherever it was put: hoisted, nested,
|
|
46
|
+
* inside pnpm's store, or in a workspace. The line above already asked properly
|
|
47
|
+
* for the version; this one now asks properly for the bytes.
|
|
48
|
+
*/
|
|
49
|
+
export const ENGINE_HOME = new URL(
|
|
50
|
+
'dist/swipl/',
|
|
51
|
+
pathToFileURL(require.resolve('swipl-wasm/package.json')),
|
|
52
|
+
);
|
|
53
|
+
|
|
34
54
|
/** The runtime a page needs. Copied side by side, so their relative imports hold. */
|
|
35
55
|
export const RUNTIME = [
|
|
36
56
|
'notebook.js', 'browser.js', 'session.js', 'engine.js', 'worker.js',
|
|
@@ -86,7 +106,7 @@ export function buildFiles(notebook, source, options = {}) {
|
|
|
86
106
|
const {
|
|
87
107
|
filename = 'notebook.prolog.md',
|
|
88
108
|
src = new URL('./', import.meta.url),
|
|
89
|
-
engine =
|
|
109
|
+
engine = ENGINE_HOME,
|
|
90
110
|
prefix = './',
|
|
91
111
|
engineVersion = ENGINE_VERSION,
|
|
92
112
|
} = options;
|
package/src/notebook.js
CHANGED
|
@@ -502,14 +502,25 @@ function mountPageBar(root, options, bus, programs, queries) {
|
|
|
502
502
|
refreshOutputs = () => {
|
|
503
503
|
const gone = queries.filter((q) => q.isCleared());
|
|
504
504
|
const left = queries.filter((q) => q.hasOutput());
|
|
505
|
-
// Restore only once there is nothing left to clear, which is the rule the
|
|
506
|
-
// hide/show button already follows: in a half-cleared page the useful move
|
|
507
|
-
// is to finish, and one vocabulary is cheaper to learn than two.
|
|
508
|
-
const back = left.length === 0 && gone.length > 0;
|
|
509
505
|
// A cleared cell that never had saved answers has nothing of the chapter's
|
|
510
|
-
// to give back
|
|
506
|
+
// to give back: restore is the way back to the FILE, and the file is empty.
|
|
511
507
|
const restorable = gone.filter((q) => q.hasSaved).length;
|
|
512
|
-
|
|
508
|
+
// Restore only once there is nothing left to clear — the rule the hide/show
|
|
509
|
+
// button already follows, since in a half-cleared page the useful move is to
|
|
510
|
+
// finish — AND only when there is something to put back.
|
|
511
|
+
//
|
|
512
|
+
// That second half was missing (869erzhe7): a chapter published without
|
|
513
|
+
// answers, run by the reader and then cleared, offered them a DISABLED
|
|
514
|
+
// "Restore outputs". The Captain: "it shows the incorrect 'Restore output' -
|
|
515
|
+
// disabled … dont show restore when there's nothing to restore."
|
|
516
|
+
//
|
|
517
|
+
// He is right, and it is the doctrine rather than a detail. A disabled
|
|
518
|
+
// control says "this could happen, but not now"; there is no now in which
|
|
519
|
+
// that chapter's answers come back, because it never had any. The true
|
|
520
|
+
// reading of that state is the one the page started in — no outputs, nothing
|
|
521
|
+
// to clear — so the button says so.
|
|
522
|
+
const back = left.length === 0 && restorable > 0;
|
|
523
|
+
wipe.disabled = !back && left.length === 0;
|
|
513
524
|
// COUNTED FROM THE PAGE, which is the only count that stays true for both
|
|
514
525
|
// kinds of chapter: one published with its answers in it, and one still
|
|
515
526
|
// being written where every output on screen is the reader's own.
|
package/src/version.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
export const NAME = 'Prolog Notebook';
|
|
11
11
|
|
|
12
12
|
/** Must equal package.json's `version` — test/run.test.mjs enforces it. */
|
|
13
|
-
export const VERSION = '0.7.
|
|
13
|
+
export const VERSION = '0.7.1';
|
|
14
14
|
|
|
15
15
|
/** The two facts a licence notice is actually made of. */
|
|
16
16
|
export const YEAR = '2026';
|