From 8660832a0e2268b22ff286a71c17fdda239ad804 Mon Sep 17 00:00:00 2001 From: tnichols217 <62992267+tnichols217@users.noreply.github.com> Date: Sun, 28 Sep 2025 19:09:15 -0400 Subject: [PATCH] add scripts and fix extension --- src/_quarto.yml | 2 + src/articles/article1.qmd | 2 +- src/articles/tag-articles.py | 40 +++++++++++++++ src/extensions/article-ref/article-ref.lua | 60 ++++++++++++++++++++++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/articles/tag-articles.py create mode 100644 src/extensions/article-ref/article-ref.lua diff --git a/src/_quarto.yml b/src/_quarto.yml index 8825a58..6702517 100755 --- a/src/_quarto.yml +++ b/src/_quarto.yml @@ -35,6 +35,8 @@ brand: dark: brand_dark.yml nocite: | @* +extensions: + - extensions/article-ref format: html: theme-default: dark diff --git a/src/articles/article1.qmd b/src/articles/article1.qmd index 0f64e60..e33e247 100755 --- a/src/articles/article1.qmd +++ b/src/articles/article1.qmd @@ -1,6 +1,6 @@ # Bylaw Structure -## Bylaws as Pertaining to the International Fraternity +## Bylaws as Pertaining to the International Fraternity 1. The Bylaws of Beta Nu Chapter of Theta Chi Fraternity are adopted as provided for in the International Bylaws {{< var acronyms.ibl >}} of Theta Chi Fraternity (Article V, Section 1). 1. The bylaws of this chapter will be superseded by the {{< var acronyms.ibl >}} of Theta Chi Fraternity. diff --git a/src/articles/tag-articles.py b/src/articles/tag-articles.py new file mode 100644 index 0000000..3ab443a --- /dev/null +++ b/src/articles/tag-articles.py @@ -0,0 +1,40 @@ +import os +import re +import random +import string + +# Constants +HEADER_PATTERN = re.compile(r'^(## .+?)(\s*\{#.*\})?\s*$') +TAG_TEMPLATE = ' {#sec-art-%s}' +ID_LENGTH = 8 + +def generate_id() -> str: + return ''.join(random.choices(string.ascii_uppercase + string.digits, k=ID_LENGTH)) + +def process_file(filepath): + changed = False + new_lines = [] + + with open(filepath, 'r', encoding='utf-8') as f: + for line in f: + match = HEADER_PATTERN.match(line) + if match: + header_text, existing_tag = match.groups() + if not existing_tag: + new_tag = TAG_TEMPLATE % generate_id() + line = header_text + new_tag + '\n' + changed = True + new_lines.append(line) + + if changed: + with open(filepath, 'w', encoding='utf-8') as f: + f.writelines(new_lines) + print(f"Updated: {filepath}") + +def main(): + for filename in os.listdir('.'): + if filename.endswith('.qmd'): + process_file(filename) + +if __name__ == '__main__': + main() diff --git a/src/extensions/article-ref/article-ref.lua b/src/extensions/article-ref/article-ref.lua new file mode 100644 index 0000000..4160977 --- /dev/null +++ b/src/extensions/article-ref/article-ref.lua @@ -0,0 +1,60 @@ +local utils = require 'pandoc.utils' +local List = require 'pandoc.List' + +local doc_cache = {} + +-- Extract section numbers from header numbering +local function get_section_number(doc, target_id) + for _, blk in ipairs(doc.blocks) do + if blk.t == "Header" and blk.identifier == target_id then + local num_parts = blk.attr and blk.attr.attributes["number"] + if blk.number and #blk.number > 0 then + return table.concat(blk.number, ".") + end + end + end + return nil +end + +-- Load target document if not already cached +local function load_doc(path) + if doc_cache[path] then + return doc_cache[path] + end + local fh = io.popen("quarto pandoc --to=json " .. path) + local json = fh:read("*a") + fh:close() + local doc = pandoc.read(json, "json") + doc_cache[path] = doc + return doc +end + +-- Main filter function +function Link(el) + local target = el.target + + -- Only process links that match pattern + local file, fragment = string.match(target, "([^#]+)#(sec%-art%-%d+)") + if not file or not fragment then + return nil + end + + local target_doc = load_doc(file) + if not target_doc then + io.stderr:write("Failed to load target file: " .. file .. "\n") + return nil + end + + local section_number = get_section_number(target_doc, fragment) + if not section_number then + return nil + end + + local article_num = file:match("article(%d+)") or "?" + local link_text = string.format("Article %s Section %s", article_num, section_number) + + -- Replace link text + el.content = pandoc.Inlines(pandoc.Str(link_text)) + + return el +end \ No newline at end of file