Skip to content

Commit 46b03d5

Browse files
author
Release Manager
committed
gh-36742: Plant anchors for hunks to create links in doc preview changes <!-- ^^^^^ Please provide a concise, informative and self-explanatory title. Don't put issue numbers in there, do this in the PR body below. For example, instead of "Fixes #1234" use "Introduce new method to calculate 1+1" --> <!-- Describe your changes here in detail --> The "changes" page of the doc preview of a PR lacks links to the actual changed parts of the doc preview. We plant invisible anchors for each hunk of the diffs and use them to create links to the changed parts. A sample page is https://deploy-preview-36742--sagemath-tobias.netlify.app/changes Wishlist item: In the diffsite comparison view, the left pane showing the doc preview is scrolled to the changed part while the right pane showing the base doc does not. It would be nice if the right pane shows the corresponding part. But this cannot be implemented now because the base doc cannot be altered for specific doc preview for a PR. <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes #12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #36742 Reported by: Kwankyu Lee Reviewer(s): Kwankyu Lee, Matthias Köppe
2 parents 2af5981 + 7b0c670 commit 46b03d5

File tree

2 files changed

+107
-61
lines changed

2 files changed

+107
-61
lines changed

.ci/create-changes-html.sh

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/bin/sh
2+
if [ $# != 2 ]; then
3+
echo >&2 "usage: $0 BASE_DOC_COMMIT DOC_REPO"
4+
echo >&2 "creates CHANGES.html in the current directory"
5+
echo >&2 "for the diffs of DOC_REPO against BASE_DOC_COMMIT"
6+
exit 1
7+
fi
8+
BASE_DOC_COMMIT="$1"
9+
DOC_REPOSITORY="$2"
10+
11+
# Wipe out chronic diffs between old doc and new doc
12+
(cd $DOC_REPOSITORY && find . -name "*.html" | xargs sed -i -e '\;<script type="application/vnd\.jupyter\.widget-state+json">;,\;</script>; d')
13+
# Create CHANGES.html
14+
echo '<html>' > CHANGES.html
15+
echo '<head>' >> CHANGES.html
16+
echo '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">' >> CHANGES.html
17+
echo '<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>' >> CHANGES.html
18+
echo '<script>hljs.highlightAll();</script>' >> CHANGES.html
19+
cat >> CHANGES.html << EOF
20+
<script>
21+
document.addEventListener('DOMContentLoaded', () => {
22+
const diffSite = 'https://pianomister.github.io/diffsite'
23+
const baseDocURL = 'https://sagemath-tobias.netlify.app'
24+
const diffParagraphs = document.querySelectorAll('p.diff');
25+
diffParagraphs.forEach(paragraph => {
26+
const rootURL = window.location.origin;
27+
const docAnchor = paragraph.querySelector('a'); // first "a" element
28+
const url = new URL(docAnchor.href);
29+
const path = url.pathname;
30+
const anchor = document.createElement('a');
31+
anchor.href = diffSite + '/?url1=' + rootURL + path + '&url2=' + baseDocURL + path;
32+
anchor.textContent = 'compare with the base';
33+
anchor.setAttribute('target', '_blank');
34+
paragraph.appendChild(anchor);
35+
paragraph.innerHTML += '&nbsp;';
36+
const hunkAnchors = paragraph.querySelectorAll('a.hunk');
37+
hunkAnchors.forEach(hunkAnchor => {
38+
const url = new URL(hunkAnchor.href);
39+
const path = url.pathname;
40+
const pathHash = path + url.hash.replace('#', '%23');
41+
const anchor = document.createElement('a');
42+
anchor.href = diffSite + '/?url1=' + rootURL + pathHash + '&url2=' + baseDocURL + path;
43+
anchor.textContent = hunkAnchor.textContent;
44+
anchor.setAttribute('target', '_blank');
45+
paragraph.appendChild(anchor);
46+
paragraph.innerHTML += '&nbsp;';
47+
});
48+
});
49+
});
50+
</script>
51+
EOF
52+
echo '</head>' >> CHANGES.html
53+
echo '<body>' >> CHANGES.html
54+
(cd $DOC_REPOSITORY && git diff $BASE_DOC_COMMIT -- *.html) > diff.txt
55+
python3 - << EOF
56+
import os, re, html
57+
with open('diff.txt', 'r') as f:
58+
diff_text = f.read()
59+
diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE)
60+
out_blocks = []
61+
for block in diff_blocks:
62+
match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE)
63+
if match:
64+
doc = match.group(1)
65+
path = 'html/' + doc
66+
file_path = os.path.join('$DOC_REPOSITORY', doc)
67+
with open(file_path, 'r') as file:
68+
content = file.readlines()
69+
count = 0
70+
for line in block.splitlines():
71+
if line.startswith('@@ -'):
72+
line_number = int(re.search(r'@@ -(\d+)', line).group(1))
73+
for i in range(line_number, -1, -1):
74+
if content[i].startswith('<'):
75+
count += 1
76+
content[i] = f'<span id="hunk{count}" style="visibility: hidden;"></span>' + content[i]
77+
break
78+
with open(file_path, 'w') as file:
79+
file.writelines(content)
80+
hunks = '&nbsp;'.join(f'<a href="{path}#hunk{i+1}" class="hunk" target="_blank">#{i + 1}</a>' for i in range(count))
81+
out_blocks.append(f'<p class="diff"><a href="{path}">{doc}</a>&nbsp;' + hunks + '&emsp;</p>'
82+
+ '\n<pre><code class="language-diff">'
83+
+ html.escape(block).strip() + '</code></pre>')
84+
output_text = '\n'.join(out_blocks)
85+
with open('diff.html', 'w') as f:
86+
f.write(output_text)
87+
EOF
88+
cat diff.html >> CHANGES.html
89+
echo '</body>' >> CHANGES.html
90+
echo '</html>' >> CHANGES.html
91+
rm diff.txt diff.html

