Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/update-api-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ jobs:
with:
python-version: '3.11'

- name: Read retained Chinese API reference
uses: actions/checkout@v4
with:
ref: gh-pages
path: previous-pages
sparse-checkout: zh/api.html
sparse-checkout-cone-mode: false
persist-credentials: false

- name: Generate API docs
run: python3 scripts/gen_api_docs.py

Expand All @@ -40,6 +49,7 @@ jobs:
python3 web-pages/product-site/build.py --output /tmp/funasr-docs-site
python3 web-pages/product-site/validate.py /tmp/funasr-docs-site
python3 web-pages/product-site/export_docs.py --site /tmp/funasr-docs-site --output gh-pages-output
python3 web-pages/product-site/link_api_guides.py --output gh-pages-output --previous previous-pages

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
Expand Down
46 changes: 46 additions & 0 deletions web-pages/product-site/link_api_guides.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Connect API references to maintained guides without renumbering entries."""

import argparse
from pathlib import Path

from bs4 import BeautifulSoup


def link_api_guides(output: Path, previous: Path) -> None:
rendered = {}
for route, prefix, labels in (
('api.html', 'en/', ('Native Transformers quickstart', 'Python SDK guide')),
('zh/api.html', '', ('原生 Transformers 入门', 'Python SDK 指南')),
):
target = output / route
# The Chinese reference is retained by keep_files, not generated on main.
source = target if target.exists() else previous / route
soup = BeautifulSoup(source.read_text(encoding='utf-8'), 'html.parser')
welcome = soup.select('#api-welcome')
existing = soup.select('#api-practical-guides')
if len(welcome) != 1 or len(existing) > 1:
raise ValueError(f'{route}: expected one api-welcome and at most one guide entry')
if existing:
existing[0].decompose()
guides = soup.new_tag('p', id='api-practical-guides')
for index, (slug, label) in enumerate(zip(('native-transformers', 'python-api'), labels)):
if index:
guides.append(' | ')
link = soup.new_tag('a', href=f'https://www.funasr.com/{prefix}docs/{slug}.html')
link.string = label
guides.append(link)
welcome[0].append(guides)
rendered[target] = str(soup)

# Validate both inputs before changing the outgoing publication directory.
for target, content in rendered.items():
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(content, encoding='utf-8')


if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--output', type=Path, required=True)
parser.add_argument('--previous', type=Path, required=True)
args = parser.parse_args()
link_api_guides(args.output, args.previous)
77 changes: 77 additions & 0 deletions web-pages/product-site/tests/test_api_guide_links.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from pathlib import Path
import sys

from bs4 import BeautifulSoup
import pytest

SITE = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(SITE))


def test_api_guides_preserve_entries_and_localize_destinations(tmp_path):
from link_api_guides import link_api_guides

output, previous = tmp_path / 'output', tmp_path / 'previous'
output.mkdir()
(previous / 'zh').mkdir(parents=True)
original = '<html><body><main><div id="api-welcome"><h2>API</h2></div><div class="api-detail" id="e3"><h2>AutoModel</h2><pre>a &lt; b</pre></div><a href="#e3">AutoModel</a></main><script>const x = "<unchanged>";</script></body></html>'
(output / 'api.html').write_text(original)
(previous / 'zh/api.html').write_text(original)
link_api_guides(output, previous)
first = {}
for route, prefix, label in [('api.html', 'en/', 'Python SDK guide'), ('zh/api.html', '', 'Python SDK 指南')]:
text = (output / route).read_text()
first[route] = text
soup = BeautifulSoup(text, 'html.parser')
before = BeautifulSoup(original, 'html.parser')
assert str(soup.select_one('#e3')) == str(before.select_one('#e3'))
assert soup.script.string == before.script.string
assert soup.select_one('a[href="#e3"]')
links = soup.select('#api-practical-guides a')
assert [a['href'] for a in links] == [
f'https://www.funasr.com/{prefix}docs/native-transformers.html',
f'https://www.funasr.com/{prefix}docs/python-api.html',
]
assert links[1].get_text() == label
link_api_guides(output, previous)
assert all((output / route).read_text() == text for route, text in first.items())
assert (previous / 'zh/api.html').read_text() == original


def test_invalid_legacy_page_does_not_partially_write(tmp_path):
from link_api_guides import link_api_guides

output, previous = tmp_path / 'output', tmp_path / 'previous'
output.mkdir()
(previous / 'zh').mkdir(parents=True)
original = '<div id="api-welcome">API</div>'
(output / 'api.html').write_text(original)
(previous / 'zh/api.html').write_text('<div>No API welcome</div>')
with pytest.raises(ValueError, match='api-welcome'):
link_api_guides(output, previous)
assert (output / 'api.html').read_text() == original
assert not (output / 'zh/api.html').exists()


def test_pages_workflow_restores_only_the_legacy_api_input():
workflow = (SITE.parents[1] / '.github/workflows/update-api-docs.yml').read_text()
assert 'ref: gh-pages' in workflow
assert 'sparse-checkout: zh/api.html' in workflow
assert 'link_api_guides.py --output gh-pages-output --previous previous-pages' in workflow


@pytest.mark.parametrize('bad', [None, '<div id="api-welcome"></div><div id="api-welcome"></div>'])
def test_missing_or_duplicate_legacy_welcome_fails_closed(tmp_path, bad):
from link_api_guides import link_api_guides

output, previous = tmp_path / 'output', tmp_path / 'previous'
output.mkdir()
(previous / 'zh').mkdir(parents=True)
original = '<div id="api-welcome">API</div>'
(output / 'api.html').write_text(original)
if bad is not None:
(previous / 'zh/api.html').write_text(bad)
with pytest.raises((ValueError, FileNotFoundError)):
link_api_guides(output, previous)
assert (output / 'api.html').read_text() == original
assert not (output / 'zh/api.html').exists()
Loading