Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add languages to code blocks #7

Merged
merged 1 commit into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions EvergreenRegex.playground/Contents.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Cocoa

extension String {
var fullRange: NSRange {
return NSRange(location: 0, length: self.count)
}
}
let codeWithClass = try! NSRegularExpression(pattern: "^```:[a-zA-Z]+$", options: [])

let line = "```:swift"
if let match = codeWithClass.firstMatch(in: line, range: line.fullRange) {
print(match)
} else {
print("Cannot find a match")
}

4 changes: 4 additions & 0 deletions EvergreenRegex.playground/contents.xcplayground
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos' buildActiveScheme='true' importAppTypes='true'>
<timeline fileName='timeline.xctimeline'/>
</playground>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Sources/Evergreen/Evergreen+String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension String {
/// - Returns: The new string with replacements

func replaceAll(matching: NSRegularExpression, with template: String, options: NSRegularExpression.MatchingOptions = []) -> String {
return matching.stringByReplacingMatches(in: self, options: options, range: self.fullRange(), withTemplate: template)
return matching.stringByReplacingMatches(in: self, options: options, range: self.fullRange, withTemplate: template)
}

/// Replace first instance of `matching` in the string with `with`
Expand All @@ -41,7 +41,7 @@ extension String {
if let r = range {
matchedRange = r
} else {
guard let match = matching.firstMatch(in: self, options: [], range: fullRange()) else {
guard let match = matching.firstMatch(in: self, options: [], range: fullRange) else {
return self
}
matchedRange = match.range
Expand Down Expand Up @@ -94,7 +94,7 @@ extension String {
/// - Returns: True or false depending if there was a match or not

func isMatching(_ match: NSRegularExpression, in givenRange: NSRange? = nil, options: NSRegularExpression.MatchingOptions = []) -> Bool {
let range = givenRange ?? fullRange()
let range = givenRange ?? fullRange
if let _ = match.firstMatch(in: self, options: options, range: range) {
return true
}
Expand All @@ -113,7 +113,7 @@ extension String {
/// - Returns: A new string with the characters replaced

func stringFromMatch(_ regex: NSRegularExpression, in range: NSRange? = nil, options: NSRegularExpression.MatchingOptions = []) -> String {
let matchRange = range ?? fullRange()
let matchRange = range ?? fullRange

guard let match = regex.firstMatch(in: self, options: options, range: matchRange) else {
return ""
Expand All @@ -137,13 +137,13 @@ extension String {
///
/// - Returns: NSRange from 0 to count of characters

func fullRange() -> NSRange {
var fullRange: NSRange {
return NSRange(location: 0, length: self.count)
}

/// Insert a substring into a string, based on a regular expression match
mutating func replaceRange(matching: NSRegularExpression, with: String, options: NSRegularExpression.MatchingOptions = [], range _range: NSRange? = nil) {
let range = _range ?? self.fullRange()
let range = _range ?? self.fullRange
let _match = matching.firstMatch(in: self, options: options, range: range)

guard let match = _match?.range else { return }
Expand Down
34 changes: 22 additions & 12 deletions Sources/Evergreen/EvergreenProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public class EvergreenProcessor {
let boldItalicMatch = try! NSRegularExpression(pattern: "\\*{3}[^\\*]+\\*{3}", options: [])

let codeMatch = try! NSRegularExpression(pattern: "^```", options: [])
let codeWithClass = try! NSRegularExpression(pattern: "^```:[a-zA-Z]+$", options: [])
let htmlMatch = try! NSRegularExpression(pattern: "<[\\/]?[^>]+>", options: [])

// MARK: Content
Expand Down Expand Up @@ -120,7 +121,7 @@ public class EvergreenProcessor {
}

func linkParser(line: String, in givenRange: NSRange? = nil) -> (String, String, String?) {
let range = givenRange ?? line.fullRange()
let range = givenRange ?? line.fullRange
let anchorText = line.stringFromMatch(altMatch, in: range).replaceSubstrings(["![", "[", "]"])

let descText = line.stringFromMatch(descMatch, in: range).replaceSubstrings(["(", ")"])
Expand All @@ -139,7 +140,7 @@ public class EvergreenProcessor {
func parseLinks(element: EvergreenElement) {
var lineCopy = element.text

while let match = linkMatch.firstMatch(in: lineCopy, options: [], range: lineCopy.fullRange()) {
while let match = linkMatch.firstMatch(in: lineCopy, options: [], range: lineCopy.fullRange) {
let (anchorText, href, altText) = linkParser(line: lineCopy, in: match.range)

let identifier = UUID()
Expand All @@ -155,7 +156,7 @@ public class EvergreenProcessor {
}

func splitItalicMatch(element: EvergreenElement, in range: NSRange? = nil) -> EvergreenElement {
let matchRange = range ?? element.text.fullRange()
let matchRange = range ?? element.text.fullRange

let text = element.text.stringFromMatch(italicMatch, in: matchRange).replaceSubstrings(["*"]).trim()
let italicElement = EvergreenElement(elementType: "i", text: text)
Expand All @@ -169,7 +170,7 @@ public class EvergreenProcessor {
}

func splitBoldMatch(element: EvergreenElement, in range: NSRange? = nil) -> EvergreenElement {
let matchRange = range ?? element.text.fullRange()
let matchRange = range ?? element.text.fullRange

let match = element.text.stringFromMatch(boldMatch, in: matchRange)
let text = match.replaceSubstrings(["**"]).trim()
Expand All @@ -183,7 +184,7 @@ public class EvergreenProcessor {
}

func splitDoubleMatch(element: EvergreenElement) -> EvergreenElement {
let text = element.text.stringFromMatch(boldItalicMatch, in: element.text.fullRange()).replaceSubstrings(["***"]).trim()
let text = element.text.stringFromMatch(boldItalicMatch, in: element.text.fullRange).replaceSubstrings(["***"]).trim()
let identifier = UUID().uuidString

let italicElement = EvergreenElement(elementType: "i", text: text)
Expand Down Expand Up @@ -214,7 +215,7 @@ public class EvergreenProcessor {
func parseHeader(_ line: String) -> EvergreenElement {
let headerMatch = try! NSRegularExpression(pattern: "^#+", options: [])

let matches = headerMatch.matches(in: line, options: [], range: line.fullRange())
let matches = headerMatch.matches(in: line, options: [], range: line.fullRange)
let match = matches.first!

let originalText = line.replaceAll(matching: headerMatch, with: "").trim()
Expand Down Expand Up @@ -249,7 +250,7 @@ public class EvergreenProcessor {
return textElement
}

// MARK: <img /> Element
// MARK: <img> Element
func parseImageElement(_ line: String) -> EvergreenElement {
let (alt, src, title) = linkParser(line: line)
let element = EvergreenElement(elementType: "img")
Expand Down Expand Up @@ -307,7 +308,7 @@ public class EvergreenProcessor {
let indentRegex = try! NSRegularExpression(pattern: " +", options: [])

if line.starts(with: " ") && inList {
let indentLength = indentRegex.firstMatch(in: line, options: [], range: line.fullRange())!.range.length
let indentLength = indentRegex.firstMatch(in: line, options: [], range: line.fullRange)!.range.length

if currentListIndentLength < indentLength {
// We are indenting more than before, create a sub list
Expand Down Expand Up @@ -358,7 +359,7 @@ public class EvergreenProcessor {
currentListType = listType
inList = true
if line.starts(with: " ") {
let indentLength = indentRegex.firstMatch(in: line, options: [], range: line.fullRange())!.range.length
let indentLength = indentRegex.firstMatch(in: line, options: [], range: line.fullRange)!.range.length
currentListIndentLength = indentLength
}

Expand Down Expand Up @@ -421,7 +422,7 @@ public class EvergreenProcessor {
// MARK: <blockquote> Element
func parseBlockquoteElement(_ line: String) {
let quoteRegex = try! NSRegularExpression(pattern: "^>+", options: [])
let quoteIndent = quoteRegex.firstMatch(in: line, options: [], range: line.fullRange())!.range.length
let quoteIndent = quoteRegex.firstMatch(in: line, options: [], range: line.fullRange)!.range.length

let trimmed = line.removeAll(matching: blockMatch).trim()

Expand Down Expand Up @@ -589,7 +590,7 @@ public class EvergreenProcessor {
if line.isMatching(htmlMatch) {
let open = try! NSRegularExpression(pattern: "<", options: [])
let close = try! NSRegularExpression(pattern: ">", options: [])
while let match = htmlMatch.firstMatch(in: escaped, options: [], range: escaped.fullRange()) {
while let match = htmlMatch.firstMatch(in: escaped, options: [], range: escaped.fullRange) {
escaped = escaped.replaceFirst(matching: close, with: "&gt;", in: match.range, options: [])
escaped = escaped.replaceFirst(matching: open, with: "&lt;", in: match.range, options: [])
}
Expand Down Expand Up @@ -648,7 +649,7 @@ public class EvergreenProcessor {
}

func parseElement(_ line: String) {
let range = line.fullRange()
let range = line.fullRange
let trimmed = line.trim()

if line.isMatching(horizontalMatch, in: range) {
Expand All @@ -673,6 +674,15 @@ public class EvergreenProcessor {

let pre = EvergreenElement(elementType: "pre")
pre.children = [currentCode!]

if let match = codeWithClass.firstMatch(in: trimmed, range: trimmed.fullRange) {
let classString = String(trimmed[Range(match.range, in: trimmed)!])
if let language = classString.components(separatedBy: [":"]).last {
// Prism.js uses language-xxxxx to determine which language to use
pre.classes.append("language-\(language)")
}
}

addToElements(pre)
}
} else if trimmed.count > 0 {
Expand Down
5 changes: 3 additions & 2 deletions Tests/EvergreenTests/EvergreenProcessorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ final class EvergreenProcessorTests: XCTestCase {

func testCodeProcessed() {
let lines: Array<String> = [
"```",
"```:swift",
"function hello() {",
" return \"Hello World!\"",
"",
Expand All @@ -612,7 +612,8 @@ final class EvergreenProcessorTests: XCTestCase {

let pre = elements.first!
XCTAssertEqual(pre.elementType, "pre")

XCTAssert(pre.classes.contains("language-swift"))

let code = pre.children.first!
XCTAssertEqual(code.elementType, "code")
XCTAssertEqual(code.text, "function hello() {\n return \"Hello World!\"\n\n}")
Expand Down
6 changes: 3 additions & 3 deletions Tests/EvergreenTests/StringExtensionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ final class StringExtensionTests: XCTestCase {
let str = "replace replace none replace"
let match = try! NSRegularExpression(pattern: "replace", options: [])

let range = match.firstMatch(in: str, options: [], range: str.fullRange())?.range
let range = match.firstMatch(in: str, options: [], range: str.fullRange)?.range

let replaced = str.replaceFirst(matching: match, with: "_", in: range)

Expand All @@ -46,7 +46,7 @@ final class StringExtensionTests: XCTestCase {

let match = try! NSRegularExpression(pattern: "replace", options: [])

let range = match.firstMatch(in: str, options: [], range: str.fullRange())?.range
let range = match.firstMatch(in: str, options: [], range: str.fullRange)?.range

let badMatch = try! NSRegularExpression(pattern: "none", options: [])

Expand All @@ -60,7 +60,7 @@ final class StringExtensionTests: XCTestCase {

let match = try! NSRegularExpression(pattern: "replace", options: [])

let range = match.firstMatch(in: str, options: [], range: str.fullRange())?.range
let range = match.firstMatch(in: str, options: [], range: str.fullRange)?.range

let badMatch = try! NSRegularExpression(pattern: "none", options: [])

Expand Down