.github/workflows/doc-build.yml

Lines changed: 16 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ jobs:
6969
-e 's;'"$mathjax_path_from"';'"$mathjax_path_to"';' \
7070
-e '\;<script type="application/vnd\.jupyter\.widget-state+json">;,\;</script>; d')
7171
# Create git repo from old doc
72-
(cd /sage/local/share/doc/sage/html && \
73-
git init && \
72+
DOC_DIR=/sage/local/share/doc/sage/html
73+
(cd $DOC_DIR && git init && \
7474
(echo "*.svg binary"; echo "*.pdf binary") >> .gitattributes && \
7575
(echo ".buildinfo"; echo '*.inv'; echo '.git*'; echo '*.svg'; echo '*.pdf'; echo '*.png'; echo 'searchindex.js') > .gitignore; \
7676
git add -A && git commit --quiet -m "old")
@@ -116,10 +116,11 @@ jobs:
116116
# incremental docbuild may introduce broken links (inter-file references) though build succeeds
117117
run: |
118118
set -ex
119-
export SAGE_USE_CDNS=yes
120-
mv /sage/local/share/doc/sage/html/.git /sage/.git-doc
119+
DOC_DIR=/sage/local/share/doc/sage/html
120+
mv $DOC_DIR/.git /sage/.git-doc
121121
make doc-clean doc-uninstall
122-
mkdir -p /sage/local/share/doc/sage/html/ && mv /sage/.git-doc /sage/local/share/doc/sage/html/.git
122+
mkdir -p $DOC_DIR/ && mv /sage/.git-doc $DOC_DIR/.git
123+
export SAGE_USE_CDNS=yes
123124
./config.status && make sagemath_doc_html-no-deps
124125
working-directory: ./worktree-image
125126
env:
@@ -131,63 +132,17 @@ jobs:
131132
if: (success() || failure()) && steps.docbuild.outcome == 'success'
132133
run: |
133134
set -ex
134-
mkdir -p ./docs
135-
(cd /sage/local/share/doc/sage/html && git commit -a -m 'new')
136-
# Wipe out chronic diffs between old doc and new doc
137-
(cd /sage/local/share/doc/sage/html && \
138-
find . -name "*.html" | xargs sed -i -e '\;<script type="application/vnd\.jupyter\.widget-state+json">;,\;</script>; d')
139-
# Create CHANGES.html
140-
echo '<html>' > ./docs/CHANGES.html
141-
echo '<head>' >> ./docs/CHANGES.html
142-
echo '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">' >> ./docs/CHANGES.html
143-
echo '<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>' >> ./docs/CHANGES.html
144-
echo '<script>hljs.highlightAll();</script>' >> ./docs/CHANGES.html
145-
cat >> ./docs/CHANGES.html << EOF
146-
<script>
147-
document.addEventListener('DOMContentLoaded', () => {
148-
const diffSite = 'https://pianomister.github.io/diffsite/'
149-
const baseDocURL = 'https://sagemath-tobias.netlify.app/'
150-
const diffParagraphs = document.querySelectorAll('p.diff');
151-
diffParagraphs.forEach(paragraph => {
152-
const rootURL = window.location.origin + '/';
153-
const docAnchor = paragraph.querySelector('a');
154-
const path = docAnchor.textContent; // .href doesn't work
155-
const anchor = document.createElement('a');
156-
anchor.href = diffSite + '?url1=' + rootURL + path + '&url2=' + baseDocURL + path;
157-
anchor.textContent = 'compare with the base';
158-
anchor.setAttribute('target', '_blank');
159-
paragraph.appendChild(anchor);
160-
});
161-
});
162-
</script>
163-
EOF
164-
echo '</head>' >> ./docs/CHANGES.html
165-
echo '<body>' >> ./docs/CHANGES.html
166-
(cd /sage/local/share/doc/sage/html && git diff HEAD^ -- *.html; rm -rf .git) > ./docs/diff.txt
167-
/sage/sage -python - << EOF
168-
import re, html
169-
with open('./docs/diff.txt', 'r') as f:
170-
diff_text = f.read()
171-
diff_blocks = re.split(r'^(?=diff --git)', diff_text, flags=re.MULTILINE)
172-
out_blocks = []
173-
for block in diff_blocks:
174-
match = re.search(r'^diff --git a/(.*) b/\1', block, flags=re.MULTILINE)
175-
if match:
176-
path = 'html/' + match.group(1)
177-
out_blocks.append(f'<p class="diff"><a href="{path}">{path}</a>&emsp;</p>\n<pre><code class="language-diff">' + html.escape(block).strip() + '</code></pre>')
178-
output_text = '\n'.join(out_blocks)
179-
with open('./docs/diff.html', 'w') as f:
180-
f.write(output_text)
181-
EOF
182-
cat ./docs/diff.html >> ./docs/CHANGES.html
183-
echo '</body>' >> ./docs/CHANGES.html
184-
echo '</html>' >>./docs/CHANGES.html
185-
rm ./docs/diff.txt ./docs/diff.html
186-
# For some reason the deploy step below cannot find /sage/...
187-
# So copy everything from there to local folder
135+
DOC_DIR=/sage/local/share/doc/sage/html
136+
(cd $DOC_DIR && git commit -a -m 'new')
137+
ls -l /sage/venv/bin
138+
PATH=/sage/venv/bin:$PATH .ci/create-changes-html.sh $(cd $DOC_DIR; git rev-parse HEAD^) $DOC_DIR
139+
(cd $DOC_DIR && rm -rf .git)
140+
# We copy everything to a local folder
188141
# We also need to replace the symlinks because netlify is not following them
189-
cp -r -L /sage/local/share/doc/sage/html ./docs
190-
cp /sage/local/share/doc/sage/index.html ./docs
142+
mkdir -p ./docs
143+
mv CHANGES.html ./docs
144+
cp -r -L $DOC_DIR ./docs
145+
cp $DOC_DIR/../index.html ./docs
191146
# Zip everything for increased performance
192147
zip -r docs.zip docs
193148

0 commit comments

Comments
 (0)