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
8 changes: 6 additions & 2 deletions src/components/Footer.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import ZDK_logo_dark from "../assets/zdk_logo_full_for_darkmode.svg";
<a
class="link"
href="https://docs.google.com/forms/d/e/1FAIpQLScv0E7IiT1cbdD2fK4IEyI6RojRcYUkWKZBFHSUciCsScn-fQ/viewform"
>お問い合わせ</a
target="_blank">お問い合わせ</a
>
</div>
<div class="footer__logo-container">
<a href="https://www.zdk.tsukuba.ac.jp/" class="footer__logo-link">
<a
href="https://www.zdk.tsukuba.ac.jp/"
target="_blank"
class="footer__logo-link"
>
<picture>
<source
srcset={ZDK_logo_dark.src}
Expand Down
32 changes: 32 additions & 0 deletions src/esa-utils/external-link-replacer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { visit } from "unist-util-visit";
import type { Node } from "hast";
import { isAnchor, type AnchorNode } from "./nodes";

function isExternalLink(href: string): boolean {
/**
* @see https://docs.astro.build/ja/guides/environment-variables/
*/
if (href.startsWith(import.meta.env.SITE)) {
return false;
}
return true;
}

export function externalLinkReplacer() {
const externalLinkNodes: AnchorNode[] = [];
return async (tree: Node) => {
visit(tree, (node) => {
if (isAnchor(node)) {
const { properties } = node;
if (isExternalLink(properties.href)) {
externalLinkNodes.push(node);
}
}
});

for (const node of externalLinkNodes) {
const { properties } = node;
properties.target = "_blank";
}
};
}
14 changes: 10 additions & 4 deletions src/esa-utils/faq-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { Faq } from "./models";
import { unified } from "unified";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";
import { imageReplacer } from "./image-replacer";
import { externalLinkReplacer } from "./external-link-replacer";

function isH2(node: RootContent): node is Heading {
return node.type === "heading" && node.depth === 2;
Expand All @@ -19,7 +21,7 @@ function getString(node: Heading | Paragraph): string {
.join("");
}

export function parseFaqs(ast: Root): Faq[] {
export async function parseFaqs(ast: Root): Promise<Faq[]> {
const faqs: Faq[] = [];

for (let i = 0; i < ast.children.length; ) {
Expand All @@ -45,10 +47,14 @@ export function parseFaqs(ast: Root): Faq[] {
type: "root",
children: answerNodes,
};
const answerHast = unified()
const answerHast = await unified()
.use(remarkRehype, { allowDangerousHtml: true })
.runSync(answerRoot);
const answerHtml = unified().use(rehypeStringify).stringify(answerHast);
.use(imageReplacer)
.use(externalLinkReplacer)
.run(answerRoot);
const answerHtml = unified()
.use(rehypeStringify, { allowDangerousHtml: true })
.stringify(answerHast);
faqs.push({
question: getString(question),
answerHtml,
Expand Down
23 changes: 23 additions & 0 deletions src/esa-utils/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,26 @@ export function isDetailsEnd(node: Node | undefined): node is DetailsNode {
}
return true;
}

export interface AnchorNode extends Node {
type: "element";
tagName: "a";
properties: {
href: string;
target?: string;
rel?: string;
};
}

export function isAnchor(node: Node | undefined): node is AnchorNode {
if (node === undefined) {
return false;
}
if (!(node.type === "element" && "tagName" in node)) {
return false;
}
if (node.tagName !== "a") {
return false;
}
return true;
}
2 changes: 1 addition & 1 deletion src/pages/faq.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import StyledHtml from "../components/StyledHtml.astro";

const faqPost = await fetchPost(import.meta.env.ESA_FAQ_NUMBER);
const faqNodes = unified().use(remarkParse).parse(faqPost.body_md);
const faqs = parseFaqs(faqNodes);
const faqs = await parseFaqs(faqNodes);
console.dir(faqs);

const ids = getUniqueHashes(faqs.map((faq) => faq.question));
Expand Down
2 changes: 2 additions & 0 deletions src/pages/posts/[id].astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { imageReplacer } from "../../esa-utils/image-replacer";
import StyledHtml from "../../components/StyledHtml.astro";
import Toc from "../../components/Toc.astro";
import { detailsContentMarker } from "../../esa-utils/details-content-marker";
import { externalLinkReplacer } from "../../esa-utils/external-link-replacer";

/**
* 動的にページを生成するときに必須の関数
Expand All @@ -36,6 +37,7 @@ const articleHtml = await unified()
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeSlug)
.use(imageReplacer)
.use(externalLinkReplacer)
.use(detailsContentMarker)
.use(rehypeStringify, { allowDangerousHtml: true })
.process(post.body_md);
Expand Down