contact messages: {contact: Label} article directive
A lone {contact: Label} line in article Markdown renders a
.contact-trigger button that opens the visitor panel (pagerite.js binds
the click and lazy-loads the contact bundle; inert in the editor
preview, whose resolver now matches the served page). The on-demand
bundle's URLs ride in the pagerite-assets config like langselect's, and
the build gets a contact entry point. Description/card mining renders
resolve the tag to nothing.
This commit is contained in:
1 parent
98c66440f6
commit
776f408743
3 files changed
+58
-19
No files matched your search
@@ -51,6 +51,7 @@ export default defineConfig({
|
||||
pagerite: fileURLToPath(new URL('./src/pagerite.js', import.meta.url)),
|
||||
analytics: fileURLToPath(new URL('./src/analytics-main.js', import.meta.url)),
|
||||
langselect: fileURLToPath(new URL('./src/langselect-main.js', import.meta.url)),
|
||||
contact: fileURLToPath(new URL('./src/contact-main.js', import.meta.url)),
|
||||
// Only the base CSS is built; theme/banner-design stylesheets live
|
||||
// in pagerite/themes/{name}/ and are served by the backend as-is.
|
||||
pagerite_base: fileURLToPath(new URL('./src/assets/pagerite.css', import.meta.url)),
|
||||
|
||||
+11
-11
@@ -544,11 +544,19 @@ async def editor_ws(ws: WebSocket) -> None:
|
||||
markdown = msg.get("markdown", "")
|
||||
chain = resolve(data.menu, path)
|
||||
node = chain[-1] if chain else None
|
||||
# Expand {cards} like page_content does, so the preview
|
||||
has_cards_tag = views._CARDS_TAG_RE.search(markdown) is not None
|
||||
# {contact} buttons preview like the served page (inert);
|
||||
# {cards} expands like page_content does, so the preview
|
||||
# shows real cards, not the literal tag. No translation
|
||||
# context: the preview has no lang of its own, so cards
|
||||
# render in their originals.
|
||||
has_cards_tag = views._CARDS_TAG_RE.search(markdown) is not None
|
||||
directives: dict = {"contact": views._contact_tag}
|
||||
if node is not None and has_cards_tag:
|
||||
directives["cards"] = (
|
||||
lambda args, _env, node=node, path=path: views._cards_tag(
|
||||
data.menu, data, node, path, args
|
||||
)
|
||||
)
|
||||
rendered = render(
|
||||
markdown,
|
||||
path,
|
||||
@@ -565,15 +573,7 @@ async def editor_ws(ws: WebSocket) -> None:
|
||||
if node
|
||||
else None
|
||||
),
|
||||
directives=(
|
||||
{
|
||||
"cards": lambda args, _env, node=node, path=path: (
|
||||
views._cards_tag(data.menu, data, node, path, args)
|
||||
)
|
||||
}
|
||||
if node is not None and has_cards_tag
|
||||
else None
|
||||
),
|
||||
directives=directives,
|
||||
)
|
||||
html = rendered.html
|
||||
if node is not None and not has_cards_tag:
|
||||
|
||||
+46
-8
@@ -415,13 +415,17 @@ def _layout(
|
||||
vite_url = env.vite_url
|
||||
editor_scripts, editor_css = _editor_assets()
|
||||
langselect_scripts, langselect_css = _langselect_assets()
|
||||
contact_scripts, contact_css = _contact_assets()
|
||||
config = {
|
||||
"pagerite:editor-src": editor_scripts[-1],
|
||||
"pagerite:analytics-src": _analytics_assets()[0][0],
|
||||
"pagerite:langselect-src": langselect_scripts[-1],
|
||||
"pagerite:contact-src": contact_scripts[-1],
|
||||
}
|
||||
if langselect_css:
|
||||
config["pagerite:langselect-css"] = ",".join(langselect_css)
|
||||
if contact_css:
|
||||
config["pagerite:contact-css"] = ",".join(contact_css)
|
||||
if editor_css:
|
||||
config["pagerite:editor-css"] = editor_css
|
||||
if vite_url:
|
||||
@@ -900,13 +904,11 @@ def page_content(
|
||||
# A {cards} tag places the card rows itself (possibly several);
|
||||
# without one the children are appended after the content as before.
|
||||
has_cards_tag = _CARDS_TAG_RE.search(content) is not None
|
||||
directives = None
|
||||
directives = {"contact": _contact_tag}
|
||||
if has_cards_tag:
|
||||
directives = {
|
||||
"cards": lambda args, _env: _cards_tag(
|
||||
menu, data, node, path, args, translation, link_lang, lang
|
||||
)
|
||||
}
|
||||
directives["cards"] = lambda args, _env: _cards_tag(
|
||||
menu, data, node, path, args, translation, link_lang, lang
|
||||
)
|
||||
rendered = render(
|
||||
content,
|
||||
path,
|
||||
@@ -984,6 +986,18 @@ def _cards(
|
||||
_CARDS_TAG_RE = re.compile(r"^\{cards(?::[^{}\n]*)?\}[ \t]*$", re.MULTILINE)
|
||||
|
||||
|
||||
def _contact_tag(args: str, _env: dict) -> str:
|
||||
"""Expand a ``{contact: Label}`` directive: the button that opens the
|
||||
visitor contact panel (docs/messages.md). The args are the button
|
||||
label ("Contact us" when empty). pagerite.js binds the click and
|
||||
lazy-loads the panel bundle; in the editor preview it stays inert."""
|
||||
return str(
|
||||
E.button(
|
||||
args.strip() or "Contact us", type="button", class_="contact-trigger"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _cards_tag(
|
||||
menu: dict[str, Node],
|
||||
data: Data,
|
||||
@@ -1123,7 +1137,7 @@ def _card(
|
||||
node.modified,
|
||||
# Card heuristics only mine the prose: nested {cards} rows
|
||||
# would just be noise in the description extraction.
|
||||
directives={"cards": lambda _args, _env: ""},
|
||||
directives={"cards": lambda _args, _env: "", "contact": lambda _a, _e: ""},
|
||||
).html
|
||||
image, _ = _media(html)
|
||||
if not image:
|
||||
@@ -1143,7 +1157,7 @@ def _card(
|
||||
path,
|
||||
node.created,
|
||||
node.modified,
|
||||
directives={"cards": lambda _args, _env: ""},
|
||||
directives={"cards": lambda _args, _env: "", "contact": lambda _a, _e: ""},
|
||||
).html
|
||||
if not large and html:
|
||||
description = _description(html, 150)
|
||||
@@ -1586,6 +1600,30 @@ def _langselect_assets() -> tuple[list[str], list[str]]:
|
||||
return _asset_cache["langselect"]
|
||||
|
||||
|
||||
def _contact_assets() -> tuple[list[str], list[str]]:
|
||||
"""Script and stylesheet URLs for the on-demand contact panel."""
|
||||
vite_url = env.vite_url
|
||||
if vite_url:
|
||||
return [f"{vite_url}/src/contact-main.js"], []
|
||||
if "contact" not in _asset_cache:
|
||||
manifest = _manifest()
|
||||
# import() loads no CSS automatically: collect the stylesheets of
|
||||
# the entry and its imported chunks (same walk as _langselect).
|
||||
scripts, stylesheets, seen = [], [], set()
|
||||
queue = ["src/contact-main.js"]
|
||||
for key in queue: # grows with imported chunks
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
entry = manifest[key]
|
||||
if entry.get("isEntry"):
|
||||
scripts.append(f"/{entry['file']}")
|
||||
stylesheets += [f"/{css}" for css in entry.get("css", [])]
|
||||
queue += entry.get("imports", [])
|
||||
_asset_cache["contact"] = scripts, stylesheets
|
||||
return _asset_cache["contact"]
|
||||
|
||||
|
||||
def render_analytics(
|
||||
menu: dict[str, Node],
|
||||
brand: str = SITE_NAME,
|
||||
|
||||
Reference in new issue
Block a user