Merge pull request #1528 from CyC2018/site-verbatim

Update site_assets.py
This commit is contained in:
CyC2018
2026-11-01 19:07:45 +08:00
committed by GitHub
2 changed files with 22 additions and 2 deletions
+16 -2
View File
@@ -18,6 +18,20 @@ IMAGE_SUFFIXES = {'.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.av
PUNCTUATION = re.compile(r'''[\u2000-\u206f\u2e00-\u2e7f\\'!"#$%&()*+,./:;<=>?@\[\]^`{|}~]''')
# 代码块和注释:围栏必须在行首(允许缩进),用同样的字符和至少同样的长度结束。
# 不能用不锚定的 ```...```:正文中的行内代码 ```` ```json ```` 会被当成代码块的开头,吞掉后面的图片引用。
VERBATIM = re.compile(r'^[ \t]*(?P<fence>`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*(?P=fence)[`~]*[ \t]*$|<!--[\s\S]*?-->', re.M)
def split_verbatim(text):
"""按代码块和注释切分:奇数下标是原样保留的部分。"""
parts, last = [], 0
for match in VERBATIM.finditer(text):
parts += [text[last:match.start()], match[0]]
last = match.end()
return parts + [text[last:]]
def plain_text(text):
text = re.sub(r'<!--[\s\S]*?-->', '', text)
text = re.sub(r'<(?:script|style)\b[^>]*>[\s\S]*?</(?:script|style)>', '', text, flags=re.I)
@@ -125,7 +139,7 @@ def write_search_index(dist, paths):
def referenced_paths(content):
content = re.sub(r'```[^\n]*\n[\s\S]*?```|<!--[\s\S]*?-->', '', content)
content = VERBATIM.sub('', content)
for match in re.finditer(r'''\]\((/[^\s)]+)\)|(?:src|href)=["'](/[^"']+)''', content):
url = match[1] or match[2]
if url.startswith(('/#', '//')):
@@ -202,7 +216,7 @@ def optimize_images(dist, cache):
def replace(match):
before, url, after = (match[1], match[2], match[3]) if match[1] else (match[4], match[5], match[6])
return before + mapping.get(url, {}).get('path', url) + after
parts = re.split(r'(```[^\n]*\n[\s\S]*?```|<!--[\s\S]*?-->)', path.read_text())
parts = split_verbatim(path.read_text())
path.write_text(''.join(part if i % 2 else image_pattern.sub(replace, part) for i, part in enumerate(parts)))
(dist / 'image-variants.json').write_text(json.dumps(mapping, ensure_ascii=False, indent=2, sort_keys=True) + '\n')
return {'converted': len(mapping), 'originalBytes': sum(v['originalBytes'] for v in mapping.values()),
+6
View File
@@ -45,6 +45,12 @@ class SearchIndexTests(unittest.TestCase):
content = '<!-- <img src="/secret.png"> -->\n```html\n<img src="/example.png">\n```\n<img src="/notes/pics/actual.png">\n[正文](/notes/示例.md)\n'
self.assertEqual(set(referenced_paths(content)), {'notes/pics/actual.png', 'notes/示例.md'})
def test_inline_triple_backticks_do_not_hide_later_images(self):
# 正文中的行内代码 ```` ```json ```` 不是代码块,后面的图片仍要发布
content = ('例如包在 ```` ```json ```` 代码块里。\n\n<img src="/notes/pics/a.png"/>\n\n'
'- 列表\n\n ```text\n <img src="/notes/pics/in-code.png"/>\n ```\n\n<img src="/notes/pics/b.png"/>\n')
self.assertEqual(set(referenced_paths(content)), {'notes/pics/a.png', 'notes/pics/b.png'})
def test_image_manifest_stable_across_file_creation_order(self):
from PIL import Image
with tempfile.TemporaryDirectory() as directory: