Skip to content

Footnotes implementation - #78

Open
ralsina wants to merge 15 commits into
icyleaf:masterfrom
ralsina:footnotes
Open

ralsina wants to merge 15 commits into
icyleaf:masterfrom
ralsina:footnotes

Conversation

@ralsina

@ralsina ralsina commented Mar 7, 2025

Copy link
Copy Markdown
Contributor

This is, AFAIK a full implementation of footnotes as per the specs we have on the repo.

@trafico-bot trafico-bot Bot added the 🚧 WIP Still work-in-progress, please don't review and don't merge label Mar 7, 2025
@icyleaf icyleaf mentioned this pull request Mar 9, 2025
7 tasks
@ralsina
ralsina force-pushed the footnotes branch 2 times, most recently from d9a392d to ac17b63 Compare March 13, 2025 23:21
@ralsina ralsina changed the title WIP: Footnotes implementation Basic Footnotes implementation Mar 13, 2025
@trafico-bot trafico-bot Bot added 🔍 Ready for Review Pull Request is not reviewed yet and removed 🚧 WIP Still work-in-progress, please don't review and don't merge labels Mar 13, 2025
@ralsina
ralsina marked this pull request as ready for review March 14, 2025 17:39
@nobodywasishere

Copy link
Copy Markdown
Collaborator

If this is in a stable place, I'm fine to merge this now and sort out the issues in followup PRs.

@ralsina

ralsina commented May 6, 2025

Copy link
Copy Markdown
Contributor Author

It implements some basic cases and doesn't seem to break anything at least :-)

@ralsina

ralsina commented Feb 15, 2026

Copy link
Copy Markdown
Contributor Author

I am working now on finishing this.

@ralsina ralsina changed the title Basic Footnotes implementation Footnotes implementation Feb 15, 2026
@ralsina

ralsina commented Feb 16, 2026

Copy link
Copy Markdown
Contributor Author

Weird, tests were passing before, fixing.

@ralsina

ralsina commented Feb 16, 2026

Copy link
Copy Markdown
Contributor Author

Sigh, I asked the LLM to fix ameba warnings and it choose wrong on every one of them. Fixed now :-)

@nobodywasishere

nobodywasishere commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator

Wonder if the .claude and .vscode folders should be in the .gitignore - how are other projects handling these?

Edit: Same with CLAUDE.md and the like

Comment thread src/markd/parsers/block.cr
@ralsina

ralsina commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

Wonder if the .claude and .vscode folders should be in the .gitignore - how are other projects handling these?

Edit: Same with CLAUDE.md and the like

Deleted and ignored.

@ralsina ralsina closed this Feb 23, 2026
@ralsina ralsina reopened this Feb 23, 2026
@ralsina

ralsina commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

I can't spend any more time working on this PR.

@nobodywasishere

Copy link
Copy Markdown
Collaborator

I can carry it from here if you want.

@ralsina

ralsina commented Feb 23, 2026

Copy link
Copy Markdown
Contributor Author

I can carry it from here if you want.

That would be great, thanks.

@ralsina

ralsina commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

I may have some time to work on markpdf these days if the project is still alive. Is there any problem with this PR?

@ralsina ralsina closed this Aug 12, 2026
@ralsina

ralsina commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Guess it's dead. If someone wants to pick up the footnotes implementation the code is there.

@ralsina

ralsina commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Sorry about the tantrum. Costs me nothing to keep this PR open for whenever someone wants it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements GitHub Flavored Markdown (GFM) footnotes end-to-end in Markd: parsing inline footnote references and block footnote definitions, post-processing to normalize numbering / resolve nested references, and HTML rendering including backrefs.

Changes:

  • Added a new block rule and node types to recognize and store footnote definitions and inline footnote references.
  • Added a post-parse footnote processing pass to resolve references (including nesting), normalize numbering, and move definitions to the end.
  • Implemented HTML output for footnote refs/definitions and enabled fixture-based coverage for the new behavior.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/markd/rules/footnote_definition.cr New block rule to match and collect footnote definition blocks.
src/markd/rule.cr Adds footnote definition start regex and treats [ as “maybe special”.
src/markd/renderers/html_renderer.cr Renders footnote refs/definitions and backrefs; supports valueless (boolean) attributes.
src/markd/renderer.cr Adds abstract renderer hooks for footnote nodes (but currently has a duplicate abstract method).
src/markd/parsers/inline.cr Parses [^label] as a new inline Footnote node in GFM mode.
src/markd/parsers/block.cr Adds passes to parse definition contents as blocks and to resolve/number/move footnotes.
src/markd/node.cr Introduces Footnote / FootnoteDefinition node types and container classification changes.
spec/fixtures/gfm-regression.txt Enables existing regression fixtures that exercise footnotes (including nesting).
spec/fixtures/gfm-extensions.txt Enables GFM extension fixtures for footnotes and escaping behavior.
.vscode/launch.json Removes editor launch configuration from the repo.
.gitignore Ignores spec binary and editor/agent files; broadens VS Code ignore to entire folder.
Suppressed comments (1)

src/markd/parsers/block.cr:156

  • footnote_definitions is deleted from inside footnote_definitions.each, which can raise due to Hash mutation during iteration. Iterate over keys snapshot instead.
          footnote_definitions.delete footnote_title

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/markd/renderer.cr Outdated
Comment thread src/markd/rule.cr Outdated
Comment thread src/markd/parsers/block.cr Outdated
Comment thread src/markd/parsers/block.cr Outdated
Comment thread src/markd/parsers/inline.cr
@icyleaf

icyleaf commented Aug 13, 2026

Copy link
Copy Markdown
Owner

I'll do a first round of review using Copilot first. @nobodywasishere hasn't been active in this project for a while—I wonder if she's been busy since joining the Crystal core team.

@nobodywasishere

Copy link
Copy Markdown
Collaborator

I am still here. Over the past year though have been dealing with a lot of personal stuff, and wrestling with how programming is changing in the advent of AI. Hard to find the joy in doing things if there's a machine that'll do it much faster than you.

@ralsina

ralsina commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

I am still here. Over the past year though have been dealing with a lot of personal stuff, and wrestling with how programming is changing in the advent of AI. Hard to find the joy in doing things if there's a machine that'll do it much faster than you.

Understand the feeling

@ralsina

ralsina commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Tried to accept the fix suggestions but after the 1st one now they are stale :-D

I will get a minion to look at them

ralsina added a commit to ralsina/markd that referenced this pull request Sep 5, 2026
Cover the edge cases from the Copilot review on PR icyleaf#78 that had no
spec coverage:
- [^a](url) keeps the footnote ref and the parentheses as text
  instead of consuming (url) as a link destination
- a mid-line [^x]: does not start a footnote definition
- nested footnote references resolve with arbitrary label characters
icyleaf and others added 11 commits September 5, 2026 21:26
Co-authored-by: Margret Riegert <margret@eowyn.net>
Co-authored-by: Margret Riegert <margret@eowyn.net>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- renderer.cr: remove duplicate thematic_break abstract method declaration
- rule.cr: anchor FOOTNOTE_DEFINITION_START to line start so mid-line
  [^x]: does not incorrectly start a block-level definition
- block.cr: iterate over a snapshot of hash keys instead of mutating
  footnotes/footnote_definitions during each-iteration (fixes potential
  Hash modified during iteration errors)
- block.cr: broaden nested-footnote label regex from [\w-]+ to [^\]]+
  so nested references with arbitrary label characters are detected
- inline.cr: skip inline-link (...) parsing for footnote openers so
  [^a](url) renders as a footnote ref with (url) preserved as text
Cover the edge cases from the Copilot review on PR icyleaf#78 that had no
spec coverage:
- [^a](url) keeps the footnote ref and the parentheses as text
  instead of consuming (url) as a link destination
- a mid-line [^x]: does not start a footnote definition
- nested footnote references resolve with arbitrary label characters
- add spaces around macro expression in Node#to_s
- drop redundant return in Inline#match
@ralsina

ralsina commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Comments addressed, updated from main

The tartrazine require test compile-runs spec/fixtures/tartrazine.cr,
which needs the tartrazine dev dependency, so --without-development
broke spec compilation on every OS in the matrix (same fix the ameba
job already got). Also fix ameba warnings in the fixture itself.
v1.6.4 no longer compiles with current Crystal (undefined method
'next_string_array_token' on Crystal::Lexer). v1.7.0 builds with
Crystal >= 1.19 and passes this repo's .ameba.yml with no changes.
The inline parser tracks positions as byte offsets, but the footnote
label was cut from the text with character-based slicing. Any
multi-byte character earlier in the line (an emoji, an accented
letter) shifted the label: the reference matched no definition and
degraded to literal text like '✅[^]'.

Cut the label with byte_slice instead, and guard it with a regression
fixture covering emoji and accented characters in paragraphs and
table cells.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔍 Ready for Review Pull Request is not reviewed yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants