From d815c5f7c34b79ce204256f4496e95a021bc4c59 Mon Sep 17 00:00:00 2001 From: Michael Housh Date: Thu, 30 Jan 2025 21:33:22 -0500 Subject: [PATCH] feat: Initial commit --- .editorconfig | 7 ++ .gitignore | 8 ++ .swiftformat | 11 +++ .swiftlint.yml | 11 +++ Package.resolved | 42 ++++++++++ Package.swift | 20 +++++ Sources/main.swift | 190 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 289 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .swiftformat create mode 100644 .swiftlint.yml create mode 100644 Package.resolved create mode 100644 Package.swift create mode 100644 Sources/main.swift diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7cfbe01 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*.swift] +indent_style = space +indent_size = 2 +tab_width = 2 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/.swiftformat b/.swiftformat new file mode 100644 index 0000000..08f338e --- /dev/null +++ b/.swiftformat @@ -0,0 +1,11 @@ +--self init-only +--indent 2 +--ifdef indent +--trimwhitespace always +--wraparguments before-first +--wrapparameters before-first +--wrapcollections preserve +--wrapconditions after-first +--typeblanklines preserve +--commas inline +--stripunusedargs closure-only diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..213129c --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,11 @@ +disabled_rules: + - closing_brace + - fuction_body_length + - opening_brace + - nesting + +included: + - Sources + - Tests + +ignore_multiline_statement_conditions: true diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 0000000..3370eb4 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,42 @@ +{ + "originHash" : "d7ba5e2a52aa5e7ace8a95b6c1e5803241eaf5b5d6b0123b81ea1dde978d8a6a", + "pins" : [ + { + "identity" : "swift-case-paths", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-case-paths", + "state" : { + "revision" : "19b7263bacb9751f151ec0c93ec816fe1ef67c7b", + "version" : "1.6.1" + } + }, + { + "identity" : "swift-parsing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-parsing.git", + "state" : { + "revision" : "3432cb81164dd3d69a75d0d63205be5fbae2c34b", + "version" : "0.14.1" + } + }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-syntax", + "state" : { + "revision" : "0687f71944021d616d34d922343dcef086855920", + "version" : "600.0.1" + } + }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "b444594f79844b0d6d76d70fbfb3f7f71728f938", + "version" : "1.5.1" + } + } + ], + "version" : 3 +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..bf8a8ca --- /dev/null +++ b/Package.swift @@ -0,0 +1,20 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "markdown-parsing", + platforms: [.macOS(.v13)], + dependencies: [ + .package(url: "https://github.com/pointfreeco/swift-parsing.git", from: "0.14.0") + ], + targets: [ + .executableTarget( + name: "markdown-parsing", + dependencies: [ + .product(name: "Parsing", package: "swift-parsing") + ] + ) + ] +) diff --git a/Sources/main.swift b/Sources/main.swift new file mode 100644 index 0000000..127e086 --- /dev/null +++ b/Sources/main.swift @@ -0,0 +1,190 @@ +import Foundation +@preconcurrency import Parsing + +let yamlString = """ +--- +author: Michael Housh +categories: + - HVAC + - General + - Programming +copy: true +draft: false +date: 2023-10-21 +lastmod: 2023-10-21 +image: banner.png +featuredImage: banner.png +series: + - General +tags: + - HVAC + - General + - Programming + +--- +""" + +_ = """ +title: "You Should Learn Markdown" +slug: "you-should-learn-markdown" +""" + +enum YamlItem { + case boolean(Bool) + case date(year: Int, month: Int, day: Int) + case string(String) + + private static let dateParser = Parse(input: Substring.self) { + Digits(4) + "-" + Digits(2) + "-" + Digits(2) + }.map { Self.date(year: $0.0, month: $0.1, day: $0.2) } + + private static let booleanParser = Parse(input: Substring.self) { + Bool.parser() + }.map { Self.boolean($0) } + + private static let quotedString = Parse(input: Substring.self) { + "\"" + PrefixUpTo("\"") + "\"" + } + + private static let stringParser = Parse(input: Substring.self) { + OneOf { + quotedString + Rest() + } + }.map { Self.string(String($0)) } + + static let parser = OneOf { + dateParser + booleanParser + stringParser + } +} + +enum YamlLine { + case keyValue(String, YamlItem) + case list(String, [String]) + + static let parser = OneOf { + listParser + keyValueParser + } + + static let keyParser = Parse(input: Substring.self) { + PrefixUpTo(":") + ":" + }.map(String.init) + + static let keyValueParser = Parse(input: Substring.self) { + PrefixUpTo(":").map(String.init) + ": " + YamlItem.parser + }.map { YamlLine.keyValue($0.0, $0.1) } + + static let listLineParser = Parse(input: Substring.self) { + Skip { PrefixThrough("- ") } + PrefixUpTo("\n").map(String.init) + "\n" + } + + static let listParser = Parse(input: Substring.self) { + PrefixUpTo(":\n").map(String.init) + ":\n" + Many { + Skip { PrefixThrough("- ") } + PrefixUpTo("\n").map(String.init) + "\n" + } + } + .map { YamlLine.list($0.0, $0.1) } +} + +let yamlBlockParser = Parse(input: Substring.UTF8View.self) { + "---\n".utf8 + Many { + PrefixUpTo("\n".utf8) + // From(.substring) { YamlLine.parser } + } separator: { + "\n".utf8 + } + "\n".utf8 + "---".utf8 +} + +// let yamlLineParser = Parse(input: Substring.UTF8View.self) { +// PrefixUpTo(":".utf8).map(String.init) +// ":".utf8 +// OneOf { +// PrefixUpTo("\n".utf8) +// Rest() +// }.map(String.init) +// } + +let stringLine = #"author: "Michael Housh""# +// let parsedLine = try yamlLineParser.parse(stringLine[...].utf8) +// print(parsedLine) + +let stringItem = "foo" +let quotedItem = "\"foo\"" +let dateItem = "2025-01-29" +let boolItem = "true" + +try print(YamlItem.parser.parse(stringItem[...])) +try print(YamlItem.parser.parse(quotedItem[...])) +try print(YamlItem.parser.parse(dateItem[...])) +try print(YamlItem.parser.parse(boolItem[...])) + +let kvLine = "author: Michael Housh" +var listLine = """ +test: + - HVAC + - General + - Programming + +"""[...] + +try print(YamlLine.parser.parse(kvLine[...])) +try print(YamlLine.parser.parse(&listLine)) +print(listLine) + +// try print(YamlItem.parser.parse(listItem[...])) + +var yamlLines = """ +author: Michael Housh +test: + - HVAC + - General + - Programming + +"""[...] + +let lineParser = Many { + YamlLine.parser +} separator: { + "\n" +} + +try print(lineParser.parse(yamlLines)) + +// let lines = try yamlBlockParser.parse(yamlString[...].utf8) +// +// for line in lines { +// print("line: \(String(line)!)") +// if let parsed = try? YamlLine.keyValueParser.parse(Substring(line)) { +// print(parsed) +// } else { +// if let key = try? YamlLine.keyParser.parse(Substring(line)) { +// print("found key: \(String(key))") +// } else { +// print("not key value.") +// } +// } +// } + +// print(lines.map(String.init)) +// print(lines)