Skip to content

Commit 46a58bb

Browse files
committed
1.0.81 src - markdown
1 parent a48b7da commit 46a58bb

80 files changed

Lines changed: 17027 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

extras/src/markdown/build.fan

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#! /usr/bin/env fan
2+
//
3+
// Copyright (c) 2024, Brian Frank and Andy Frank
4+
// Licensed under the Academic Free License version 3.0
5+
//
6+
// History:
7+
// 07 Oct 2024 Matthew Giannini Creation
8+
//
9+
10+
using build
11+
12+
**
13+
** Build: markdown
14+
**
15+
class Build : BuildPod
16+
{
17+
new make()
18+
{
19+
podName = "markdown"
20+
summary = "Markdown parsing and rendering"
21+
meta = ["org.name": "Fantom",
22+
"org.uri": "https://fantom.org/",
23+
"proj.name": "Fantom Core",
24+
"proj.uri": "https://fantom.org/",
25+
"license.name": "Academic Free License 3.0",
26+
"vcs.name": "Git",
27+
"vcs.uri": "https://github.com/fantom-lang/fantom"]
28+
depends = ["sys 1.0",
29+
]
30+
srcDirs = [`fan/`,
31+
`fan/ast/`,
32+
`fan/ext/`,
33+
`fan/ext/xetodoc/`,
34+
`fan/ext/gfm-tables/`,
35+
`fan/ext/image-attributes/`,
36+
`fan/parser/`,
37+
`fan/parser/block/`,
38+
`fan/parser/inline/`,
39+
`fan/render/`,
40+
`fan/render/html/`,
41+
`fan/render/markdown/`,
42+
`fan/util/`,
43+
`test/`,
44+
`test/ext/`,
45+
`test/markdown/`,
46+
]
47+
docSrc = true
48+
}
49+
50+
@Target { help = "Compile to pod file" }
51+
override Void compile()
52+
{
53+
codegen
54+
super.compile
55+
}
56+
57+
@Target { help = "Auto-generate HTML5 entities" }
58+
Void codegen()
59+
{
60+
html5 := scriptDir + `fan/util/Html5.fan`
61+
entities := scriptDir + `res/entities.txt`
62+
63+
// short-circuit if the entities file is older than the generated html5 file
64+
if (html5.modified != null && entities.modified != null &&
65+
html5.modified > entities.modified) { return }
66+
67+
src := html5.readAllStr
68+
out := html5.out
69+
inStart := false
70+
lines := src.splitLines
71+
lines.each |line, i|
72+
{
73+
if (inStart && line.contains("/* codegen-end */"))
74+
{
75+
ts := " "
76+
out.writeChars("${ts}private static const [Str:Str] named_char_refs := [\n")
77+
entities.eachLine |entity|
78+
{
79+
if (entity.isEmpty) return
80+
parts := entity.split('=')
81+
out.writeChars("${ts}${ts}${parts[0].toCode}: ${parts[1].toCode},\n")
82+
}
83+
out.writeChars("${ts}${ts}\"NewLine\": \"\\n\",\n")
84+
out.writeChars("${ts}]\n")
85+
out.writeChars("${line}\n")
86+
inStart = false
87+
}
88+
else if (line.contains("/* codegen-start */"))
89+
{
90+
out.writeChars("${line}\n")
91+
inStart = true
92+
}
93+
else if (!inStart)
94+
{
95+
out.writeChars("${line}")
96+
if (i+1 != lines.size) out.writeChar('\n')
97+
}
98+
}
99+
out.close
100+
}
101+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// Copyright (c) 2024, Brian Frank and Andy Frank
3+
// Licensed under the Academic Free License version 3.0
4+
//
5+
// History:
6+
// 01 Nov 2024 Matthew Giannini Creation
7+
//
8+
9+
**
10+
** Mixin for parser/renderer extensions.
11+
**
12+
** Markdown extensions encapsulate all the modifications to the parser/renderer
13+
** to support a given markdown "feature" (e.g. tables, strikethrough, etc.). The are
14+
** registered using the methods on the various builders.
15+
**
16+
@Js
17+
const mixin MarkdownExt
18+
{
19+
** Callback to extend the parser. Default implementation does nothing.
20+
virtual Void extendParser(ParserBuilder builder) { }
21+
22+
** Callback to extend the HTML renderer. Default implementation does nothing.
23+
virtual Void extendHtml(HtmlRendererBuilder builder) { }
24+
25+
** Callback to extend the Markdown renderer. Default implementation does nothing.
26+
virtual Void extendMarkdown(MarkdownRendererBuilder builder) { }
27+
}
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
//
2+
// Copyright (c) 2024, Brian Frank and Andy Frank
3+
// Licensed under the Academic Free License version 3.0
4+
//
5+
// History:
6+
// 08 Oct 2024 Matthew Giannini Creation
7+
//
8+
9+
**
10+
** A block node.
11+
**
12+
** We can think of a document as a sequence of blocks - structural
13+
** elements like paragraphs, block quotations, lists, headings, rules,
14+
** and code blocks. Some blocks contain other blocks; others contain
15+
** inline content (text, images, code spans, etc.).
16+
**
17+
@Js
18+
abstract class Block : Node
19+
{
20+
override Block? parent() { super.parent }
21+
22+
protected override Void setParent(Node? p)
23+
{
24+
if (p isnot Block)
25+
throw ArgErr("Parent of block must also be a block")
26+
super.setParent(p)
27+
}
28+
}
29+
30+
**************************************************************************
31+
** Document
32+
**************************************************************************
33+
34+
** Document is the root node of the AST
35+
@Js
36+
final class Document : Block { }
37+
38+
**************************************************************************
39+
** Heading
40+
**************************************************************************
41+
42+
** Heading block
43+
@Js
44+
class Heading : Block
45+
{
46+
new make(Int level := 0) { this.level = level }
47+
48+
** The heading "level"
49+
const Int level
50+
}
51+
52+
**************************************************************************
53+
** BlockQuote
54+
**************************************************************************
55+
56+
** Block quote block
57+
@Js
58+
class BlockQuote : Block { }
59+
60+
**************************************************************************
61+
** FencedCode
62+
**************************************************************************
63+
64+
** Fenced code block
65+
@Js
66+
class FencedCode : Block
67+
{
68+
new make(Str? fenceChar := null)
69+
{
70+
this.fenceChar = fenceChar
71+
}
72+
73+
** The fence character that was used, e.g. '`', or '~', if available, or null otherwise
74+
Str? fenceChar
75+
76+
Int fenceIndent := 0
77+
78+
** The length of the opening fence (how many of the `fenceChar` were used to start
79+
** the code block) if available, or null otherwise
80+
Int? openingFenceLen
81+
{
82+
set {
83+
if (it != null && it < 3) throw ArgErr("openingFenceLen needs to be >= 3")
84+
checkFenceLens(it, closingFenceLen)
85+
&openingFenceLen = it
86+
}
87+
}
88+
89+
** The length of the closing fence (how many of the `fenceChar` were used to end
90+
** the code block) if available, or null otherwise
91+
Int? closingFenceLen
92+
{
93+
set {
94+
if (it != null && it < 3) throw ArgErr("closingFenceLen needs to be >= 3")
95+
checkFenceLens(openingFenceLen, it)
96+
&closingFenceLen = it
97+
}
98+
}
99+
100+
** Optional info string (see spec), e.g. 'fantom' in '```fantom'
101+
Str? info
102+
103+
Str? literal
104+
105+
private static Void checkFenceLens(Int? openingFenceLen, Int? closingFenceLen)
106+
{
107+
if (openingFenceLen != null && closingFenceLen != null)
108+
{
109+
if (closingFenceLen < openingFenceLen)
110+
throw ArgErr("fence lengths required to be: closingFenceLen >= openingFenceLen")
111+
}
112+
}
113+
}
114+
115+
**************************************************************************
116+
** HtmlBlock
117+
**************************************************************************
118+
119+
** HTML block
120+
@Js
121+
class HtmlBlock : Block
122+
{
123+
new make(Str? literal := null) { this.literal = literal }
124+
125+
Str? literal
126+
}
127+
128+
**************************************************************************
129+
** ThematicBreak
130+
**************************************************************************
131+
132+
** Thematic break block
133+
@Js
134+
class ThematicBreak : Block
135+
{
136+
new make(Str? literal := null) { this.literal = literal }
137+
138+
** source literal that represents this break, if available
139+
Str? literal
140+
}
141+
142+
**************************************************************************
143+
** IndentedCode
144+
**************************************************************************
145+
146+
** Indented code block
147+
@Js
148+
class IndentedCode : Block
149+
{
150+
new make(Str? literal := null) { this.literal = literal }
151+
152+
** Indented code literal
153+
Str? literal
154+
}
155+
156+
** Abstract base class for list blocks
157+
@Js
158+
abstract class ListBlock : Block
159+
{
160+
** Whether this list is tight or loose
161+
**
162+
** spec: A list is loose if any of its constituent list items are separated by blank
163+
** lines, or if any of its constituent list items directly contain two block-level
164+
** elements with a blank line between them. Otherwise, a list is tight.
165+
** (The difference in HTML output is that paragraphs in a loose list are
166+
** wrapped in <p> tags, while paragraphs in a tight list are not.)
167+
Bool tight := false
168+
}
169+
170+
**************************************************************************
171+
** BulletList
172+
**************************************************************************
173+
174+
** Bullet list block
175+
@Js
176+
class BulletList : ListBlock
177+
{
178+
new make(Str? marker := null) { this.marker = marker }
179+
180+
** The bullet list marker that was used, e.g. '-', '*', or '+', if available,
181+
** or null otherwise.
182+
Str? marker
183+
}
184+
185+
**************************************************************************
186+
** OrderedList
187+
**************************************************************************
188+
189+
** Ordered list block
190+
@Js
191+
class OrderedList : ListBlock
192+
{
193+
new make(Int? startNumber, Str? markerDelim)
194+
{
195+
this.startNumber = startNumber
196+
this.markerDelim = markerDelim
197+
}
198+
199+
** The start number used in the marker, e.g. '1', if available, or null otherwise
200+
Int? startNumber
201+
202+
** The delimiter used in the marker, e.g. '.' or ')', if available, or null otherwise
203+
Str? markerDelim
204+
}
205+
206+
**************************************************************************
207+
** ListItem
208+
**************************************************************************
209+
210+
** List item
211+
@Js
212+
class ListItem : Block
213+
{
214+
new make(Int? markerIndent, Int? contentIndent)
215+
{
216+
this.markerIndent = markerIndent
217+
this.contentIndent = contentIndent
218+
}
219+
220+
** The indent of the marker such as '-' or '1.' in columns (spaces or tab stop of 4)
221+
** if available, or null otherwise.
222+
**
223+
** - '- Foo' (marker indent: 0)
224+
** - ' - Foo' (marker indent: 1)
225+
** - ' 1. Foo' (marker indent: 2)
226+
Int? markerIndent
227+
228+
** The indent of the content in columns (spaces or tab stop of 4) if available
229+
** or null otherwise. The content indent is counted from the beginning of the line
230+
** and includes the marker on the first line
231+
**
232+
** - '- Foo' (content indent: 2)
233+
** - ' - Foo' (content indent: 3)
234+
** - ' 1. Foo' (content indent: 5)
235+
**
236+
** Note that subsequent lines in the same list item need to be indented by at least
237+
** the content indent to be counted as part of the list item.
238+
Int? contentIndent
239+
}
240+
241+
**************************************************************************
242+
** Paragraph
243+
**************************************************************************
244+
245+
** Paragraph
246+
@Js
247+
class Paragraph : Block { }
248+
249+
**************************************************************************
250+
** CustomBlock
251+
**************************************************************************
252+
253+
** Custom Block
254+
@Js
255+
abstract class CustomBlock : Block { }

0 commit comments

Comments
 (0)