@@ -968,6 +968,7 @@ $(4)/%.pdf: $(1)/%.adoc .adoc-images-stamp $$(DOC_FONTS) | svgs_made_from_dots
968968 --sourcemap \
969969 -a compat-mode \
970970 -a "doc-languages=$$(LANGUAGES)" \
971+ -a "lcnc-lang=$3" \
971972 -a xref-root=$$(dir $$<) \
972973 -a "xref-exclude=$(2)" \
973974 -a "scriptdir=$$(DOC_SRCDIR)/" \
@@ -1103,36 +1104,40 @@ $(foreach L,$(LANGUAGES),$(eval $(call HTML_COPY_RULE,$(L))))
11031104.images-stamp: .adoc-images-stamp .html-images-stamp
11041105 touch $@
11051106
1106- # Image copy from sources into the output tree. HTML files for English
1107- # live at $(DOC_OUT_HTML)/en/<topic>/X.html; for translations at
1108- # $(DOC_OUT_HTML)/<lang>/<topic>/X.html. The source images are in
1109- # $(DOC_SRCDIR)/<topic>/ regardless of language (translations are
1110- # image-symlinked to English originals via the sed below). Generated SVGs are
1111- # not in src; fall back to the English build tree where they render.
1112- #
1113- # src="..." covers displayed images; href="...png" covers click-to-enlarge
1114- # targets from image:thumb[link=...] (which would otherwise 404). The
1115- # extension filter keeps page/anchor hrefs out.
1107+ # Materialise the shared image pool. image_resolver has already rewritten
1108+ # every HTML src/href to a pool path (image/<srcrel> or <lang>/image/<srcrel>);
1109+ # here we copy each referenced image to the location its link points at. All
1110+ # languages' generic refs resolve to the one shared image/ tree, so the first
1111+ # copy wins and the existence guard skips the rest: no per-language duplication,
1112+ # no symlinks (a server may lack FollowSymLinks), and a no-op second build.
1113+ # DEST comes from the page dir + the ref; <srcrel> finds the source under
1114+ # $(DOC_SRCDIR) (or the English build tree for generated SVGs).
11161115#
11171116# Depend on .lang-switcher-stamp so this runs after the post-processor has
11181117# rewritten the HTML in place; otherwise that later rewrite leaves this stamp
11191118# older than its inputs and the image copy re-fires on every subsequent make.
11201119.html-images-stamp: $(DOC_TARGETS_HTML) .lang-switcher-stamp
1121- set -e; for HTML_FILE in $^; do \
1122- HTML_REL=$$(echo $$HTML_FILE | sed 's%^$(DOC_OUT_HTML)/%%'); \
1123- LANG=$$(echo $$HTML_REL | cut -d/ -f1); \
1124- REST=$$(echo $$HTML_REL | cut -d/ -f2-); \
1125- HTML_DIR=$$(dirname $$REST | cut -d/ -f1); \
1126- for IMAGE_FILE in $$(grep -oE '(src|href)="[^"]+"' $$HTML_FILE | sed -E 's/^(src|href)="//;s/"$$//' | grep -vE '^https?:|^data:|^/|lcnc-docs\.svg' | grep -iE '\.(png|jpe?g|gif|svg|webp)$$'); do \
1127- IMAGE_DIR=$$(dirname $$IMAGE_FILE); \
1128- IMAGE_PATH=$(DOC_SRCDIR)/$$HTML_DIR/$$IMAGE_FILE; \
1129- if [ ! -e $$IMAGE_PATH ] ; then \
1130- IMAGE_PATH=$(DOC_OUT_ADOC)/en/$$HTML_DIR/$$IMAGE_FILE; \
1131- fi; \
1132- mkdir -p $(DOC_OUT_HTML)/$$LANG/$$HTML_DIR/$$IMAGE_DIR; \
1133- cp -f $$IMAGE_PATH $(DOC_OUT_HTML)/$$LANG/$$HTML_DIR/$$IMAGE_FILE; \
1120+ set -e; \
1121+ HTMLROOT=$$(realpath $(DOC_OUT_HTML)); \
1122+ place() { \
1123+ PAGE_DIR=$$(dirname $$1); \
1124+ for REF in $$(grep -oE '(src|href)="[^"]+"' $$1 | sed -E 's/^(src|href)="//;s/"$$//' | grep -vE '^https?:|^data:|^#|^/|lcnc-docs\.svg' | grep -iE '\.(png|jpe?g|gif|svg|webp)$$'); do \
1125+ DEST=$$(realpath -m "$$PAGE_DIR/$$REF"); \
1126+ case $$DEST in $$HTMLROOT/*) ;; *) echo "html-images: out-of-tree $$DEST (page $$1)" >&2; exit 1;; esac; \
1127+ [ -e "$$DEST" ] && continue; \
1128+ REL=$${DEST#$$HTMLROOT/}; \
1129+ case $$REL in \
1130+ image/*) SRCREL=$${REL#image/}; SRC=$(DOC_SRCDIR)/$$SRCREL; [ -e "$$SRC" ] || SRC=$(DOC_OUT_ADOC)/en/$$SRCREL;; \
1131+ */image/*) L=$${REL%%/*}; SRCREL=$${REL#*/image/}; SRC=$(DOC_SRCDIR)/$$SRCREL; [ -e "$$SRC" ] || SRC=$(DOC_OUT_ADOC)/$$L/$$SRCREL;; \
1132+ *) echo "html-images: unexpected pool dest $$REL (page $$1)" >&2; exit 1;; \
1133+ esac; \
1134+ if [ ! -e "$$SRC" ] ; then echo "html-images: no source for $$REL (page $$1)" >&2; exit 1; fi; \
1135+ mkdir -p "$$(dirname "$$DEST")"; \
1136+ cp -f "$$SRC" "$$DEST"; \
11341137 done; \
1135- done > $@.new && mv $@.new $@
1138+ }; \
1139+ for HTML_FILE in $(DOC_TARGETS_HTML); do place $$HTML_FILE; done \
1140+ > $@.new && mv $@.new $@
11361141
11371142# mb2hal_HOWTO.ini lives in the docs source tree next to mb2hal.adoc, so the
11381143# English build includes it directly. Copy it into the per-language build
@@ -1158,10 +1163,12 @@ $(foreach L,$(LANGUAGES),$(eval $(call HTML_COPY_RULE,$(L))))
11581163 cp -f emc/usr_intf/gmoccapy/release_notes.txt $(DOC_OUT_HTML)/$$lang/gui/gmoccapy_release_notes.txt ; \
11591164 done) > $@.new && mv $@.new $@
11601165
1161- # Copy all images used by translated adoc files into the directories
1162- # with translated adoc files. The .translateddocs-stamp prerequisite
1163- # only exists when BUILD_DOCS_TRANSLATED=yes; without it the rule has
1164- # no work to do (filter-out yields empty) so we skip the dep too.
1166+ # Stage the images used by translated adoc files into the translated adoc
1167+ # tree, so asciidoctor-pdf can read them at render time. The .translateddocs-stamp
1168+ # prerequisite only exists when BUILD_DOCS_TRANSLATED=yes; without it the rule
1169+ # has no work to do (filter-out yields empty) so we skip the dep too. HTML
1170+ # image placement is no longer done here: the image_resolver rewrites HTML src
1171+ # to the shared pool and .html-images-stamp materialises it.
11651172ifeq ($(BUILD_DOCS_TRANSLATED),yes)
11661173ADOC_IMAGES_STAMP_DEPS := $(DOC_DIR)/.translateddocs-stamp
11671174endif
@@ -1177,13 +1184,10 @@ endif
11771184 IMAGE_PATH=$(DOC_OUT_ADOC)/en/$$EN_DIR/$$IMAGE_FILE; \
11781185 fi; \
11791186 TIMAGE_PATH=$(DOC_OUT_ADOC)/$$ADOC_DIR/$$IMAGE_FILE; \
1180- HIMAGE_PATH=$(DOC_OUT_HTML)/$$ADOC_DIR/$$IMAGE_FILE; \
11811187 mkdir -p $(DOC_OUT_ADOC)/$$ADOC_DIR/$$IMAGE_DIR; \
1182- mkdir -p $(DOC_OUT_HTML)/$$ADOC_DIR/$$IMAGE_DIR; \
11831188 if [ ! -e $$TIMAGE_PATH ] ; then \
11841189 echo "Generating $$TIMAGE_PATH for $$ADOC_FILE"; \
11851190 cp -f $$IMAGE_PATH $$TIMAGE_PATH; \
1186- cp -f $$IMAGE_PATH $$HIMAGE_PATH; \
11871191 fi ; \
11881192 done; \
11891193 done > $@.new && mv $@.new $@
@@ -1208,13 +1212,20 @@ $(DOC_OUT_ADOC)/en/%.html: LCNC_CSSREL=$(shell python3 -c "print('../' * (1 + '$
12081212# $4 xref-exclude pattern (English filters all lang subdirs; translated
12091213# trees are rooted inside their own lang dir so the exclude is empty).
12101214define ASCIIDOCTOR_HTML_RULE
1211- $$(patsubst %.adoc,$2/%.html,$$(DOC_SRCS_$(call toUC,$1)_SMALL)): $2/%.html: $2/%.adoc $$(DOC_SRCDIR)/docinfo.html $$(DOC_SRCDIR)/docinfo-header.html
1215+ # Order-only dep on .adoc-images-stamp so translated images are staged before
1216+ # the resolver probes for them at render (it also falls back to docs/src).
1217+ $$(patsubst %.adoc,$2/%.html,$$(DOC_SRCS_$(call toUC,$1)_SMALL)): $2/%.html: $2/%.adoc $$(DOC_SRCDIR)/docinfo.html $$(DOC_SRCDIR)/docinfo-header.html | .adoc-images-stamp
12121218 $$(ECHO) "Building '$1' adoc to html: " $$<
12131219 $$(Q)asciidoctor -r $$(realpath $$(DOC_SRCDIR))/extensions/xref_resolver.rb \
1220+ -r $$(realpath $$(DOC_SRCDIR))/extensions/image_resolver.rb \
12141221 -r $$(realpath $$(DOC_SRCDIR))/extensions/rouge_hal.rb \
12151222 -r $$(realpath $$(DOC_SRCDIR))/extensions/rouge_ngc.rb \
12161223 -r $$(realpath $$(DOC_SRCDIR))/extensions/rouge_ini.rb \
12171224 -a compat-mode \
1225+ -a "doc-languages=$$(LANGUAGES)" \
1226+ -a "lcnc-lang=$1" \
1227+ -a "lcnc-srcdir=$$(realpath $$(DOC_SRCDIR))" \
1228+ -a "lcnc-adocdir=$$(realpath $$(DOC_OUT_ADOC))" \
12181229 -a xref-root=$3 \
12191230 -a "xref-exclude=$4" \
12201231 -a "relindir=$$(shell dirname $$*)" \
0 commit comments