Skip to content
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
6 changes: 3 additions & 3 deletions Modules/Package.resolved

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

17 changes: 16 additions & 1 deletion Modules/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ let package = Package(
.library(name: "AsyncImageKit", targets: ["AsyncImageKit"]),
.library(name: "DesignSystem", targets: ["DesignSystem"]),
.library(name: "FormattableContentKit", targets: ["FormattableContentKit"]),
.library(name: "GutenbergProcessors", targets: ["GutenbergProcessors"]),
.library(name: "JetpackStats", targets: ["JetpackStats"]),
.library(name: "JetpackSocial", targets: ["JetpackSocial"]),
.library(name: "JetpackStatsWidgetsCore", targets: ["JetpackStatsWidgetsCore"]),
Expand Down Expand Up @@ -46,7 +47,7 @@ let package = Package(
.package(url: "https://github.com/erikdoe/ocmock", revision: "2c0bfd373289f4a7716db5d6db471640f91a6507"),
.package(url: "https://github.com/johnxnguyen/Down", branch: "master"),
.package(url: "https://github.com/kaishin/Gifu", from: "3.4.1"),
.package(url: "https://github.com/scinfu/SwiftSoup", exact: "2.7.5"),
.package(url: "https://github.com/scinfu/SwiftSoup", exact: "2.13.6"),
.package(url: "https://github.com/squarefrog/UIDeviceIdentifier", from: "2.3.0"),
// We can remove the SVProgressHUD fork once this PR is merged: https://github.com/SVProgressHUD/SVProgressHUD/pull/1131
.package(url: "https://github.com/automattic/SVProgressHUD", branch: "master"),
Expand Down Expand Up @@ -334,6 +335,11 @@ let package = Package(
.enableUpcomingFeature("BareSlashRegexLiterals")
]
),
.target(
name: "GutenbergProcessors",
dependencies: [.product(name: "SwiftSoup", package: "SwiftSoup")],
swiftSettings: [.swiftLanguageMode(.v5)]
),
.target(
name: "WordPressReader",
dependencies: [
Expand Down Expand Up @@ -400,6 +406,14 @@ let package = Package(
),
.testTarget(name: "WordPressCoreTests", dependencies: [.target(name: "WordPressCore")]),
.testTarget(name: "WordPressIntelligenceTests", dependencies: [.target(name: "WordPressIntelligence")]),
.testTarget(
name: "GutenbergProcessorsTests",
dependencies: [
.target(name: "GutenbergProcessors"),
.product(name: "SwiftSoup", package: "SwiftSoup")
],
swiftSettings: [.swiftLanguageMode(.v5)]
),
.testTarget(name: "WordPressReaderTests", dependencies: [.target(name: "WordPressReader")]),
.testTarget(
name: "JetpackSocialTests",
Expand Down Expand Up @@ -484,6 +498,7 @@ enum XcodeSupport {
"DesignSystem",
"BuildSettingsKit",
"FormattableContentKit",
"GutenbergProcessors",
"JetpackSocial",
"JetpackStats",
"JetpackStatsWidgetsCore",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ public class GutenbergParsedBlock {

public var attributes: [String: Any] {
get {
guard let data = self.attributesData.data(using: .utf8 ),
let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
let attributes = jsonObject as? [String: Any]
guard let data = self.attributesData.data(using: .utf8),
let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
let attributes = jsonObject as? [String: Any]
else {
return [:]
}
Expand All @@ -21,7 +21,8 @@ public class GutenbergParsedBlock {

set(newValue) {
guard let data = try? JSONSerialization.data(withJSONObject: newValue, options: .sortedKeys),
let attributes = String(data: data, encoding: .utf8) else {
let attributes = String(data: data, encoding: .utf8)
else {
return
}
self.attributesData = attributes
Expand All @@ -44,8 +45,7 @@ public class GutenbergParsedBlock {
if let separatorRange = data.range(of: " ") {
self.name = String(data[data.startIndex..<separatorRange.lowerBound])
self.attributesData = String(data[separatorRange.upperBound..<data.endIndex])
}
else {
} else {
self.name = data
self.attributesData = ""
}
Expand Down Expand Up @@ -114,7 +114,8 @@ public class GutenbergContentParser {
private let htmlDocument: Document?

public init(for content: String) {
self.htmlDocument = try? SwiftSoup.parseBodyFragment(content).outputSettings(OutputSettings().prettyPrint(pretty: false))
self.htmlDocument = try? SwiftSoup.parseBodyFragment(content)
.outputSettings(OutputSettings().prettyPrint(pretty: false))
self.blocks = []

guard let htmlContent = self.htmlDocument?.body() else {
Expand All @@ -124,37 +125,53 @@ public class GutenbergContentParser {
}

public func html() -> String {
return (try? self.htmlDocument?.body()?.html()) ?? ""
guard let body = self.htmlDocument?.body() else {
return ""
}
// SwiftSoup 2.12+ serializes unchanged nodes from a cached copy of the
// original source, so the attribute mutations the processors make on
// nested elements aren't reflected in the output. Replacing each
// top-level element with a copy marks its subtree dirty and forces a
// re-render, while the surrounding comment and text nodes (the Gutenberg
// block delimiters) are emitted from their original bytes.
for element in body.children().array() {
guard let clone = try? element.copy() as? Element else {
continue
}
try? element.replaceWith(clone)
}
return (try? body.html()) ?? ""
}

private func traverseChildNodes(element: Element, parentBlock: GutenbergParsedBlock? = nil) {
var currentBlock: GutenbergParsedBlock?
element.getChildNodes().forEach { node in
switch node {
// Convert comment tag into block
case let comment as SwiftSoup.Comment:
guard let block = GutenbergParsedBlock(comment: comment, parentBlock: parentBlock) else {
return
}
element.getChildNodes()
.forEach { node in
switch node {
// Convert comment tag into block
case let comment as SwiftSoup.Comment:
guard let block = GutenbergParsedBlock(comment: comment, parentBlock: parentBlock) else {
return
}

// Identify close tag
if let currrentBlock = currentBlock, block.name == "/\(currrentBlock.name)" {
currentBlock = nil
return
}
// Identify close tag
if let currrentBlock = currentBlock, block.name == "/\(currrentBlock.name)" {
currentBlock = nil
return
}

self.blocks.append(block)
currentBlock = block
// Insert HTML elements into block being processed
case let element as SwiftSoup.Element:
if let currentBlock {
currentBlock.elements.add(element)
self.blocks.append(block)
currentBlock = block
// Insert HTML elements into block being processed
case let element as SwiftSoup.Element:
if let currentBlock {
currentBlock.elements.add(element)
}
if element.childNodeSize() > 0 {
traverseChildNodes(element: element, parentBlock: currentBlock ?? parentBlock)
}
default: break
}
if element.childNodeSize() > 0 {
traverseChildNodes(element: element, parentBlock: currentBlock ?? parentBlock)
}
default: break
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

class GutenbergFileUploadProcessor: GutenbergProcessor {
public class GutenbergFileUploadProcessor: GutenbergProcessor {
private struct FileBlockKeys {
static var name = "wp:file"
static var id = "id"
Expand All @@ -11,7 +11,7 @@ class GutenbergFileUploadProcessor: GutenbergProcessor {
let remoteURLString: String
let serverMediaID: Int

init(mediaUploadID: Int32, serverMediaID: Int, remoteURLString: String) {
public init(mediaUploadID: Int32, serverMediaID: Int, remoteURLString: String) {
self.mediaUploadID = mediaUploadID
self.serverMediaID = serverMediaID
self.remoteURLString = remoteURLString
Expand All @@ -34,7 +34,7 @@ class GutenbergFileUploadProcessor: GutenbergProcessor {
}
}

func process(_ blocks: [GutenbergParsedBlock]) {
public func process(_ blocks: [GutenbergParsedBlock]) {
processFileBlocks(blocks)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation
import SwiftSoup

class GutenbergGalleryUploadProcessor: GutenbergProcessor {
public class GutenbergGalleryUploadProcessor: GutenbergProcessor {

let mediaUploadID: Int32
let remoteURLString: String
Expand All @@ -12,7 +12,7 @@ class GutenbergGalleryUploadProcessor: GutenbergProcessor {

static let imgClassIDPrefixAttribute = "wp-image-"

init(mediaUploadID: Int32, serverMediaID: Int, remoteURLString: String, mediaLink: String) {
public init(mediaUploadID: Int32, serverMediaID: Int, remoteURLString: String, mediaLink: String) {
self.mediaUploadID = mediaUploadID
self.serverMediaID = serverMediaID
self.remoteURLString = remoteURLString
Expand Down Expand Up @@ -139,7 +139,7 @@ class GutenbergGalleryUploadProcessor: GutenbergProcessor {
}
}

func process(_ blocks: [GutenbergParsedBlock]) {
public func process(_ blocks: [GutenbergParsedBlock]) {
processGalleryBlocks(blocks)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import Foundation

class GutenbergImgUploadProcessor: GutenbergProcessor {
public class GutenbergImgUploadProcessor: GutenbergProcessor {

let mediaUploadID: Int32
let remoteURLString: String
let serverMediaID: Int
static let imgClassIDPrefixAttribute = "wp-image-"

init(mediaUploadID: Int32, serverMediaID: Int, remoteURLString: String) {
public init(mediaUploadID: Int32, serverMediaID: Int, remoteURLString: String) {
self.mediaUploadID = mediaUploadID
self.serverMediaID = serverMediaID
self.remoteURLString = remoteURLString
Expand Down Expand Up @@ -63,7 +63,7 @@ class GutenbergImgUploadProcessor: GutenbergProcessor {
}
}

func process(_ blocks: [GutenbergParsedBlock]) {
public func process(_ blocks: [GutenbergParsedBlock]) {
processImageBlocks(blocks)
processMediaTextBlocks(blocks)
}
Expand Down
Loading