Create modular javascript for bundling#2815
Create modular javascript for bundling#2815oscarlevin wants to merge 12 commits intoPreTeXtBook:masterfrom
Conversation
- script/jsbuilder/PLAN.md: full plan for converting JS to ES modules, removing jQuery, and building bundles with esbuild (mirroring cssbuilder) - .github/copilot-instructions.md: Copilot context for this repo Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Corrected line counts and jQuery status per file - Documented dead/broken code (ptx_search.js, video magnify, knowl_focus_stack) - Added modular structure: js/src/ with focused modules - Reorganized phases: modularize first, then convert standalone files - Added js/src/deprecated/ for flagged dead code Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Create script/jsbuilder/ mirroring the cssbuilder pattern: - package.json: esbuild dependency, build/watch scripts, Node >=18 - jsbuilder.mjs: two bundle targets (pretext-core, pretext-search), CLI with --help, --list-targets, --watch, --output-directory - README.md: usage docs and build target reference Entry-point source files (js/src/*-entry.js) will be created in Phase 4 after modules are extracted. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Break the 1,340-line monolith into 19 focused modules under js/src/: Core modules: - permalink.js: copy-to-clipboard for permalinks - image-magnify.js: click-to-zoom image popup (jQuery removed) - geogebra.js: GeoGebra calculator integration (jQuery removed) - keyboard-nav.js: ESC/ENTER key handlers + anchor-knowl nav (jQuery removed) - theme.js: dark/light mode switching - embed.js: LMS embed button + embed display mode - code-copy.js: code block copy button Print-preview subsystem (9 modules in print-preview/): - index.js: orchestrator for print preview setup - pages.js: page creation and adjustment - workspace.js: workspace height management - headers-footers.js: editable header/footer management - page-breaks.js: DP page-break algorithm - geometry.js: page geometry CSS + unit conversion - paper-size.js: letter/a4 detection via geolocation - section-swap.js: printout section loading - solutions.js: details-to-div rewriting Deprecated modules (flagged for future removal): - scrollbar-width.js: only used by GeoGebra - auto-id.js: suspicious utility with heavy console spam - video-magnify.js: dead code (selector matches nothing) Bug fixes in extracted modules: - keyboard-nav.js: add missing break after case 13 (ENTER), preventing fallthrough to ESC handler - keyboard-nav.js: guard knowl_focus_stack reference with typeof check to prevent ReferenceError - auto-id.js: replace jQuery .prevAll() with vanilla DOM traversal jQuery removed from: image-magnify, geogebra, keyboard-nav, auto-id (~35 calls total). Original pretext_add_on.js left intact until Phase 4. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Create ES module versions of the existing standalone scripts in js/src/: - toc.js: TOC sidebar, scroll-to-active, focused/expandable items (from pretext.js) - knowl.js: xref/born-hidden knowl behavior with slide animation (from knowl.js) - lti-iframe-resizer.js: SPLICE iframe resize message handler (from lti_iframe_resizer.js) - search.js: lunr-based search UI with result ranking and snippets (from pretext_search.js) Each module exports init functions that register event listeners. Original files are left intact so existing <script> tags continue to work until Phase 5 updates the XSL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Entry points: - js/src/pretext-core-entry.js: imports all core modules (TOC, knowls, LTI resizer, permalink, image magnify, GeoGebra, keyboard nav, print preview, theme, embed, code-copy, deprecated modules) - js/src/pretext-search-entry.js: imports search module Built bundles (committed for users without Node): - js/dist/pretext-core.js (59 KB) + sourcemap - js/dist/pretext-search.js (9 KB) + sourcemap Both bundles are IIFE format, unminified, with sourcemaps. MathJax is marked as external (loaded separately). Deleted js/jquery.min.js no longer needed since all jQuery calls have been replaced with vanilla DOM in Phase 2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
pretext-js template: - Replace 3 script tags (jquery.min.js, pretext.js, pretext_add_on.js) with single dist/pretext-core.js knowl template: - Remove standalone knowl.js script tag (now in core bundle) - Keep sagecell eval name inline script lti-iframe-resizer template: - Remove standalone lti_iframe_resizer.js script tag (now in core bundle) - Template kept empty so callers don't break native-search-box-js template: - Load dist/pretext-search.js instead of pretext_search.js Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update copy_html_js() to exclude the js/src/ directory when copying JS files to the build output. Only the pre-built bundles in js/dist/ are needed at runtime; the ES module source files are development-only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expose isDarkMode() and setDarkMode() on window so inline XSL scripts (mermaid init) can access them from outside the IIFE bundle closure. Restore jQuery as a local file (upgraded to 3.7.1) for Runestone compatibility. jQuery is loaded conditionally only when Runestone JS bundles are present, keeping non-Runestone pages jQuery-free. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Print preview rewrites <details> born-hidden-knowl elements into <div>s (removing <summary>), but keeps the class. When initKnowls() later queries for .born-hidden-knowl > summary, it gets null and crashes. Skip elements that have already been rewritten. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thoughts - not trying to start discussion here necessarily, mostly so I remember. Any appetite for moving raw source to typescript? IMO it goes a long way to reduce some sources of bugs related to type coercion between things like null, undefined, "", false, etc... If there was, seems like a logical time to introduce. Integration with themes? There isn't tons of theme specific JS. So don't think we need to do anything at this stage. But if a theme needs specific JS for handling UI elements, it would be nice to only include that when necessary (especially if different themes have conflicting requirements). What might that look like? Sidecar files? Monolithic self contained single js file for each theme? Definitely not a part of this PR, but IMO PTX should not have to inject JQuery for RS. RS should be bundling that itself. |
|
Yes, I would be in favor of modernization and bundling. I see your CoPilot and raise you by a Claude Code. Next. |
|
This is a significant infrastructure change — modularizing the JavaScript, removing jQuery from core, and introducing an esbuild-based build system. Some observations: Architecture. The approach mirrors the existing CSS build system ( jQuery removal. jQuery is removed from core and only loaded conditionally for Runestone builds ( Old files not removed. The original files ( Built artifacts in the repo. The Copilot instructions file. The PR adds PLAN.md.
The The knowl module was substantially rewritten. Comparing the old Dead code is preserved with deprecation flags. The Responding to @ascholerChemeketa's comment about TypeScript: that would be a separate decision and probably best deferred until the modular structure settles. The current JS modules are a good foundation that TypeScript could be layered onto later. Claude Opus 4.6, acting as a review assistant for Rob Beezer |
|
Removing jQuery will break the interactive components in static html builds. I'm sure it can be done, but I think I would rather put my efforts into the continued removal of jQuery from the components themselves and once that is complete then you would not need to include it anywhere. Brad Miller, acting like he knows what he's talking about. |
|
Thanks everyone. I am 100% on board with moving toward typescript (that's what I'm using for pretext tools and such). The various comments about old files and the plan.md and copilot-instructions.md, I totally agree that they will go away before this is merged. I'll take a close look at the knowl.js rewrite and make sure that is for the best. So I guess that if that gets resolved, then this is likely good to go. I'll try to get this cleaned up this weekend. |
|
@oscarlevin - I am battling LaTeX, MathJax 3, and MathJax 4 today. Slow going and subject to big changes at the least surprise. :-( But to your point, I have branch which incorporates #2180 - adding a new *.js and removing mathjaxknowl3.js. But I think it needs to sit and wait for mid-May. Not sure how disruptive that is for you right now? |
|
I don't think that change would be difficult to incorporate (this switch leaves mathjaxknowl3.js alone, I think). While modularizing should not have any effect on users, it will make development a lot easier. So I would recommend we take care of this sooner rather than later. That said, I can redo this work again later if you think it should wait. |
|
Just a heads-up, I would not, was not, suggesting a pause until mid-May. Unless my change was going to be a headache, otr something. Carry on. |
With the help of copilot I have a possible way forward on making the javascript modular and easier to maintain. I'm marking this as draft, since it definitely needs more eyes and testing, but from what I've seen, there are no functional changes to the sample article or sample book.
The idea is that we will maintain a js/src directory with modular files that get bundled by a esbuild function (see
script/jsbuilder) This createsjs/dist/pretext-core.jsandjs/dist/pretext-search.js(since we don't always provide the search javascript).There was an initial attempt to remove jquery (and I think we removed the reliance on jquery from pretext_add_on's replacements), but I think maybe some runestone js requires us to have a copy of jquery? I don't really understand that.
So @rbeezer and @ascholerChemeketa, do you think this is the sort of thing we want? Any suggestions? When we are mostly happy with the new file structure I will remove the old files we no longer need and clean up all the commits.