Skip to content

Commit 99d0457

Browse files
committed
Initial import
0 parents  commit 99d0457

Some content is hidden

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

66 files changed

+13967
-0
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
.swiftpm
7+
Resources/spec*

LICENSE.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright 2019 Read Evaluate Press, LLC
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a
4+
copy of this software and associated documentation files (the "Software"),
5+
to deal in the Software without restriction, including without limitation
6+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
and/or sell copies of the Software, and to permit persons to whom the
8+
Software is furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
DEALINGS IN THE SOFTWARE.

Makefile

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
COMMONMARK_SPEC_VERSION=0.29
2+
3+
Tests/CommonMarkSpecTests/XCTestManifests.swift: Resources/XCTestManifests.swift.gyb | Tests/CommonMarkSpecTests
4+
@gyb --line-directive '' -o $@ $<; \
5+
6+
Tests/CommonMarkSpecTests: Resources/spec.json | Resources/spec
7+
@mkdir -p $@
8+
@for section in $(shell jq -c '.[].section' $< | uniq); do \
9+
filename=`echo "$${section}" | awk -f Resources/camelcase.awk`; \
10+
jq "map(select(.section == \"$${section}\"))" $< > "$|/$${filename}.json" ; \
11+
gyb --line-directive '' -o $@/$${filename}Tests.swift -D filename="$${filename}" Resources/CommonMarkSpecTests.swift.gyb; \
12+
done
13+
14+
Resources/spec:
15+
@mkdir -p Resources/spec
16+
17+
Resources/spec.json:
18+
@curl "https://spec.commonmark.org/${COMMONMARK_SPEC_VERSION}/spec.json" > $@
19+
20+
%.swift: %.swift.gyb
21+
@gyb --line-directive '' -o $@ $<
22+
23+
.PHONY:
24+
clean:
25+
@rm -f Resources/spec.json
26+
@rm -rf Resources/spec
27+
@rm -rf Tests/CommonMarkSpecTests

Package.resolved

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"object": {
3+
"pins": [
4+
{
5+
"package": "cmark",
6+
"repositoryURL": "https://github.com/apple/swift-cmark.git",
7+
"state": {
8+
"branch": "master",
9+
"revision": "2a766030bee955b4806044fd7aca1b6884475138",
10+
"version": null
11+
}
12+
}
13+
]
14+
},
15+
"version": 1
16+
}

Package.swift

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// swift-tools-version:5.1
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "CommonMark",
8+
products: [
9+
// Products define the executables and libraries produced by a package, and make them visible to other packages.
10+
.library(
11+
name: "CommonMark",
12+
targets: ["CommonMark"]
13+
),
14+
],
15+
dependencies: [
16+
// Dependencies declare other packages that this package depends on.
17+
.package(url: "https://github.com/apple/swift-cmark.git", .branch("master")),
18+
],
19+
targets: [
20+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
21+
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
22+
.target(
23+
name: "CommonMark",
24+
dependencies: ["cmark"]
25+
),
26+
.testTarget(
27+
name: "CommonMarkTests",
28+
dependencies: ["CommonMark"]
29+
),
30+
.testTarget(
31+
name: "CommonMarkSpecTests",
32+
dependencies: ["CommonMark"]
33+
),
34+
]
35+
)

