Skip to content

Commit 87b1401

Browse files
Show content invisible characters
1 parent 6c8bca8 commit 87b1401

Some content is hidden

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

54 files changed

+1781
-1624
lines changed

Resources/branch_main/Sources/parser/TokenVisitor.swift

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ final class TokenVisitor: SyntaxRewriter {
4141

4242
list.append(
4343
"<span class='\(className)' " +
44-
"data-title='\("\(escapeHTML("\(node.trimmed)"))".replacingOccurrences(of: "\n", with: ""))' " +
45-
"data-content='\(escapeHTML(content))' " +
46-
"data-type='\(escapeHTML(type))' " +
44+
"data-title='\("\(node.trimmed)".htmlEscaped().displayInvisibles())' " +
45+
"data-content='\(content.htmlEscaped().substituteInvisibles())' " +
46+
"data-type='\(type.htmlEscaped())' " +
4747
#"data-range='{"startRow":\#(start.line),"startColumn":\#(start.column),"endRow":\#(end.line),"endColumn":\#(end.column)}'>"#
4848
)
4949

@@ -142,7 +142,12 @@ final class TokenVisitor: SyntaxRewriter {
142142
}
143143

144144
override func visit(_ token: TokenSyntax) -> TokenSyntax {
145-
current.text = escapeHTML(token.text)
145+
current.text = token
146+
.text
147+
.htmlEscaped()
148+
.substituteInvisibles()
149+
.replacingOccurrences(of: "&nbsp;", with: "")
150+
.replacingOccurrences(of: "<br/>", with: "↲<br/>")
146151
current.token = Token(kind: "\(token.tokenKind)", leadingTrivia: "", trailingTrivia: "")
147152

148153
token.leadingTrivia.forEach { (piece) in
@@ -183,18 +188,21 @@ final class TokenVisitor: SyntaxRewriter {
183188
let end = sourceRange.end
184189
let text = token.presence == .present ? token.text : ""
185190
list.append(
186-
"<span class='token \(escapeHTML(kind))' " +
187-
"data-title='\(escapeHTML("\(token.trimmed)"))' " +
188-
"data-content='\(escapeHTML("\(token.tokenKind)"))' " +
191+
"<span class='token \(kind.htmlEscaped())' " +
192+
"data-title='\("\(token.trimmed)".htmlEscaped().displayInvisibles())' " +
193+
"data-content='\("\(token.tokenKind)".htmlEscaped().substituteInvisibles())' " +
189194
"data-type='Token' " +
190195
#"data-range='{"startRow":\#(start.line),"startColumn":\#(start.column),"endRow":\#(end.line),"endColumn":\#(end.column)}'>"# +
191-
"\(escapeHTML(text).replacingOccurrences(of: "<br>", with: "<br/>"))</span>"
196+
"\(text.htmlEscaped().substituteInvisibles())</span>"
192197
)
193198
}
194199

195200
private func processTriviaPiece(_ piece: TriviaPiece) -> String {
196201
func wrapWithSpanTag(class c: String, text: String) -> String {
197-
"<span class='\(escapeHTML(c))' data-title='\(escapeHTML("\(piece)"))' data-content='\(escapeHTML(c))' data-type='Trivia'>\(escapeHTML(text).replacingOccurrences(of: "<br>", with: "<br/>"))</span>"
202+
"<span class='\(c.htmlEscaped())' " +
203+
"data-title='\("\(piece)".htmlEscaped().displayInvisibles())' " +
204+
"data-content='\(c.htmlEscaped().substituteInvisibles())' " +
205+
"data-type='Trivia'>\(text.htmlEscaped().substituteInvisibles())</span>"
198206
}
199207

200208
var trivia = ""
@@ -234,19 +242,31 @@ final class TokenVisitor: SyntaxRewriter {
234242
}
235243
}
236244

237-
func escapeHTML(_ string: String) -> String {
238-
var newString = string
239-
let specialCharacters = [
240-
("&", "&amp;"),
241-
("<", "&lt;"),
242-
(">", "&gt;"),
243-
("\"", "&quot;"),
244-
("'", "&apos;"),
245-
];
246-
for (unescaped, escaped) in specialCharacters {
247-
newString = newString.replacingOccurrences(of: unescaped, with: escaped, options: .literal, range: nil)
245+
private extension String {
246+
func htmlEscaped() -> String {
247+
var string = self
248+
let specialCharacters = [
249+
("&", "&amp;"),
250+
("<", "&lt;"),
251+
(">", "&gt;"),
252+
("\"", "&quot;"),
253+
("'", "&apos;"),
254+
];
255+
for (unescaped, escaped) in specialCharacters {
256+
string = string.replacingOccurrences(of: unescaped, with: escaped, options: .literal, range: nil)
257+
}
258+
return string
259+
}
260+
261+
func substituteInvisibles() -> String {
262+
self
263+
.replacingOccurrences(of: " ", with: "&nbsp;")
264+
.replacingOccurrences(of: "\n", with: "<br/>")
265+
}
266+
267+
func displayInvisibles() -> String {
268+
self
269+
.replacingOccurrences(of: " ", with: "")
270+
.replacingOccurrences(of: "\n", with: "")
248271
}
249-
return newString
250-
.replacingOccurrences(of: " ", with: "&nbsp;")
251-
.replacingOccurrences(of: "\n", with: "<br>")
252272
}

Resources/branch_main/Sources/parser/TreeNode.swift

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ final class TreeNode: Codable {
1212

1313
init(id: Int, text: String, range: Range, type: SyntaxType) {
1414
self.id = id
15-
self.text = escapeHTML(text)
15+
self.text = text.htmlEscaped()
1616
self.range = range
1717
self.type = type
1818
}
@@ -72,13 +72,9 @@ struct StructureProperty: Codable, Equatable {
7272
let ref: String?
7373

7474
init(name: String, value: StructureValue? = nil, ref: String? = nil) {
75-
self.name = escapeHTML(name)
75+
self.name = name.htmlEscaped()
7676
self.value = value
77-
if let ref {
78-
self.ref = escapeHTML(ref)
79-
} else {
80-
self.ref = nil
81-
}
77+
self.ref = ref?.htmlEscaped()
8278
}
8379
}
8480

@@ -99,12 +95,8 @@ struct StructureValue: Codable, Equatable {
9995
let kind: String?
10096

10197
init(text: String, kind: String? = nil) {
102-
self.text = escapeHTML(text)
103-
if let kind {
104-
self.kind = escapeHTML(kind)
105-
} else {
106-
self.kind = nil
107-
}
98+
self.text = text.htmlEscaped()
99+
self.kind = kind?.htmlEscaped()
108100
}
109101
}
110102

@@ -134,7 +126,7 @@ struct Token: Codable, Equatable {
134126
var trailingTrivia: String
135127

136128
init(kind: String, leadingTrivia: String, trailingTrivia: String) {
137-
self.kind = escapeHTML(kind)
129+
self.kind = kind.htmlEscaped()
138130
self.leadingTrivia = leadingTrivia
139131
self.trailingTrivia = trailingTrivia
140132
}
@@ -151,3 +143,22 @@ extension Token: CustomStringConvertible {
151143
"""
152144
}
153145
}
146+
147+
private extension String {
148+
func htmlEscaped() -> String {
149+
var string = self
150+
let specialCharacters = [
151+
("&", "&amp;"),
152+
("<", "&lt;"),
153+
(">", "&gt;"),
154+
("\"", "&quot;"),
155+
("'", "&apos;"),
156+
];
157+
for (unescaped, escaped) in specialCharacters {
158+
string = string.replacingOccurrences(of: unescaped, with: escaped, options: .literal, range: nil)
159+
}
160+
return string
161+
.replacingOccurrences(of: " ", with: "&nbsp;")
162+
.replacingOccurrences(of: "\n", with: "<br>")
163+
}
164+
}

Resources/branch_main/Tests/Tests/Fixtures/test-1-1.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
<span class='SourceFile' data-title='let&nbsp;number&nbsp;=&nbsp;0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
2-
<span class='CodeBlockItemList' data-title='let&nbsp;number&nbsp;=&nbsp;0' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
3-
<span class='CodeBlockItem' data-title='let&nbsp;number&nbsp;=&nbsp;0' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
4-
<span class='VariableDecl' data-title='let&nbsp;number&nbsp;=&nbsp;0' data-content='VariableDeclSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
1+
<span class='SourceFile' data-title='letnumber␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
2+
<span class='CodeBlockItemList' data-title='letnumber␣=␣0' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
3+
<span class='CodeBlockItem' data-title='letnumber␣=␣0' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
4+
<span class='VariableDecl' data-title='letnumber␣=␣0' data-content='VariableDeclSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
55
<span class='Token' data-title='let' data-content='keyword(SwiftSyntax.Keyword.let)' data-type='Token' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":4}'>
66
<span class='token keyword' data-title='let' data-content='keyword(SwiftSyntax.Keyword.let)' data-type='Token' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":4}'>
77
let
88
</span>
99
&nbsp;
1010
</span>
11-
<span class='PatternBindingList' data-title='number&nbsp;=&nbsp;0' data-content='PatternBindingListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":15}'>
12-
<span class='PatternBinding' data-title='number&nbsp;=&nbsp;0' data-content='PatternBindingSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":15}'>
11+
<span class='PatternBindingList' data-title='number␣=␣0' data-content='PatternBindingListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":15}'>
12+
<span class='PatternBinding' data-title='number␣=␣0' data-content='PatternBindingSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":15}'>
1313
<span class='IdentifierPattern' data-title='number' data-content='IdentifierPatternSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":11}'>
1414
<span class='Token' data-title='number' data-content='identifier(&quot;number&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":11}'>
1515
<span class='token identifier' data-title='number' data-content='identifier(&quot;number&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":11}'>
@@ -18,7 +18,7 @@
1818
&nbsp;
1919
</span>
2020
</span>
21-
<span class='InitializerClause' data-title='=&nbsp;0' data-content='InitializerClauseSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":15}'>
21+
<span class='InitializerClause' data-title='=0' data-content='InitializerClauseSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":15}'>
2222
<span class='Token' data-title='=' data-content='equal' data-type='Token' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":13}'>
2323
<span class='token equal' data-title='=' data-content='equal' data-type='Token' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":13}'>
2424
=

0 commit comments

Comments
 (0)