unaltraweb 0.3.0
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.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/Makefile +412 -0
- data/README.md +226 -0
- data/_config.yml +842 -0
- data/_data/i18n/ca.yml +278 -0
- data/_data/i18n/en.yml +278 -0
- data/_data/i18n/es.yml +278 -0
- data/_includes/audio.liquid +30 -0
- data/_includes/bib_search.liquid +5 -0
- data/_includes/blog-list.liquid +66 -0
- data/_includes/book-citation.liquid +33 -0
- data/_includes/citation.liquid +26 -0
- data/_includes/custom_head.liquid +3 -0
- data/_includes/custom_scripts.liquid +5 -0
- data/_includes/cv/list.liquid +5 -0
- data/_includes/cv/list_groups.liquid +51 -0
- data/_includes/cv/map.liquid +29 -0
- data/_includes/cv/nested_list.liquid +16 -0
- data/_includes/cv/time_table.liquid +118 -0
- data/_includes/cv-download-card.liquid +26 -0
- data/_includes/developer-mode-switcher.liquid +24 -0
- data/_includes/disqus.liquid +13 -0
- data/_includes/distill_scripts.liquid +298 -0
- data/_includes/documentation-download-detail.liquid +76 -0
- data/_includes/documentation-downloads.liquid +71 -0
- data/_includes/documentation-profile-attributes.liquid +4 -0
- data/_includes/documentation-section-toc.liquid +9 -0
- data/_includes/documentation-sidebar.liquid +112 -0
- data/_includes/figure.liquid +87 -0
- data/_includes/footer.liquid +66 -0
- data/_includes/giscus.liquid +25 -0
- data/_includes/head.liquid +220 -0
- data/_includes/header.liquid +544 -0
- data/_includes/latest_posts.liquid +61 -0
- data/_includes/localized-date.liquid +5 -0
- data/_includes/manual-bibliography.liquid +2 -0
- data/_includes/manual-featured-readings.liquid +12 -0
- data/_includes/manual-other-readings.liquid +12 -0
- data/_includes/manual-page-toc.liquid +11 -0
- data/_includes/manual-sidebar.liquid +58 -0
- data/_includes/manual-teachers.liquid +74 -0
- data/_includes/metadata.liquid +278 -0
- data/_includes/news.liquid +48 -0
- data/_includes/newsletter.liquid +68 -0
- data/_includes/page-hero.liquid +96 -0
- data/_includes/page-link.liquid +8 -0
- data/_includes/pagination.liquid +22 -0
- data/_includes/post-reading-time.liquid +29 -0
- data/_includes/previous-next.liquid +37 -0
- data/_includes/profile-card.liquid +49 -0
- data/_includes/profile-feature-matrix.liquid +75 -0
- data/_includes/profile-highlights.liquid +122 -0
- data/_includes/project-grid.liquid +26 -0
- data/_includes/project-resource-link.liquid +45 -0
- data/_includes/project-resources.liquid +21 -0
- data/_includes/projects.liquid +38 -0
- data/_includes/projects_horizontal.liquid +37 -0
- data/_includes/publications-metrics-summary.liquid +69 -0
- data/_includes/publications-summary.liquid +127 -0
- data/_includes/reading-biblio-controls.liquid +65 -0
- data/_includes/reading-cover-card.liquid +93 -0
- data/_includes/reading-rating.liquid +11 -0
- data/_includes/recommended-readings.liquid +30 -0
- data/_includes/related_posts.liquid +39 -0
- data/_includes/repository/repo.liquid +48 -0
- data/_includes/repository/repo_trophies.liquid +44 -0
- data/_includes/repository/repo_user.liquid +35 -0
- data/_includes/resume/awards.liquid +19 -0
- data/_includes/resume/basics.liquid +28 -0
- data/_includes/resume/certificates.liquid +35 -0
- data/_includes/resume/education.liquid +54 -0
- data/_includes/resume/interests.liquid +34 -0
- data/_includes/resume/languages.liquid +31 -0
- data/_includes/resume/projects.liquid +32 -0
- data/_includes/resume/publications.liquid +28 -0
- data/_includes/resume/references.liquid +31 -0
- data/_includes/resume/skills.liquid +33 -0
- data/_includes/resume/volunteer.liquid +52 -0
- data/_includes/resume/work.liquid +52 -0
- data/_includes/scripts.liquid +364 -0
- data/_includes/search-data.js.liquid +341 -0
- data/_includes/selected_papers.liquid +3 -0
- data/_includes/t.liquid +31 -0
- data/_includes/team-grid.liquid +172 -0
- data/_includes/video.liquid +97 -0
- data/_layouts/about.liquid +93 -0
- data/_layouts/archive.liquid +45 -0
- data/_layouts/bib.liquid +677 -0
- data/_layouts/book-review.liquid +225 -0
- data/_layouts/book-shelf.liquid +66 -0
- data/_layouts/cv.liquid +127 -0
- data/_layouts/default.liquid +70 -0
- data/_layouts/distill.liquid +132 -0
- data/_layouts/documentation-download-detail.liquid +5 -0
- data/_layouts/documentation-home.liquid +100 -0
- data/_layouts/documentation-page.liquid +45 -0
- data/_layouts/manual-bib.liquid +73 -0
- data/_layouts/manual-chapter.liquid +99 -0
- data/_layouts/manual-featured-bib.liquid +100 -0
- data/_layouts/manual-home.liquid +120 -0
- data/_layouts/none.liquid +1 -0
- data/_layouts/outputs.liquid +29 -0
- data/_layouts/page.liquid +52 -0
- data/_layouts/post.liquid +95 -0
- data/_layouts/profile.liquid +36 -0
- data/_layouts/profiles.liquid +36 -0
- data/_layouts/project.liquid +7 -0
- data/_layouts/repositories.liquid +58 -0
- data/_layouts/theses.liquid +126 -0
- data/_plugins/bibliography_profiles.rb +164 -0
- data/_plugins/callouts.rb +104 -0
- data/_plugins/code_blocks.rb +277 -0
- data/_plugins/computation_figure_images.rb +266 -0
- data/_plugins/computation_sources.rb +42 -0
- data/_plugins/content_search_index.rb +210 -0
- data/_plugins/details.rb +23 -0
- data/_plugins/external-posts.rb +124 -0
- data/_plugins/figure_captions.rb +800 -0
- data/_plugins/file-exists.rb +22 -0
- data/_plugins/google-scholar-citations.rb +86 -0
- data/_plugins/hide-custom-bibtex.rb +18 -0
- data/_plugins/inspirehep-citations.rb +57 -0
- data/_plugins/localized_visual_sources.rb +145 -0
- data/_plugins/manual_release_metadata.rb +47 -0
- data/_plugins/mermaid_mmd_images.rb +233 -0
- data/_plugins/profile-pages.rb +28 -0
- data/_plugins/remove-accents.rb +32 -0
- data/_plugins/reproducible_build_time.rb +55 -0
- data/_plugins/search-data.rb +83 -0
- data/_plugins/theme-cache-bust.rb +56 -0
- data/_plugins/vega_visual_images.rb +290 -0
- data/_plugins/web_capture_images.rb +154 -0
- data/_sass/_base.scss +2133 -0
- data/_sass/_blog.scss +67 -0
- data/_sass/_callouts.scss +100 -0
- data/_sass/_custom.scss +437 -0
- data/_sass/_cv.scss +274 -0
- data/_sass/_developer.scss +97 -0
- data/_sass/_distill.scss +185 -0
- data/_sass/_documentation.scss +2220 -0
- data/_sass/_layout.scss +218 -0
- data/_sass/_manual.scss +2691 -0
- data/_sass/_profile.scss +323 -0
- data/_sass/_projects.scss +163 -0
- data/_sass/_reading.scss +465 -0
- data/_sass/_site-custom.scss +3 -0
- data/_sass/_tabs.scss +48 -0
- data/_sass/_team.scss +230 -0
- data/_sass/_themes.scss +254 -0
- data/_sass/_typograms.scss +132 -0
- data/_sass/_variables.scss +52 -0
- data/_sass/font-awesome/_animated.scss +152 -0
- data/_sass/font-awesome/_bordered-pulled.scss +20 -0
- data/_sass/font-awesome/_core.scss +49 -0
- data/_sass/font-awesome/_fixed-width.scss +7 -0
- data/_sass/font-awesome/_functions.scss +57 -0
- data/_sass/font-awesome/_icons.scss +13 -0
- data/_sass/font-awesome/_list.scss +18 -0
- data/_sass/font-awesome/_mixins.scss +65 -0
- data/_sass/font-awesome/_rotated-flipped.scss +31 -0
- data/_sass/font-awesome/_screen-reader.scss +14 -0
- data/_sass/font-awesome/_shims.scss +1578 -0
- data/_sass/font-awesome/_sizing.scss +16 -0
- data/_sass/font-awesome/_stacked.scss +32 -0
- data/_sass/font-awesome/_variables.scss +5044 -0
- data/_sass/font-awesome/brands.scss +30 -0
- data/_sass/font-awesome/fontawesome.scss +21 -0
- data/_sass/font-awesome/regular.scss +27 -0
- data/_sass/font-awesome/solid.scss +27 -0
- data/_sass/font-awesome/v4-shims.scss +11 -0
- data/_sass/tabler-icons/tabler-icons-filled.scss +1646 -0
- data/_sass/tabler-icons/tabler-icons-outline.scss +9859 -0
- data/_sass/tabler-icons/tabler-icons.scss +11463 -0
- data/_scripts/cronitor-analytics-setup.js +9 -0
- data/_scripts/giscus-setup.js +48 -0
- data/_scripts/google-analytics-setup.js +9 -0
- data/_scripts/open-panel-analytics-setup.js +14 -0
- data/_scripts/photoswipe-setup.js +11 -0
- data/assets/audio/epicaly-short-113909.mp3 +0 -0
- data/assets/bibliography/2018-12-22-distill.bib +7 -0
- data/assets/css/academicons.min.css +1 -0
- data/assets/css/bootstrap-toc.min.css +4 -0
- data/assets/css/bootstrap.min.css +7 -0
- data/assets/css/bootstrap.min.css.map +1 -0
- data/assets/css/jekyll-pygments-themes-github.css +209 -0
- data/assets/css/jekyll-pygments-themes-native.css +232 -0
- data/assets/css/jupyter-grade3.css +3758 -0
- data/assets/css/jupyter-monokai.css +3758 -0
- data/assets/css/jupyter.css +383 -0
- data/assets/css/main.scss +36 -0
- data/assets/css/mdb.min.css +48 -0
- data/assets/css/mdb.min.css.map +1 -0
- data/assets/css/scholar-icons.css +386 -0
- data/assets/fonts/academicons.ttf +0 -0
- data/assets/fonts/academicons.woff +0 -0
- data/assets/fonts/scholar-icons.ttf +0 -0
- data/assets/fonts/scholar-icons.woff +0 -0
- data/assets/fonts/tabler-icons-filled.ttf +0 -0
- data/assets/fonts/tabler-icons-filled.woff +0 -0
- data/assets/fonts/tabler-icons-filled.woff2 +0 -0
- data/assets/fonts/tabler-icons-outline.ttf +0 -0
- data/assets/fonts/tabler-icons-outline.woff +0 -0
- data/assets/fonts/tabler-icons-outline.woff2 +0 -0
- data/assets/fonts/tabler-icons.ttf +0 -0
- data/assets/fonts/tabler-icons.woff +0 -0
- data/assets/fonts/tabler-icons.woff2 +0 -0
- data/assets/html/relativity.html +15 -0
- data/assets/img/1.jpg +0 -0
- data/assets/img/10.jpg +0 -0
- data/assets/img/11.jpg +0 -0
- data/assets/img/12.jpg +0 -0
- data/assets/img/2.jpg +0 -0
- data/assets/img/3.jpg +0 -0
- data/assets/img/4.jpg +0 -0
- data/assets/img/5.jpg +0 -0
- data/assets/img/6.jpg +0 -0
- data/assets/img/7.jpg +0 -0
- data/assets/img/8.jpg +0 -0
- data/assets/img/9.jpg +0 -0
- data/assets/img/book_covers/the_godfather.jpg +0 -0
- data/assets/img/brand/dosquartsdedocs-logo-cafe.svg +31 -0
- data/assets/img/brand/dosquartsdedocs-logo-footer-cafe.svg +31 -0
- data/assets/img/brand/dosquartsdedocs-logo-white.svg +31 -0
- data/assets/img/brand/dosquartsdedocs-logo.svg +31 -0
- data/assets/img/prof_pic.jpg +0 -0
- data/assets/img/prof_pic_color.png +0 -0
- data/assets/img/profile-placeholder.svg +8 -0
- data/assets/img/publication_preview/brownian-motion.gif +0 -0
- data/assets/img/publication_preview/goodchild1992-gis-cover.jpg +0 -0
- data/assets/img/publication_preview/gutierrez2020-jtrg-preview.jpg +0 -0
- data/assets/img/publication_preview/harvey1989-postmodernity-cover.jpg +0 -0
- data/assets/img/publication_preview/tobler1970-economic-geography-cover.jpg +0 -0
- data/assets/img/publication_preview/tuan1977-space-place-cover.jpg +0 -0
- data/assets/img/publication_preview/wave-mechanics.gif +0 -0
- data/assets/img/publication_preview/zaragozi2025-rooftop-pv-preview.jpg +0 -0
- data/assets/img/rhino.png +0 -0
- data/assets/img/team/aaron-gutierrez.png +0 -0
- data/assets/img/team/alba-font.png +0 -0
- data/assets/img/team/alba-viana.png +0 -0
- data/assets/img/team/alejandro-gonzalez.png +0 -0
- data/assets/img/team/ana-pastor.png +0 -0
- data/assets/img/team/antoni-domenech.png +0 -0
- data/assets/img/team/benito-zaragozi.png +0 -0
- data/assets/img/team/cinta-sanz.png +0 -0
- data/assets/img/team/daniel-miravet.png +0 -0
- data/assets/img/team/eugenia-altamirano.png +0 -0
- data/assets/img/team/fiammetta-brandajs.png +0 -0
- data/assets/img/team/francesc-gonzalez.png +0 -0
- data/assets/img/team/isabel-paulino.png +0 -0
- data/assets/img/team/joan-borras.png +0 -0
- data/assets/img/team/julie-wilson.png +0 -0
- data/assets/img/team/liliana-sole.png +0 -0
- data/assets/img/team/maria-casado.png +0 -0
- data/assets/img/team/maria-medina.png +0 -0
- data/assets/img/team/marta-nello.png +0 -0
- data/assets/img/team/mogrify +1 -0
- data/assets/img/team/oscar-saladie.png +0 -0
- data/assets/img/team/paolo-russo.png +0 -0
- data/assets/img/team/raquel-santos.png +0 -0
- data/assets/img/team/salvador-anton.png +0 -0
- data/assets/img/team/sunsi-huertas.png +0 -0
- data/assets/img/team/user-placeholder.png +0 -0
- data/assets/img/team/wilbert-den-hoed.png +0 -0
- data/assets/img/team/xavier-delclos.png +0 -0
- data/assets/img/template_error.png +0 -0
- data/assets/js/bibsearch.js +70 -0
- data/assets/js/bootstrap-toc.min.js +5 -0
- data/assets/js/bootstrap.bundle.min.js +7 -0
- data/assets/js/bootstrap.bundle.min.js.map +1 -0
- data/assets/js/callouts.js +115 -0
- data/assets/js/chartjs-setup.js +14 -0
- data/assets/js/common.js +117 -0
- data/assets/js/content-search-match.js +159 -0
- data/assets/js/content-search.js +441 -0
- data/assets/js/copy_code.js +60 -0
- data/assets/js/custom.js +6 -0
- data/assets/js/developer-mode.js +103 -0
- data/assets/js/diff2html-setup.js +20 -0
- data/assets/js/distillpub/overrides.js +27 -0
- data/assets/js/distillpub/template.v2.js +9616 -0
- data/assets/js/distillpub/template.v2.js.map +1 -0
- data/assets/js/distillpub/transforms.v2.js +14557 -0
- data/assets/js/distillpub/transforms.v2.js.map +1 -0
- data/assets/js/documentation.js +435 -0
- data/assets/js/echarts-setup.js +29 -0
- data/assets/js/highlight-search-term.js +110 -0
- data/assets/js/jupyter_new_tab.js +18 -0
- data/assets/js/leaflet-setup.js +22 -0
- data/assets/js/manual.js +308 -0
- data/assets/js/masonry.js +12 -0
- data/assets/js/mathjax-setup.js +46 -0
- data/assets/js/mermaid-setup.js +37 -0
- data/assets/js/newsletter.js +105 -0
- data/assets/js/no_defer.js +24 -0
- data/assets/js/plotly-setup.js +52 -0
- data/assets/js/profile-nav.js +92 -0
- data/assets/js/progress-bar.js +73 -0
- data/assets/js/pseudocode-setup.js +18 -0
- data/assets/js/search/base-styles.min.js +286 -0
- data/assets/js/search/command-score.min.js +7 -0
- data/assets/js/search/hotkeys-js/hotkeys.esm.min.js +18 -0
- data/assets/js/search/lit/decorators.min.js +7 -0
- data/assets/js/search/lit/directives/class-map.min.js +7 -0
- data/assets/js/search/lit/directives/join.min.js +7 -0
- data/assets/js/search/lit/directives/live.min.js +7 -0
- data/assets/js/search/lit/directives/ref.min.js +7 -0
- data/assets/js/search/lit/directives/repeat.min.js +7 -0
- data/assets/js/search/lit/directives/unsafe-html.min.js +7 -0
- data/assets/js/search/lit/index.min.js +7 -0
- data/assets/js/search/lit-element/lit-element.min.js +12 -0
- data/assets/js/search/lit-html/directives/class-map.min.js +22 -0
- data/assets/js/search/lit-html/directives/join.min.js +12 -0
- data/assets/js/search/lit-html/directives/live.min.js +28 -0
- data/assets/js/search/lit-html/directives/ref.min.js +32 -0
- data/assets/js/search/lit-html/directives/repeat.min.js +27 -0
- data/assets/js/search/lit-html/directives/unsafe-html.min.js +22 -0
- data/assets/js/search/lit-html/is-server.min.js +12 -0
- data/assets/js/search/lit-html/lit-html.min.js +12 -0
- data/assets/js/search/ninja-action.min.js +101 -0
- data/assets/js/search/ninja-footer.min.js +62 -0
- data/assets/js/search/ninja-header.min.js +78 -0
- data/assets/js/search/ninja-keys.min.js +39 -0
- data/assets/js/search/reactive-element/decorators/custom-element.min.js +12 -0
- data/assets/js/search/reactive-element/decorators/event-options.min.js +12 -0
- data/assets/js/search/reactive-element/decorators/property.min.js +22 -0
- data/assets/js/search/reactive-element/decorators/query-all.min.js +17 -0
- data/assets/js/search/reactive-element/decorators/query-assigned-elements.min.js +17 -0
- data/assets/js/search/reactive-element/decorators/query-assigned-nodes.min.js +17 -0
- data/assets/js/search/reactive-element/decorators/query-async.min.js +17 -0
- data/assets/js/search/reactive-element/decorators/query.min.js +17 -0
- data/assets/js/search/reactive-element/decorators/state.min.js +27 -0
- data/assets/js/search/reactive-element/reactive-element.min.js +17 -0
- data/assets/js/search-setup.js +17 -0
- data/assets/js/shortcut-key.js +11 -0
- data/assets/js/tabs.min.js +5 -0
- data/assets/js/theme.js +314 -0
- data/assets/js/tooltips-setup.js +3 -0
- data/assets/js/typograms.js +1341 -0
- data/assets/js/vanilla-back-to-top.min.js +1 -0
- data/assets/js/vega-setup.js +24 -0
- data/assets/js/venobox-setup.js +5 -0
- data/assets/js/wechat.js +14 -0
- data/assets/js/zoom.js +15 -0
- data/assets/json/resume.json +98 -0
- data/assets/json/table_data.json +128 -0
- data/assets/jupyter/blog.ipynb +48 -0
- data/assets/pdf/example_pdf.pdf +0 -0
- data/assets/plotly/demo.html +72 -0
- data/assets/video/pexels-engin-akyurt-6069112-960x540-30fps.mp4 +0 -0
- data/assets/webfonts/fa-brands-400.ttf +0 -0
- data/assets/webfonts/fa-brands-400.woff2 +0 -0
- data/assets/webfonts/fa-regular-400.ttf +0 -0
- data/assets/webfonts/fa-regular-400.woff2 +0 -0
- data/assets/webfonts/fa-solid-900.ttf +0 -0
- data/assets/webfonts/fa-solid-900.woff2 +0 -0
- data/assets/webfonts/fa-v4compatibility.ttf +0 -0
- data/assets/webfonts/fa-v4compatibility.woff2 +0 -0
- data/docs/Gemfile +5 -0
- data/docs/_config.yml +83 -0
- data/docs/_documentation/en/01-quick-start.md +115 -0
- data/docs/_documentation/en/02-tools.md +146 -0
- data/docs/_documentation/en/03-usage.md +107 -0
- data/docs/_documentation/en/04-jekyll-basics.md +51 -0
- data/docs/_documentation/en/05-pages-collections.md +68 -0
- data/docs/_documentation/en/06-github-web-editing.md +92 -0
- data/docs/_documentation/en/10-profiles.md +125 -0
- data/docs/_documentation/en/11-unaltreselfie.md +39 -0
- data/docs/_documentation/en/12-unaltreprojecte.md +38 -0
- data/docs/_documentation/en/13-unaltremanual.md +237 -0
- data/docs/_documentation/en/14-unaltredocs.md +92 -0
- data/docs/_documentation/en/15-profile-checklist.md +39 -0
- data/docs/_documentation/en/20-syntax.md +353 -0
- data/docs/_documentation/en/21-themes.md +103 -0
- data/docs/_documentation/en/22-feature-reference.md +56 -0
- data/docs/_documentation/en/23-front-matter.md +51 -0
- data/docs/_documentation/en/24-data-files.md +28 -0
- data/docs/_documentation/en/30-customization.md +448 -0
- data/docs/_documentation/en/31-template.md +55 -0
- data/docs/_documentation/en/32-development.md +108 -0
- data/docs/_documentation/en/33-reusable-workflows.md +136 -0
- data/docs/_documentation/en/40-distribution.md +164 -0
- data/docs/_documentation/en/41-bibliometrics.md +137 -0
- data/docs/_documentation/en/42-docker-image.md +185 -0
- data/docs/_documentation/en/50-faq.md +33 -0
- data/docs/_pages/ca/index.md +35 -0
- data/docs/_pages/en/index.md +35 -0
- data/docs/_pages/es/index.md +35 -0
- data/docs/agents/action-prompts/00-start-site-session.txt +10 -0
- data/docs/agents/action-prompts/05-create-new-web.txt +5 -0
- data/docs/agents/action-prompts/10-content-update.txt +9 -0
- data/docs/agents/action-prompts/15-edit-default-content.txt +8 -0
- data/docs/agents/action-prompts/20-manual-teaching-materials.txt +18 -0
- data/docs/agents/action-prompts/22-manual-style-audit.txt +14 -0
- data/docs/agents/action-prompts/23-manual-structure-audit.txt +17 -0
- data/docs/agents/action-prompts/25-translation-prepublish.txt +8 -0
- data/docs/agents/action-prompts/30-project-site-update.txt +7 -0
- data/docs/agents/action-prompts/40-documentation-update.txt +7 -0
- data/docs/agents/action-prompts/50-bibliography-entry.txt +7 -0
- data/docs/agents/action-prompts/60-bibliometrics-refresh.txt +7 -0
- data/docs/agents/action-prompts/70-build-and-review.txt +12 -0
- data/docs/agents/manual-authoring-components.md +255 -0
- data/docs/agents/mcp-contract.md +162 -0
- data/docs/agents/quarto-computation-adoption.md +102 -0
- data/docs/assets/img/unaltraweb-docs-hero.svg +36 -0
- data/lib/unaltraweb/version.rb +8 -0
- data/lib/unaltraweb.rb +31 -0
- data/requirements.txt +5 -0
- data/scripts/biblio/fetch_scimago_csv.sh +126 -0
- data/scripts/biblio/metrics_common.py +154 -0
- data/scripts/biblio/metrics_merge_meta.py +73 -0
- data/scripts/biblio/metrics_update.py +826 -0
- data/scripts/computations/python/Dockerfile +37 -0
- data/scripts/computations/r/Dockerfile +31 -0
- data/scripts/computations/render.py +1267 -0
- data/scripts/cv/render_pdf_preview.sh +36 -0
- data/scripts/deploy/publish_branch.sh +80 -0
- data/scripts/generate_logo_variants.py +47 -0
- data/scripts/manual/Dockerfile +31 -0
- data/scripts/manual/build_pdf.py +1780 -0
- data/scripts/manual/filters/bibliography.lua +164 -0
- data/scripts/manual/filters/code-blocks.lua +102 -0
- data/scripts/manual/filters/figure-captions.lua +35 -0
- data/scripts/manual/publish_release.sh +281 -0
- data/scripts/manual/templates/manual.tex +494 -0
- data/scripts/manual/verify_release_assets.py +650 -0
- data/scripts/test_gem_build.py +128 -0
- data/scripts/test_reproducible_jekyll_build.py +191 -0
- data/scripts/test_wheel_install.py +282 -0
- data/scripts/unaltraweb-docker-mount.sh +36 -0
- data/scripts/unaltraweb-mcp-bootstrap.sh +105 -0
- data/scripts/unaltraweb-mcp-cleanup.sh +73 -0
- data/scripts/unaltraweb-mcp-project-id.sh +34 -0
- data/scripts/validate_distribution.py +563 -0
- data/scripts/validate_workflows.py +1285 -0
- data/scripts/web_captures/Dockerfile +31 -0
- data/scripts/web_captures/capture.mjs +157 -0
- data/scripts/web_captures/package-lock.json +56 -0
- data/scripts/web_captures/package.json +9 -0
- data/scripts/web_captures/render.py +867 -0
- data/src/unaltraweb_mcp/component-contract.json +153 -0
- data/src/unaltraweb_mcp/component-contract.schema.json +87 -0
- data/src/unaltraweb_mcp/docker_mount.py +19 -0
- metadata +861 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8881f6168982bd26668967e8c6d5baa8b7a02cb3bc6427edf7fdd89169fd8e36
|
|
4
|
+
data.tar.gz: 47457791441af3403defd6e99e621ebde05ada5e5adb50f80ce141db3a80e72c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b870af22e7562818aa3b1a3c45911daaf273cd34ca9f523e05fb995f71f62c44f8222cc9d3457e420683c563c0d675ea6869165d8d6df0100058e4b7d07e9f27
|
|
7
|
+
data.tar.gz: 6c50e56046cb84a0ea06e7690177be1709265a5f4d5422c3605ab600e45ff5926ec776b1c28b8a3b7d27a01b8503c513d3d74f24608514e34a8fc5746b17472b
|
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Maruan Al-Shedivat.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
PYTHON ?= python3
|
|
2
|
+
override PROJECT := $${MCP_CONSUMER_WORKSPACE:?MCP_CONSUMER_WORKSPACE is required}
|
|
3
|
+
override PROJECT_ROOT := $(PROJECT)
|
|
4
|
+
MCP_RUNTIME_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.3.0
|
|
5
|
+
MCP_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-mcp:0.3.0
|
|
6
|
+
MCP_DOCKER_BUILD_NETWORK ?= default
|
|
7
|
+
INIT_SITE_PROFILE ?= unaltreselfie
|
|
8
|
+
NEW_WEB_PROFILE ?= unaltreselfie
|
|
9
|
+
SITE_PROFILE ?=
|
|
10
|
+
SITE_TITLE ?=
|
|
11
|
+
BASEURL ?=
|
|
12
|
+
URL ?=
|
|
13
|
+
DEFAULT_LANG ?=
|
|
14
|
+
LANGUAGES ?=
|
|
15
|
+
METRICS_ARGS ?=
|
|
16
|
+
SCIMAGO_INPUT ?=
|
|
17
|
+
COMPUTE_PYTHON_IMAGE ?=
|
|
18
|
+
COMPUTE_R_IMAGE ?=
|
|
19
|
+
COMPUTE_SOURCE ?=
|
|
20
|
+
COMPUTE_CONFIRM_OVERWRITE ?= 0
|
|
21
|
+
COMPUTE_STALE_ONLY ?= 0
|
|
22
|
+
COMPUTE_MODE ?=
|
|
23
|
+
COMPUTE_SCRIPT := $(CURDIR)/scripts/computations/render.py
|
|
24
|
+
DOCKER_MOUNT_SCRIPT := $(CURDIR)/scripts/unaltraweb-docker-mount.sh
|
|
25
|
+
COMPUTE_PYTHON_LOCAL_IMAGE ?= unaltraweb-compute-python:dev
|
|
26
|
+
COMPUTE_R_LOCAL_IMAGE ?= unaltraweb-compute-r:dev
|
|
27
|
+
COMPUTE_DOCKER_BUILD_NETWORK ?= default
|
|
28
|
+
COMPUTE_CPUS ?= 4
|
|
29
|
+
COMPUTE_MEMORY ?= 8g
|
|
30
|
+
COMPUTE_PIDS_LIMIT ?= 512
|
|
31
|
+
RSTUDIO_PORT ?= 8787
|
|
32
|
+
WEB_CAPTURE_SOURCE ?=
|
|
33
|
+
WEB_CAPTURE_BASE_URL ?=
|
|
34
|
+
WEB_CAPTURE_DOCKER_NETWORK ?=
|
|
35
|
+
WEB_CAPTURE_SERVICE_HOST ?=
|
|
36
|
+
WEB_CAPTURE_CONFIRM_OVERWRITE ?= 0
|
|
37
|
+
WEB_CAPTURE_SCRIPT := $(CURDIR)/scripts/web_captures/render.py
|
|
38
|
+
WEB_CAPTURE_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-web-capture:0.3.0
|
|
39
|
+
WEB_CAPTURE_DEV_IMAGE ?= unaltraweb-web-capture:dev
|
|
40
|
+
WEB_CAPTURE_DOCKER_BUILD_NETWORK ?= default
|
|
41
|
+
VEGAVISUALS_CLI ?=
|
|
42
|
+
DOCKER_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb:0.3.0
|
|
43
|
+
MANUAL_PDF_IMAGE ?= ghcr.io/dosquartsdedocs/unaltraweb-manual-pdf:0.3.0
|
|
44
|
+
MANUAL_PDF_DEV_IMAGE ?= unaltraweb-manual-pdf:dev
|
|
45
|
+
MANUAL_PDF_LANG ?=
|
|
46
|
+
MANUAL_PDF_PUBLISH_DRY_RUN ?= 1
|
|
47
|
+
MANUAL_RELEASE_SELECTOR ?= latest
|
|
48
|
+
MANUAL_RELEASE_DRY_RUN ?= 1
|
|
49
|
+
MANUAL_RELEASE_CONFIRM_PREPARE ?= 0
|
|
50
|
+
override MANUAL_RELEASE_SELECTOR := $(value MANUAL_RELEASE_SELECTOR)
|
|
51
|
+
override MANUAL_RELEASE_DRY_RUN := $(value MANUAL_RELEASE_DRY_RUN)
|
|
52
|
+
override MANUAL_RELEASE_CONFIRM_PREPARE := $(value MANUAL_RELEASE_CONFIRM_PREPARE)
|
|
53
|
+
export MANUAL_RELEASE_SELECTOR
|
|
54
|
+
UNALTRAWEB_WORKER_ROLE ?=
|
|
55
|
+
UNALTRAWEB_WORKER_PROJECT ?=
|
|
56
|
+
UNALTRAWEB_WORKER_TOKEN ?=
|
|
57
|
+
WORKER_LABEL_ARGS = $(if $(strip $(UNALTRAWEB_WORKER_TOKEN)),--label "io.context.mcp-factory=unaltraweb" --label "io.context.mcp-role=$(UNALTRAWEB_WORKER_ROLE)" --label "io.context.mcp-project=$(UNALTRAWEB_WORKER_PROJECT)" --label "io.context.mcp-worker-token=$(UNALTRAWEB_WORKER_TOKEN)",)
|
|
58
|
+
DOCS_CONTAINER ?= unaltraweb-docs-local
|
|
59
|
+
DOCS_HOST ?= 0.0.0.0
|
|
60
|
+
DOCS_PORT ?= 4000
|
|
61
|
+
PUBLISH_REMOTE ?= origin
|
|
62
|
+
PUBLISH_BRANCH ?= gh-pages
|
|
63
|
+
PUBLISH_SOURCE ?= tmp/docs-site
|
|
64
|
+
PUBLISH_WORKTREE ?= tmp/publish-$(PUBLISH_BRANCH)
|
|
65
|
+
PUBLISH_DRY_RUN ?= 0
|
|
66
|
+
LOCAL_UID ?= $(shell id -u)
|
|
67
|
+
LOCAL_GID ?= $(shell id -g)
|
|
68
|
+
|
|
69
|
+
ifneq ($(filter mcp-stdio,$(MAKECMDGOALS)),)
|
|
70
|
+
ifneq ($(origin MCP_CONSUMER_WORKSPACE),environment)
|
|
71
|
+
ifneq ($(origin MCP_CONSUMER_WORKSPACE),environment override)
|
|
72
|
+
$(error MCP_CONSUMER_WORKSPACE must be inherited through the process environment)
|
|
73
|
+
endif
|
|
74
|
+
endif
|
|
75
|
+
endif
|
|
76
|
+
|
|
77
|
+
SCIMAGO_ARGS :=
|
|
78
|
+
ifneq ($(strip $(SCIMAGO_INPUT)),)
|
|
79
|
+
SCIMAGO_ARGS += --input "$(SCIMAGO_INPUT)"
|
|
80
|
+
endif
|
|
81
|
+
|
|
82
|
+
.PHONY: distribution-check distribution-release-check distribution-doctor workflow-check wheel-check gem-check reproducible-site-check docs-build docs-serve docs-publish docs-down metrics-scimago-fetch metrics-update metrics-update-all metrics-check manual-pdf-image manual-pdf-image-dev manual-pdf-preflight manual-pdf-status manual-pdf-check manual-pdf-build manual-pdf-publish manual-pdf-sync manual-release-status manual-release-check manual-release-prepare manual-compute-status manual-compute-check manual-compute-render manual-compute-render-figures manual-compute-image-python manual-compute-image-r manual-compute-images manual-compute-rstudio compute-base-image-python compute-base-image-r web-capture-status web-capture-check web-capture-render web-capture-image visualization-status visualization-check visualization-render
|
|
83
|
+
.PHONY: mcp-runtime-image mcp-image mcp-build mcp-check mcp-smoke mcp-smoke-prebuilt mcp-stdio mcp-down mcp-down-all mcp-list-tools mcp-starter-templates mcp-new-web mcp-initialize-site mcp-site-context mcp-profile-check mcp-manual-source-quality-check mcp-manual-editorial-quality-check mcp-manual-authoring-capabilities mcp-manual-computation-status mcp-manual-computation-check mcp-manual-computation-render mcp-manual-computation-render-figures mcp-web-capture-status mcp-web-capture-check mcp-web-capture-render mcp-manual-pdf-status mcp-manual-pdf-build mcp-manual-pdf-publish mcp-manual-release-status mcp-manual-release-check mcp-manual-release-prepare mcp-profile-prune-plan mcp-profile-prune mcp-content-inventory mcp-language-policy mcp-content-approval-inventory mcp-translation-plan mcp-bibliography-inventory mcp-bibliometrics-check mcp-build-health
|
|
84
|
+
|
|
85
|
+
REPOSITORY_CONTEXT_TARGETS := distribution-doctor manual-compute-status manual-compute-check manual-compute-render manual-compute-render-figures manual-compute-image-python manual-compute-image-r manual-compute-images manual-compute-rstudio web-capture-status web-capture-check web-capture-render visualization-status visualization-check visualization-render manual-pdf-preflight manual-pdf-status manual-pdf-check manual-pdf-build manual-pdf-publish manual-pdf-sync manual-release-status manual-release-check manual-release-prepare metrics-scimago-fetch metrics-update metrics-update-all metrics-check
|
|
86
|
+
$(REPOSITORY_CONTEXT_TARGETS): override PROJECT = $${MCP_CONSUMER_WORKSPACE:-$$PWD}
|
|
87
|
+
$(REPOSITORY_CONTEXT_TARGETS): override PROJECT_ROOT = $${MCP_CONSUMER_WORKSPACE:-$$PWD}
|
|
88
|
+
|
|
89
|
+
distribution-check: ## Validate component/version parity, release selections, and the wheel boundary
|
|
90
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) scripts/validate_distribution.py
|
|
91
|
+
|
|
92
|
+
distribution-release-check: ## Require every selected component to be ready for coordinated publication
|
|
93
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) scripts/validate_distribution.py --require-release-ready
|
|
94
|
+
|
|
95
|
+
distribution-doctor: ## Inspect the selected distribution and PROJECT without network access
|
|
96
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli doctor --project "$(PROJECT)"
|
|
97
|
+
|
|
98
|
+
workflow-check: ## Validate GitHub Actions syntax and publication safety gates
|
|
99
|
+
@$(PYTHON) scripts/validate_workflows.py
|
|
100
|
+
|
|
101
|
+
wheel-check: ## Build and exercise a clean factory-free wheel install
|
|
102
|
+
@$(PYTHON) scripts/test_wheel_install.py
|
|
103
|
+
|
|
104
|
+
gem-check: ## Build the gem and verify its package-owned contract files
|
|
105
|
+
@$(PYTHON) scripts/test_gem_build.py
|
|
106
|
+
|
|
107
|
+
reproducible-site-check: ## Build the same fixed-epoch Jekyll fixture twice and compare every output
|
|
108
|
+
@DOCKER_IMAGE="$(DOCKER_IMAGE)" $(PYTHON) scripts/test_reproducible_jekyll_build.py
|
|
109
|
+
|
|
110
|
+
mcp-runtime-image: ## Build the reusable Jekyll runtime used by the MCP
|
|
111
|
+
docker build --network "$(MCP_DOCKER_BUILD_NETWORK)" -t "$(MCP_RUNTIME_IMAGE)" .
|
|
112
|
+
|
|
113
|
+
mcp-image: mcp-runtime-image ## Build the Dockerized FastMCP control plane
|
|
114
|
+
docker build --network "$(MCP_DOCKER_BUILD_NETWORK)" --build-arg "UNALTRAWEB_RUNTIME_IMAGE=$(MCP_RUNTIME_IMAGE)" -t "$(MCP_IMAGE)" -f Dockerfile.mcp .
|
|
115
|
+
|
|
116
|
+
mcp-build: mcp-image ## Prepare the Docker images used by MCP sessions, builds, and previews
|
|
117
|
+
|
|
118
|
+
mcp-check: mcp-image ## Verify the Dockerized MCP CLI contract
|
|
119
|
+
docker run --rm --entrypoint unaltraweb-mcp "$(MCP_IMAGE)" version
|
|
120
|
+
|
|
121
|
+
mcp-smoke: mcp-build ## Build and prove a real MCP stdio connection
|
|
122
|
+
@$(MAKE) --silent --no-print-directory mcp-smoke-prebuilt MCP_IMAGE="$(MCP_IMAGE)"
|
|
123
|
+
|
|
124
|
+
mcp-smoke-prebuilt: ## Prove a real MCP stdio connection using the selected prebuilt MCP image
|
|
125
|
+
docker run --rm --user "$(LOCAL_UID):$(LOCAL_GID)" -e HOME=/tmp --entrypoint python3 "$(MCP_IMAGE)" /opt/unaltraweb/test/mcp_smoke.py
|
|
126
|
+
@mkdir -p "$(CURDIR)/tmp/mcp-preview-smoke"
|
|
127
|
+
@docker_socket="$${UNALTRAWEB_DOCKER_SOCKET:-/var/run/docker.sock}"; socket_group=$$(stat -c '%g' "$$docker_socket"); \
|
|
128
|
+
image_id=$$(docker image inspect --format '{{.Id}}' "$(MCP_IMAGE)"); \
|
|
129
|
+
socket_mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$$docker_socket" /var/run/docker.sock); \
|
|
130
|
+
project_mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$(CURDIR)/tmp/mcp-preview-smoke" /workspace); \
|
|
131
|
+
docker run --rm --user "$(LOCAL_UID):$(LOCAL_GID)" --group-add "$$socket_group" \
|
|
132
|
+
-e HOME=/tmp -e "UNALTRAWEB_DOCKER_ROOT=$(CURDIR)/tmp/mcp-preview-smoke" \
|
|
133
|
+
-e "UNALTRAWEB_PROJECT_USER=$(LOCAL_UID):$(LOCAL_GID)" -e "UNALTRAWEB_MCP_IMAGE=$$image_id" \
|
|
134
|
+
--mount "$$socket_mount" \
|
|
135
|
+
--mount "$$project_mount" -w /workspace \
|
|
136
|
+
--entrypoint python3 "$$image_id" /opt/unaltraweb/test/mcp_preview_smoke.py
|
|
137
|
+
|
|
138
|
+
mcp-stdio: ## Serve MCP_CONSUMER_WORKSPACE through the Dockerized stdio MCP
|
|
139
|
+
@test -n "$${MCP_CONSUMER_WORKSPACE:-}" || { printf '%s\n' 'MCP_CONSUMER_WORKSPACE is required' >&2; exit 2; }
|
|
140
|
+
@exec "$(CURDIR)/scripts/unaltraweb-mcp-bootstrap.sh" --image "$(MCP_IMAGE)"
|
|
141
|
+
|
|
142
|
+
mcp-down: ## Remove MCP resources owned by MCP_CONSUMER_WORKSPACE or MCP_PROJECT_ID
|
|
143
|
+
@exec "$(CURDIR)/scripts/unaltraweb-mcp-cleanup.sh"
|
|
144
|
+
|
|
145
|
+
mcp-down-all: ## Remove all MCP resources owned by this factory (maintainers only)
|
|
146
|
+
@containers="$$(docker ps -aq --filter "label=io.context.mcp-factory=unaltraweb")" || exit $$?; \
|
|
147
|
+
if [ -n "$$containers" ]; then docker rm -f $$containers || exit $$?; fi; \
|
|
148
|
+
networks="$$(docker network ls -q --filter "label=io.context.mcp-factory=unaltraweb")" || exit $$?; \
|
|
149
|
+
if [ -n "$$networks" ]; then docker network rm $$networks; fi
|
|
150
|
+
|
|
151
|
+
mcp-list-tools: ## List MCP resources, prompts, and tools exposed by this factory
|
|
152
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp list-tools
|
|
153
|
+
|
|
154
|
+
mcp-starter-templates: ## List starter website templates available to initialize PROJECT
|
|
155
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp starter-templates
|
|
156
|
+
|
|
157
|
+
mcp-new-web: ## Create PROJECT from the package-owned scaffold for NEW_WEB_PROFILE
|
|
158
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" new-web --site-profile "$(NEW_WEB_PROFILE)" --title "$(SITE_TITLE)" --baseurl "$(BASEURL)" --url "$(URL)" --default-lang "$(DEFAULT_LANG)" --languages "$(LANGUAGES)"
|
|
159
|
+
|
|
160
|
+
mcp-initialize-site: ## Compatibility alias for package-owned website creation
|
|
161
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp initialize-site --site-profile "$(INIT_SITE_PROFILE)" --title "$(SITE_TITLE)" --baseurl "$(BASEURL)" --url "$(URL)" --default-lang "$(DEFAULT_LANG)" --languages "$(LANGUAGES)"
|
|
162
|
+
|
|
163
|
+
mcp-site-context: ## Print JSON site context for PROJECT
|
|
164
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp site-context
|
|
165
|
+
|
|
166
|
+
mcp-profile-check: ## Print JSON profile contract checks for PROJECT
|
|
167
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp profile-check
|
|
168
|
+
|
|
169
|
+
mcp-manual-source-quality-check: ## Print JSON manual source hygiene checks for PROJECT
|
|
170
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-source-quality-check
|
|
171
|
+
|
|
172
|
+
mcp-manual-editorial-quality-check: ## Print JSON publishable-prose checks for PROJECT
|
|
173
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-editorial-quality-check
|
|
174
|
+
|
|
175
|
+
mcp-manual-authoring-capabilities: ## Print supported manual component syntax and compatibility
|
|
176
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-authoring-capabilities
|
|
177
|
+
|
|
178
|
+
mcp-manual-computation-status: ## Inspect executable manual sources and generated artefacts
|
|
179
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-computation-status --source "$(COMPUTE_SOURCE)"
|
|
180
|
+
|
|
181
|
+
mcp-manual-computation-check: ## Fail when executable manual results are stale
|
|
182
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-computation-check --source "$(COMPUTE_SOURCE)"
|
|
183
|
+
|
|
184
|
+
mcp-manual-computation-render: ## Execute and publish versioned manual computation outputs
|
|
185
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-computation-render --source "$(COMPUTE_SOURCE)" $(if $(filter 1 true TRUE yes YES y Y,$(COMPUTE_CONFIRM_OVERWRITE)),--confirm-overwrite,) $(if $(filter 1 true TRUE yes YES y Y,$(COMPUTE_STALE_ONLY)),--stale-only,)
|
|
186
|
+
|
|
187
|
+
mcp-manual-computation-render-figures: ## Render all stale figure-only computation outputs without touching fresh or unmanaged files
|
|
188
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-computation-render-figures
|
|
189
|
+
|
|
190
|
+
mcp-web-capture-status: ## Inspect web capture recipes and generated artefacts
|
|
191
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp web-capture-status --source "$(WEB_CAPTURE_SOURCE)"
|
|
192
|
+
|
|
193
|
+
mcp-web-capture-check: ## Fail when web capture artefacts are stale
|
|
194
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp web-capture-check --source "$(WEB_CAPTURE_SOURCE)"
|
|
195
|
+
|
|
196
|
+
mcp-web-capture-render: ## Start an isolated preview and publish annotated SVG artefacts
|
|
197
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp web-capture-render --source "$(WEB_CAPTURE_SOURCE)" $(if $(filter 1 true TRUE yes YES y Y,$(WEB_CAPTURE_CONFIRM_OVERWRITE)),--confirm-overwrite,)
|
|
198
|
+
|
|
199
|
+
mcp-manual-pdf-status: ## Inspect manual PDF state for PROJECT
|
|
200
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-pdf-status --language "$(MANUAL_PDF_LANG)"
|
|
201
|
+
|
|
202
|
+
mcp-manual-pdf-build: ## Build the manual PDF for PROJECT
|
|
203
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-pdf-build --language "$(MANUAL_PDF_LANG)"
|
|
204
|
+
|
|
205
|
+
mcp-manual-pdf-publish: ## Dry-run manual PDF publication for PROJECT
|
|
206
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-pdf-publish --language "$(MANUAL_PDF_LANG)"
|
|
207
|
+
|
|
208
|
+
mcp-manual-release-status: ## Inspect local manual release readiness without publishing
|
|
209
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-release-status
|
|
210
|
+
|
|
211
|
+
mcp-manual-release-check: ## Require a current verified local manual release candidate
|
|
212
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-release-check
|
|
213
|
+
|
|
214
|
+
mcp-manual-release-prepare: ## Dry-run local manual release preparation unless explicitly confirmed
|
|
215
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp manual-release-prepare $(if $(filter 0 false FALSE no NO n N,$(MANUAL_RELEASE_DRY_RUN)),--apply,) $(if $(filter 1 true TRUE yes YES y Y,$(MANUAL_RELEASE_CONFIRM_PREPARE)),--confirm-prepare,)
|
|
216
|
+
|
|
217
|
+
mcp-profile-prune-plan: ## Print JSON dry-run prune candidates for the active or selected profile
|
|
218
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp profile-prune-plan --site-profile "$(SITE_PROFILE)"
|
|
219
|
+
|
|
220
|
+
mcp-profile-prune: ## Dry-run profile prune; use the MCP tool with confirm_prune for destructive runs
|
|
221
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp profile-prune --site-profile "$(SITE_PROFILE)"
|
|
222
|
+
|
|
223
|
+
mcp-content-inventory: ## Print JSON content inventory for PROJECT
|
|
224
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp content-inventory
|
|
225
|
+
|
|
226
|
+
mcp-language-policy: ## Print JSON default language and translation workflow settings for PROJECT
|
|
227
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp language-policy
|
|
228
|
+
|
|
229
|
+
mcp-content-approval-inventory: ## Print JSON editorial approval state for PROJECT content
|
|
230
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp content-approval-inventory
|
|
231
|
+
|
|
232
|
+
mcp-translation-plan: ## Print JSON missing translations for approved default-language content
|
|
233
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp translation-plan
|
|
234
|
+
|
|
235
|
+
mcp-bibliography-inventory: ## Print JSON bibliography inventory for PROJECT
|
|
236
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp bibliography-inventory
|
|
237
|
+
|
|
238
|
+
mcp-bibliometrics-check: ## Run the offline bibliometrics check for PROJECT
|
|
239
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp bibliometrics-check
|
|
240
|
+
|
|
241
|
+
mcp-build-health: ## Inspect existing _site build artefacts for PROJECT
|
|
242
|
+
@PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.cli --project "$(PROJECT)" mcp build-health
|
|
243
|
+
|
|
244
|
+
manual-compute-status: ## Inspect executable manual sources and generated artefacts
|
|
245
|
+
@COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" $(PYTHON) "$(COMPUTE_SCRIPT)" status --project "$(PROJECT_ROOT)" $(if $(strip $(COMPUTE_SOURCE)),--source "$(COMPUTE_SOURCE)",) $(if $(strip $(COMPUTE_MODE)),--mode "$(COMPUTE_MODE)",)
|
|
246
|
+
|
|
247
|
+
manual-compute-check: ## Fail when executable manual results are stale
|
|
248
|
+
@COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" $(PYTHON) "$(COMPUTE_SCRIPT)" check --project "$(PROJECT_ROOT)" $(if $(strip $(COMPUTE_SOURCE)),--source "$(COMPUTE_SOURCE)",) $(if $(strip $(COMPUTE_MODE)),--mode "$(COMPUTE_MODE)",)
|
|
249
|
+
|
|
250
|
+
manual-compute-render: ## Execute sources and atomically publish Markdown and figures
|
|
251
|
+
@set -e; \
|
|
252
|
+
runtime_dir="$(PROJECT_ROOT)/tmp/.unaltraweb/computations"; \
|
|
253
|
+
mkdir -p "$$runtime_dir"; runtime_script=$$(mktemp "$$runtime_dir/render.XXXXXX"); cp "$(COMPUTE_SCRIPT)" "$$runtime_script"; \
|
|
254
|
+
results=$$(mktemp); cidfiles=""; trap 'rm -f "$$results" "$$runtime_script" $$cidfiles' EXIT; \
|
|
255
|
+
project_mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$(PROJECT_ROOT)" /project); \
|
|
256
|
+
runtime_mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$$runtime_script" /opt/unaltraweb/computations/render.py readonly); \
|
|
257
|
+
status=$$(COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" $(PYTHON) "$(COMPUTE_SCRIPT)" status --project "$(PROJECT_ROOT)" $(if $(strip $(COMPUTE_SOURCE)),--source "$(COMPUTE_SOURCE)",) $(if $(strip $(COMPUTE_MODE)),--mode "$(COMPUTE_MODE)",)); \
|
|
258
|
+
engines=$$(printf '%s' "$$status" | $(PYTHON) -c 'import json,sys; data=json.load(sys.stdin); print(" ".join(f"{engine}={image}" for engine,image in sorted({(item["engine"], item["image"]["image"]) for item in data["sources"]})))'); \
|
|
259
|
+
for selection in $$engines; do \
|
|
260
|
+
engine=$${selection%%=*}; image=$${selection#*=}; \
|
|
261
|
+
python_image="$(COMPUTE_PYTHON_IMAGE)"; r_image="$(COMPUTE_R_IMAGE)"; \
|
|
262
|
+
if test "$$engine" = "r"; then r_image="$$image"; else python_image="$$image"; fi; \
|
|
263
|
+
if ! docker image inspect "$$image" >/dev/null 2>&1; then \
|
|
264
|
+
COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" COMPUTE_DOCKER_BUILD_NETWORK="$(COMPUTE_DOCKER_BUILD_NETWORK)" $(PYTHON) "$(COMPUTE_SCRIPT)" image --project "$(PROJECT_ROOT)" --engine "$$engine" >/dev/null; \
|
|
265
|
+
fi; \
|
|
266
|
+
identity=$$(docker image inspect "$$image" --format '{{.Id}}'); \
|
|
267
|
+
digest=$$(docker image inspect "$$image" --format '{{join .RepoDigests ","}}'); \
|
|
268
|
+
set --; if test -n "$(UNALTRAWEB_WORKER_TOKEN)"; then cidfile="$$runtime_dir/worker-$(UNALTRAWEB_WORKER_TOKEN)-$$engine.cid"; rm -f "$$cidfile"; cidfiles="$$cidfiles $$cidfile"; set -- --cidfile "$$cidfile"; fi; \
|
|
269
|
+
docker run --rm "$$@" $(WORKER_LABEL_ARGS) --user "$(LOCAL_UID):$(LOCAL_GID)" --network none --read-only --cap-drop ALL --security-opt no-new-privileges --pids-limit "$(COMPUTE_PIDS_LIMIT)" --cpus "$(COMPUTE_CPUS)" --memory "$(COMPUTE_MEMORY)" --tmpfs /tmp:rw,noexec,nosuid,size=1g \
|
|
270
|
+
-e HOME=/tmp -e COMPUTE_PYTHON_IMAGE="$$python_image" -e COMPUTE_R_IMAGE="$$r_image" \
|
|
271
|
+
-e UNALTRAWEB_COMPUTE_IMAGE_ID="$$identity" -e UNALTRAWEB_COMPUTE_IMAGE_DIGEST="$$digest" \
|
|
272
|
+
--mount "$$project_mount" \
|
|
273
|
+
--mount "$$runtime_mount" \
|
|
274
|
+
-w /project --entrypoint python3 "$$image" \
|
|
275
|
+
/opt/unaltraweb/computations/render.py render --project /project --engine "$$engine" $(if $(strip $(COMPUTE_SOURCE)),--source "$(COMPUTE_SOURCE)",) $(if $(filter 1 true TRUE yes YES y Y,$(COMPUTE_CONFIRM_OVERWRITE)),--confirm-overwrite,) $(if $(filter 1 true TRUE yes YES y Y,$(COMPUTE_STALE_ONLY)),--stale-only,) $(if $(strip $(COMPUTE_MODE)),--mode "$(COMPUTE_MODE)",) >> "$$results"; \
|
|
276
|
+
done; \
|
|
277
|
+
if test -z "$(strip $(COMPUTE_SOURCE))"; then $(PYTHON) "$(COMPUTE_SCRIPT)" prune --project "$(PROJECT_ROOT)" >/dev/null; fi; \
|
|
278
|
+
$(PYTHON) -c 'import json,sys; text=open(sys.argv[1], encoding="utf-8").read(); decoder=json.JSONDecoder(); items=[]; index=0; exec("while index < len(text):\n index += len(text[index:]) - len(text[index:].lstrip())\n if index >= len(text): break\n item,index = decoder.raw_decode(text,index)\n items.append(item)"); rendered=[entry for item in items for entry in item.get("rendered", [])]; print(json.dumps({"project":sys.argv[2],"rendered":rendered,"rendered_count":len(rendered),"ok":all(item.get("ok",False) for item in items)}, indent=2))' "$$results" "$(PROJECT_ROOT)"
|
|
279
|
+
|
|
280
|
+
manual-compute-render-figures: override COMPUTE_STALE_ONLY := 1
|
|
281
|
+
manual-compute-render-figures: override COMPUTE_MODE := figure
|
|
282
|
+
manual-compute-render-figures: manual-compute-render ## Render only stale figure-mode computation sources
|
|
283
|
+
|
|
284
|
+
manual-compute-image-python: ## Build or pull the selected Python computation image
|
|
285
|
+
@COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" COMPUTE_DOCKER_BUILD_NETWORK="$(COMPUTE_DOCKER_BUILD_NETWORK)" $(PYTHON) "$(COMPUTE_SCRIPT)" image --project "$(PROJECT_ROOT)" --engine python
|
|
286
|
+
|
|
287
|
+
manual-compute-image-r: ## Build or pull the selected R computation image
|
|
288
|
+
@COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" COMPUTE_DOCKER_BUILD_NETWORK="$(COMPUTE_DOCKER_BUILD_NETWORK)" $(PYTHON) "$(COMPUTE_SCRIPT)" image --project "$(PROJECT_ROOT)" --engine r
|
|
289
|
+
|
|
290
|
+
manual-compute-images: manual-compute-image-python manual-compute-image-r
|
|
291
|
+
|
|
292
|
+
compute-base-image-python: ## Build the reusable local Python computation image
|
|
293
|
+
docker build --network "$(COMPUTE_DOCKER_BUILD_NETWORK)" -f scripts/computations/python/Dockerfile -t "$(COMPUTE_PYTHON_LOCAL_IMAGE)" .
|
|
294
|
+
|
|
295
|
+
compute-base-image-r: ## Build the reusable local R computation image
|
|
296
|
+
docker build --network "$(COMPUTE_DOCKER_BUILD_NETWORK)" -f scripts/computations/r/Dockerfile -t "$(COMPUTE_R_LOCAL_IMAGE)" .
|
|
297
|
+
|
|
298
|
+
manual-compute-rstudio: manual-compute-image-r ## Open the selected R computation image in RStudio Server
|
|
299
|
+
@image=$$(COMPUTE_PYTHON_IMAGE="$(COMPUTE_PYTHON_IMAGE)" COMPUTE_R_IMAGE="$(COMPUTE_R_IMAGE)" $(PYTHON) "$(COMPUTE_SCRIPT)" resolve --project "$(PROJECT_ROOT)" --engine r | $(PYTHON) -c 'import json,sys; print(json.load(sys.stdin)["image"])'); \
|
|
300
|
+
mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$(PROJECT_ROOT)" /home/rstudio/project); \
|
|
301
|
+
docker run --rm -it -p "127.0.0.1:$(RSTUDIO_PORT):8787" -e DISABLE_AUTH=true -e USERID="$(LOCAL_UID)" -e GROUPID="$(LOCAL_GID)" --mount "$$mount" -w /home/rstudio/project "$$image" /init
|
|
302
|
+
|
|
303
|
+
web-capture-status: ## Inspect web capture recipes and generated artefacts
|
|
304
|
+
@WEB_CAPTURE_IMAGE="$(WEB_CAPTURE_IMAGE)" $(PYTHON) "$(WEB_CAPTURE_SCRIPT)" status --project "$(PROJECT_ROOT)" $(if $(strip $(WEB_CAPTURE_SOURCE)),--source "$(WEB_CAPTURE_SOURCE)",)
|
|
305
|
+
|
|
306
|
+
web-capture-check: ## Fail when web capture PNG, SVG, or edited overrides are stale
|
|
307
|
+
@WEB_CAPTURE_IMAGE="$(WEB_CAPTURE_IMAGE)" $(PYTHON) "$(WEB_CAPTURE_SCRIPT)" check --project "$(PROJECT_ROOT)" $(if $(strip $(WEB_CAPTURE_SOURCE)),--source "$(WEB_CAPTURE_SOURCE)",)
|
|
308
|
+
|
|
309
|
+
web-capture-render: ## Capture a trusted running preview and publish PNG plus annotated SVG
|
|
310
|
+
@WEB_CAPTURE_IMAGE="$(WEB_CAPTURE_IMAGE)" WEB_CAPTURE_DOCKER_BUILD_NETWORK="$(WEB_CAPTURE_DOCKER_BUILD_NETWORK)" WEB_CAPTURE_DOCKER_NETWORK="$(WEB_CAPTURE_DOCKER_NETWORK)" WEB_CAPTURE_SERVICE_HOST="$(WEB_CAPTURE_SERVICE_HOST)" $(PYTHON) "$(WEB_CAPTURE_SCRIPT)" render --project "$(PROJECT_ROOT)" --base-url "$(WEB_CAPTURE_BASE_URL)" $(if $(strip $(WEB_CAPTURE_SOURCE)),--source "$(WEB_CAPTURE_SOURCE)",) $(if $(filter 1 true TRUE yes YES y Y,$(WEB_CAPTURE_CONFIRM_OVERWRITE)),--confirm-overwrite,)
|
|
311
|
+
|
|
312
|
+
web-capture-image: ## Build the isolated Playwright web capture image
|
|
313
|
+
docker build --network "$(WEB_CAPTURE_DOCKER_BUILD_NETWORK)" -f scripts/web_captures/Dockerfile -t "$(WEB_CAPTURE_DEV_IMAGE)" .
|
|
314
|
+
|
|
315
|
+
define run_vegavisuals
|
|
316
|
+
@visuals_root="$${VEGAVISUALS_PATH:-$(PROJECT_ROOT)/../vegavisuals}"; visuals_root="$$(realpath -m -- "$$visuals_root")"; \
|
|
317
|
+
if test ! -f "$(PROJECT_ROOT)/.vegavisuals.yml"; then \
|
|
318
|
+
printf '%s\n' 'No .vegavisuals.yml; skipping visualization $(1).'; \
|
|
319
|
+
elif test -n "$(strip $(VEGAVISUALS_CLI))"; then \
|
|
320
|
+
"$(VEGAVISUALS_CLI)" --project "$(PROJECT_ROOT)" $(1); \
|
|
321
|
+
elif test -f "$$visuals_root/src/vegavisuals/cli.py"; then \
|
|
322
|
+
PYTHONPATH="$$visuals_root/src$${PYTHONPATH:+:$$PYTHONPATH}" $(PYTHON) -m vegavisuals.cli --project "$(PROJECT_ROOT)" $(1); \
|
|
323
|
+
elif command -v vegavisuals >/dev/null 2>&1; then \
|
|
324
|
+
vegavisuals --project "$(PROJECT_ROOT)" $(1); \
|
|
325
|
+
else \
|
|
326
|
+
printf '%s\n' 'vegavisuals CLI not found. Set VEGAVISUALS_CLI or VEGAVISUALS_PATH, or install vegavisuals.' >&2; \
|
|
327
|
+
exit 1; \
|
|
328
|
+
fi
|
|
329
|
+
endef
|
|
330
|
+
|
|
331
|
+
visualization-status: ## Report Vega visualization manifest and output freshness when configured
|
|
332
|
+
$(call run_vegavisuals,status)
|
|
333
|
+
|
|
334
|
+
visualization-check: ## Reject stale Vega visualization outputs when configured
|
|
335
|
+
$(call run_vegavisuals,check)
|
|
336
|
+
|
|
337
|
+
visualization-render: ## Render missing or stale Vega visualizations when configured
|
|
338
|
+
$(call run_vegavisuals,render-all)
|
|
339
|
+
|
|
340
|
+
manual-pdf-image: ## Ensure the selected versioned Pandoc/XeLaTeX image is present
|
|
341
|
+
@docker image inspect "$(MANUAL_PDF_IMAGE)" >/dev/null 2>&1 || docker pull "$(MANUAL_PDF_IMAGE)"
|
|
342
|
+
|
|
343
|
+
manual-pdf-image-dev: ## Build the explicitly named maintainer PDF development image
|
|
344
|
+
docker build -f scripts/manual/Dockerfile -t "$(MANUAL_PDF_DEV_IMAGE)" scripts/manual
|
|
345
|
+
|
|
346
|
+
define run_manual_pdf_worker
|
|
347
|
+
@set -e; set --; cidfile=""; \
|
|
348
|
+
if test -n "$(UNALTRAWEB_WORKER_TOKEN)"; then runtime_dir="$(PROJECT_ROOT)/tmp/.unaltraweb/manual-pdf"; mkdir -p "$$runtime_dir"; cidfile="$$runtime_dir/worker-$(UNALTRAWEB_WORKER_TOKEN).cid"; rm -f "$$cidfile"; set -- --cidfile "$$cidfile"; fi; \
|
|
349
|
+
mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$(PROJECT_ROOT)" /project); \
|
|
350
|
+
trap 'test -z "$$cidfile" || rm -f "$$cidfile"' EXIT; \
|
|
351
|
+
docker run --rm "$$@" $(WORKER_LABEL_ARGS) --user "$(LOCAL_UID):$(LOCAL_GID)" -e HOME=/tmp -e "UNALTRAWEB_MANUAL_RELEASE_SELECTOR=$${MANUAL_RELEASE_SELECTOR}" --mount "$$mount" -w /project "$(MANUAL_PDF_IMAGE)" $(1) --project /project $(if $(strip $(MANUAL_PDF_LANG)),--language "$(MANUAL_PDF_LANG)",) $(2)
|
|
352
|
+
endef
|
|
353
|
+
|
|
354
|
+
manual-pdf-preflight: ## Run required PDF gates without contaminating the worker JSON stream
|
|
355
|
+
@$(MAKE) --silent --no-print-directory manual-compute-check >/dev/null
|
|
356
|
+
@$(MAKE) --silent --no-print-directory web-capture-check >/dev/null
|
|
357
|
+
@docker image inspect "$(MANUAL_PDF_IMAGE)" >/dev/null 2>&1 || docker pull "$(MANUAL_PDF_IMAGE)" >/dev/null
|
|
358
|
+
|
|
359
|
+
manual-pdf-status: ## Inspect manual PDF configuration and artefacts without Docker, network, or writes
|
|
360
|
+
@UNALTRAWEB_MANUAL_RELEASE_SELECTOR="$${MANUAL_RELEASE_SELECTOR}" $(PYTHON) "$(CURDIR)/scripts/manual/build_pdf.py" status --project "$(PROJECT_ROOT)" $(if $(strip $(MANUAL_PDF_LANG)),--language "$(MANUAL_PDF_LANG)",)
|
|
361
|
+
|
|
362
|
+
manual-pdf-check: ## Reject stale or unpublished manual PDF artefacts without Docker or network
|
|
363
|
+
@UNALTRAWEB_MANUAL_RELEASE_SELECTOR="$${MANUAL_RELEASE_SELECTOR}" $(PYTHON) "$(CURDIR)/scripts/manual/build_pdf.py" check --project "$(PROJECT_ROOT)" $(if $(strip $(MANUAL_PDF_LANG)),--language "$(MANUAL_PDF_LANG)",)
|
|
364
|
+
|
|
365
|
+
manual-pdf-build: manual-pdf-preflight ## Build manual PDFs and cover previews under tmp
|
|
366
|
+
$(call run_manual_pdf_worker,build)
|
|
367
|
+
|
|
368
|
+
manual-pdf-publish: manual-pdf-preflight ## Copy built PDF artefacts to configured public paths
|
|
369
|
+
$(call run_manual_pdf_worker,publish,$(if $(filter 1 true TRUE yes YES y Y,$(MANUAL_PDF_PUBLISH_DRY_RUN)),--dry-run,))
|
|
370
|
+
|
|
371
|
+
manual-pdf-sync: manual-pdf-preflight ## Build and copy changed manual PDFs to their public paths
|
|
372
|
+
$(call run_manual_pdf_worker,sync)
|
|
373
|
+
|
|
374
|
+
define run_manual_release_worker
|
|
375
|
+
@{ $(MAKE) --silent --no-print-directory manual-pdf-status MANUAL_PDF_LANG= || true; } | \
|
|
376
|
+
UNALTRAWEB_MANUAL_RELEASE_SELECTOR="$${MANUAL_RELEASE_SELECTOR}" PYTHONPATH="$(CURDIR)/src" $(PYTHON) -m unaltraweb_mcp.manual_release $(1) --project "$(PROJECT_ROOT)" $(2)
|
|
377
|
+
endef
|
|
378
|
+
|
|
379
|
+
manual-release-status: ## Inspect release readiness and local candidate state without publishing or writing
|
|
380
|
+
$(call run_manual_release_worker,status)
|
|
381
|
+
|
|
382
|
+
manual-release-check: ## Fail unless the selected local candidate exactly matches verified current outputs
|
|
383
|
+
$(call run_manual_release_worker,check)
|
|
384
|
+
|
|
385
|
+
manual-release-prepare: ## Prepare only a local candidate; defaults to dry-run and never publishes
|
|
386
|
+
$(call run_manual_release_worker,prepare,$(if $(filter 0 false FALSE no NO n N,$(MANUAL_RELEASE_DRY_RUN)),--apply,) $(if $(filter 1 true TRUE yes YES y Y,$(MANUAL_RELEASE_CONFIRM_PREPARE)),--confirm-prepare,))
|
|
387
|
+
|
|
388
|
+
docs-build: visualization-check
|
|
389
|
+
@mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$$PWD" /work); docker run --rm --user "$(LOCAL_UID):$(LOCAL_GID)" -e HOME=/tmp -e BUNDLE_GEMFILE=docs/Gemfile -e BUNDLE_APP_CONFIG=/work/tmp/docs_bundle_config -e BUNDLE_PATH=/work/tmp/docs_bundle_path --mount "$$mount" -w /work $(DOCKER_IMAGE) bash -lc 'git config --global --add safe.directory /work >/dev/null 2>&1 || true; mkdir -p tmp/docs_bundle_config tmp/docs_bundle_path; bundle check || bundle install; core_config=$$(bundle exec ruby -e "spec = Gem::Specification.find_by_name(\"unaltraweb\"); print File.join(spec.full_gem_path, \"_config.yml\")"); bundle exec jekyll build --source docs --destination tmp/docs-site --config "$$core_config,docs/_config.yml" --disable-disk-cache'
|
|
390
|
+
|
|
391
|
+
docs-serve: visualization-check
|
|
392
|
+
-docker rm -f "$(DOCS_CONTAINER)" >/dev/null 2>&1 || true
|
|
393
|
+
@mount=$$(/bin/sh "$(DOCKER_MOUNT_SCRIPT)" "$$PWD" /work); docker run --name "$(DOCS_CONTAINER)" --rm --user "$(LOCAL_UID):$(LOCAL_GID)" -e HOME=/tmp -e BUNDLE_GEMFILE=docs/Gemfile -e BUNDLE_APP_CONFIG=/work/tmp/docs_bundle_config -e BUNDLE_PATH=/work/tmp/docs_bundle_path -p "$(DOCS_PORT):$(DOCS_PORT)" --mount "$$mount" -w /work $(DOCKER_IMAGE) bash -lc 'git config --global --add safe.directory /work >/dev/null 2>&1 || true; mkdir -p tmp/docs_bundle_config tmp/docs_bundle_path; bundle check || bundle install; core_config=$$(bundle exec ruby -e "spec = Gem::Specification.find_by_name(\"unaltraweb\"); print File.join(spec.full_gem_path, \"_config.yml\")"); bundle exec jekyll serve --source docs --destination tmp/docs-site --config "$$core_config,docs/_config.yml" --host $(DOCS_HOST) --port $(DOCS_PORT) --disable-disk-cache'
|
|
394
|
+
|
|
395
|
+
docs-publish: docs-build
|
|
396
|
+
PUBLISH_REMOTE="$(PUBLISH_REMOTE)" PUBLISH_BRANCH="$(PUBLISH_BRANCH)" PUBLISH_SOURCE="$(PUBLISH_SOURCE)" PUBLISH_WORKTREE="$(PUBLISH_WORKTREE)" PUBLISH_DRY_RUN="$(PUBLISH_DRY_RUN)" scripts/deploy/publish_branch.sh
|
|
397
|
+
|
|
398
|
+
docs-down:
|
|
399
|
+
-docker rm -f "$(DOCS_CONTAINER)" >/dev/null 2>&1 || true
|
|
400
|
+
|
|
401
|
+
metrics-scimago-fetch:
|
|
402
|
+
@cd "$(PROJECT_ROOT)" && "$(CURDIR)/scripts/biblio/fetch_scimago_csv.sh" $(SCIMAGO_ARGS) 1>&2 && $(PYTHON) -c 'import json,sys; print(json.dumps({"ok": True, "project": sys.argv[1], "scimago": ".cache/scimago/scimagojr.csv"}, indent=2))' "$(PROJECT_ROOT)"
|
|
403
|
+
|
|
404
|
+
metrics-update:
|
|
405
|
+
@cd "$(PROJECT_ROOT)" && $(PYTHON) "$(CURDIR)/scripts/biblio/metrics_update.py" $(METRICS_ARGS) 1>&2 && $(PYTHON) -c 'import json,sys; print(json.dumps({"ok": True, "project": sys.argv[1], "updated": True}, indent=2))' "$(PROJECT_ROOT)"
|
|
406
|
+
|
|
407
|
+
metrics-update-all:
|
|
408
|
+
@$(MAKE) --silent --no-print-directory metrics-scimago-fetch SCIMAGO_INPUT="$(SCIMAGO_INPUT)" 1>&2
|
|
409
|
+
@$(MAKE) --silent --no-print-directory metrics-update METRICS_ARGS="$(METRICS_ARGS)"
|
|
410
|
+
|
|
411
|
+
metrics-check:
|
|
412
|
+
@cd "$(PROJECT_ROOT)" && $(PYTHON) "$(CURDIR)/scripts/biblio/metrics_update.py" --offline --dry-run $(METRICS_ARGS) 1>&2 && $(PYTHON) -c 'import json,sys; print(json.dumps({"ok": True, "project": sys.argv[1], "offline": True, "dry_run": True}, indent=2))' "$(PROJECT_ROOT)"
|