README.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# CommonMark
2+
3+
A Swift package for parsing and rendering [CommonMark][commonmark].
4+
It's built on top of [libcmark][cmark]
5+
and fully compliant with the [CommonMark Spec][commonmark].
6+
7+
```swift
8+
import CommonMark
9+
10+
let markdown = #"""
11+
# [Universal Declaration of Human Rights][uhdr]
12+
13+
## Article 1.
14+
15+
All human beings are born free and equal in dignity and rights.
16+
They are endowed with reason and conscience
17+
and should act towards one another in a spirit of brotherhood.
18+
19+
[uhdr]: https://www.un.org/en/universal-declaration-human-rights/ "View full version"
20+
"""#
21+
22+
let document = try Document(markdown)
23+
24+
25+
// Rendering to HTML, XML, LaTeX, and Manpage
26+
let html = document.render(format: .html) // <h1> [ ... ]
27+
let xml = document.render(format: .xml) // <?xml [ ... ]
28+
let latex = document.render(format: .latex) // \section{ [ ... ]
29+
let manpage = document.render(format: .manpage) // .SH [ ... ]
30+
31+
// To get back CommonMark text,
32+
// you can either render with the `.commonmark` format...
33+
document.render(format: .commonmark) // # [Universal [ ... ]
34+
// ...or call `description`
35+
// (individual nodes also return their CommonMark representation as their description)
36+
document.description // # [Universal [ ... ]
37+
38+
39+
// Inspecting the document tree
40+
document.children.count // 3
41+
42+
let heading = document.children[0] as! Heading
43+
heading.headerLevel // 1
44+
heading.children.count // 1
45+
46+
let link = heading.children[0] as! Link
47+
link.urlString // "https://www.un.org/en/universal-declaration-human-rights/")
48+
link.title // "View full version"
49+
50+
let subheading = document.children[1] as! Heading
51+
subheading.headerLevel // 2
52+
subheading.children.count // 1
53+
54+
let subheadingText = subheading.children[0] as! Text
55+
subheadingText.literal // "Article 1."
56+
57+
let paragraph = document.children[2] as! Paragraph
58+
paragraph.description // "All human beings [ ... ]"
59+
paragraph.range.lowerBound // (line: 5, column: 1)
60+
paragraph.range.upperBound // (line: 7, column: 62)
61+
```
62+
63+
### CommonMark Spec Compliance
64+
65+
This package passes all of the 649 test cases
66+
in the latest version (0.29) of the [CommonMark Spec][commonmark spec]:
67+
68+
```console
69+
$ swift test
70+
Executed 649 tests, with 0 failures (0 unexpected) in 0.178 (0.201) seconds
71+
```
72+
73+
## License
74+
75+
MIT
76+
77+
## Contact
78+
79+
Mattt ([@mattt](https://twitter.com/mattt))
80+
81+
[cmark]: https://github.com/commonmark/cmark
82+
[commonmark]: https://commonmark.org
83+
[commonmark spec]: https://spec.commonmark.org
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
% warning = "This file was automatically generated and should not be edited."
2+
// ${warning}
3+
%{
4+
# encoding=utf8
5+
import sys
6+
reload(sys)
7+
sys.setdefaultencoding('utf8')
8+
9+
import json
10+
11+
def indent(text, amount, ch=' '):
12+
padding = amount * ch
13+
return ''.join(padding+line for line in text.splitlines(True))
14+
}%
15+
16+
import XCTest
17+
import CommonMark
18+
19+
final class CommonMarkSpec${filename}Tests: XCTestCase {
20+
% with open('../Resources/spec/%s.json' % filename) as file:
21+
%{ spec = json.load(file) }%
22+
% for example in spec:
23+
%{
24+
number = example['example']
25+
markdown = example['markdown']
26+
html = example['html'] }%
27+
func testExample${number}() throws {
28+
let markdown = #######"""
29+
${indent(markdown, 8)}
30+
"""#######
31+
32+
let html = #######"""
33+
${indent(html, 8)}
34+
"""#######
35+
36+
let document = try Document(markdown)
37+
XCTAssertEqual(document.render(format: .html, options: [.unsafe]), html)
38+
}
39+
40+
% end
41+
static var allTests = [
42+
% for example in spec:
43+
%{ number = example['example'] }%
44+
("testExample${number}", testExample${number}),
45+
% end
46+
]
47+
% end
48+
}

Resources/XCTestManifests.swift.gyb

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
% warning = "This file was automatically generated and should not be edited."
2+
// ${warning}
3+
%{
4+
# encoding=utf8
5+
import sys
6+
reload(sys)
7+
sys.setdefaultencoding('utf8')
8+
9+
import os
10+
import glob
11+
12+
names = sorted([os.path.basename(f) for f in glob.glob("../Tests/CommonMarkSpecTests/*Tests.swift")])
13+
}%
14+
15+
import XCTest
16+
17+
#if !canImport(ObjectiveC)
18+
public func allTests() -> [XCTestCaseEntry] {
19+
return [
20+
% for name in names:
21+
testCase(${name}.allTests),
22+
% end
23+
]
24+
}
25+
#endif

Resources/camelcase.awk

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/awk -f
2+
3+
{
4+
text = $0;
5+
split(text, words, /[^a-zA-Z]+/);
6+
for (i=1; i<=length(words); i++) {
7+
res = res toupper(substr(words[i],1,1)) tolower(substr(words[i],2));
8+
}
9+
print res
10+
}

Sources/CommonMark/Children.swift

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import cmark
2+
3+
struct Children: Sequence {
4+
var cmark_node: OpaquePointer
5+
6+
init(of node: Node) {
7+
cmark_node = node.cmark_node
8+
}
9+
10+
init(of document: Document) {
11+
cmark_node = document.cmark_node
12+
}
13+
14+
func makeIterator() -> AnyIterator<Node> {
15+
var iterator = CMarkNodeChildIterator(cmark_node)
16+
return AnyIterator {
17+
guard let child = iterator.next() else { return nil }
18+
return Node.create(for: child)
19+
}
20+
}
21+
}
22+
23+
struct CMarkNodeChildIterator: IteratorProtocol {
24+
var current: OpaquePointer!
25+
26+
init(_ node: OpaquePointer!) {
27+
current = cmark_node_first_child(node)
28+
}
29+
30+
mutating func next() -> OpaquePointer? {
31+
guard let next = current else { return nil }
32+
defer { current = cmark_node_next(current) }
33+
return next
34+
}
35+
}

0 commit comments

Comments
 (0)