Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // SingleFile.swift
- // SingleFile
- //
- // Created by David Littlefield on 8/5/19.
- // Copyright © 2019 David Littlefield. All rights reserved.
- //
- import Cocoa
- import Foundation
- class SingleFile {
- static let shared = SingleFile()
- let javaScript = JavaScript.shared
- let fileManager = FileManager.default
- var libraryFilePaths = [
- "/index.js",
- "/lib/hooks/content/content-hooks-web.js",
- "/lib/hooks/content/content-hooks.js",
- "/lib/hooks/content/content-hooks-frames-web.js",
- "/lib/hooks/content/content-hooks-frames.js",
- "/lib/fetch/content/content-fetch-resources.js",
- "/lib/frame-tree/content/content-frame-tree.js",
- "/lib/lazy/content/content-lazy-loader.js",
- "/lib/single-file/single-file-util.js",
- "/lib/single-file/single-file-helper.js",
- "/lib/single-file/vendor/css-tree.js",
- "/lib/single-file/vendor/html-srcset-parser.js",
- "/lib/single-file/vendor/css-minifier.js",
- "/lib/single-file/vendor/css-font-property-parser.js",
- "/lib/single-file/vendor/css-media-query-parser.js",
- "/lib/single-file/modules/html-minifier.js",
- "/lib/single-file/modules/css-fonts-minifier.js",
- "/lib/single-file/modules/css-fonts-alt-minifier.js",
- "/lib/single-file/modules/css-matched-rules.js",
- "/lib/single-file/modules/css-medias-alt-minifier.js",
- "/lib/single-file/modules/css-rules-minifier.js",
- "/lib/single-file/modules/html-images-alt-minifier.js",
- "/lib/single-file/modules/html-serializer.js",
- "/lib/single-file/single-file-core.js",
- "/lib/single-file/single-file.js"
- ]
- var optionsFilePath = [
- "/extension/core/bg/config.js"
- ]
- var singleFileFilePath = [
- "/cli/back-ends/puppeteer.js"
- ]
- var folderContent = [
- "demo",
- "extension",
- "LICENSE",
- "privacy.md",
- "faq.md",
- "index.js",
- "cli",
- "README.MD",
- ".gitignore",
- ".github",
- "manifest.json",
- ".eslintrc.js",
- "lib",
- "_locales",
- "build-extension.sh"
- ]
- init() {}
- func convert() {
- convertLibrary()
- convertOptions()
- convertSingleFile()
- removeDirectory()
- }
- private func convertLibrary() {
- convertContentHooksWeb()
- convertContentHooks()
- convertContentHooksFramesWeb()
- convertContentFetchResources()
- convertIndex()
- convertFiles()
- mergeFiles()
- }
- private func convertContentHooksWeb() {
- let filePath = libraryFilePaths[1]
- let defaultStart = "(() => {"
- let defaultEnd = "})();"
- let customStart = "var contentHooksWeb = `"
- let customEnd = "`"
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.replace(javaScript: defaultEnd, withJavaScript: customEnd, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- private func convertContentHooks() {
- let filePath = libraryFilePaths[2]
- let defaultStart = """
- if (this.browser && browser.runtime && browser.runtime.getURL) {
- scriptElement.src = browser.runtime.getURL("/lib/hooks/content/content-hooks-web.js");
- scriptElement.async = false;
- } else if (this.singlefile.lib.getFileContent) {
- scriptElement.textContent = this.singlefile.lib.getFileContent("/lib/hooks/content/content-hooks-web.js");
- }
- """
- let customStart = ""
- let defaultEnd = "scriptElement.async = false;"
- let customEnd = "scriptElement.textContent = contentHooksWeb;"
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.insert(javaScript: customEnd, afterJavaScript: defaultEnd, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- private func convertContentHooksFramesWeb() {
- let filePath = libraryFilePaths[3]
- let defaultStart = "(() => {"
- let defaultEnd = "})();"
- let customStart = "var contentHooksFramesWeb = `"
- let customEnd = "`"
- javaScript.replace(javaScript:defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.replace(javaScript: defaultEnd, withJavaScript: customEnd, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- private func convertContentHooksFramesFile() {
- let filePath = libraryFilePaths[4]
- let defaultStart = """
- if (this.browser && browser.runtime && browser.runtime.getURL) {
- scriptElement.src = browser.runtime.getURL("/lib/hooks/content/content-hooks-frames-web.js");
- scriptElement.async = false;
- } else if (this.singlefile.lib.getFileContent) {
- scriptElement.textContent = this.singlefile.lib.getFileContent("/lib/hooks/content/content-hooks-frames-web.js");
- }
- """
- let customStart = ""
- let defaultEnd = "scriptElement.async = false;"
- let customEnd = "scriptElement.textContent = contentHooksFramesWeb;"
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.insert(javaScript: customEnd, afterJavaScript: defaultEnd, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- private func convertContentFetchResources() {
- let filePath = libraryFilePaths[5]
- let defaultStart = """
- const FETCH_REQUEST_EVENT = "single-file-request-fetch";
- const FETCH_RESPONSE_EVENT = "single-file-response-fetch";
- """
- let customStart = ""
- let defaultMiddle1 = """
- this.singlefile.lib.fetch.content.resources = this.singlefile.lib.fetch.content.resources || (() => {
- """
- let customMiddle1 = "const pendingMessages = new Map();"
- let defaultMiddle2 = "response = await hostFetch(url);"
- let customMiddle2 = "return nativeFetch(url);"
- let defaultMiddle3 = "catch (error) {"
- let customMiddle3 = "return nativeFetch(url);"
- let customEnd1 = "}"
- let customEnd2 = "},"
- let customEnd3 = """
- callbackFetch: message => {
- const callbacks = pendingMessages.get(message.url);
- if (callbacks) {
- pendingMessages.delete(message.url);
- if (message.error) {
- callbacks.forEach(callback => callback.reject(message.error));
- } else {
- const data = {
- status: message.status,
- headers: { get: name => message.headers[name] },
- arrayBuffer: async () => new Uint8Array(message.body).buffer
- };
- callbacks.forEach(callback => callback.resolve(data));
- }
- }
- }
- """
- let customEnd4 = "};"
- let customEnd5 = """
- function nativeFetch(url) {
- return new Promise((resolve, reject) => {
- webkit.messageHandlers.performHttpRequest.postMessage(url);
- let callbacks = pendingMessages.get(url);
- if (!callbacks) {
- callbacks = [];
- pendingMessages.set(url, callbacks);
- }
- callbacks.push({ resolve, reject });
- });
- }
- """
- let customEnd6 = "})();"
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.insert(javaScript: customMiddle1, afterJavaScript: defaultMiddle1, inPath: filePath)
- javaScript.replace(javaScript: defaultMiddle2, withJavaScript: customMiddle2, inPath: filePath)
- javaScript.trim(javaScript: defaultMiddle3, toEnd: true, inPath: filePath)
- javaScript.insert(javaScript: customMiddle3, afterJavaScript: defaultMiddle3, inPath: filePath)
- javaScript.insert(javaScript: customEnd1, atEnd: true, inPath: filePath)
- javaScript.insert(javaScript: customEnd2, atEnd: true, inPath: filePath)
- javaScript.insert(javaScript: customEnd3, atEnd: true, inPath: filePath)
- javaScript.insert(javaScript: customEnd4, atEnd: true, inPath: filePath)
- javaScript.insert(javaScript: customEnd5, atEnd: true, inPath: filePath)
- javaScript.insert(javaScript: customEnd6, atEnd: true, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- private func convertIndex() {
- let filePath = libraryFilePaths[0]
- let defaultStart = "this.singlefile = this.singlefile || {"
- let customStart = "var singlefile = {"
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- private func convertFiles() {
- let filePaths = libraryFilePaths
- for index in 1 ..< filePaths.count {
- let filePath = filePaths[index]
- let defaultStart = "this.singlefile"
- let customStart = "window.singlefile"
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.removeNewLines(inPath: filePath)
- }
- }
- private func mergeFiles() {
- let directoryPath = fileManager.currentDirectoryPath
- let filePaths = libraryFilePaths
- var string = ""
- for index in 0 ..< filePaths.count {
- let filePath = directoryPath + filePaths[index]
- let source = try! String(contentsOfFile: filePath, encoding: .utf8)
- string.append(contentsOf: source)
- string.append(contentsOf: "\n\n")
- if index == filePaths.count - 1 {
- javaScript.save(asFileName: "library.js", inPath: filePath)
- }
- }
- }
- private func convertOptions() {
- let filePath: String = optionsFilePath[0]
- let defaultStart: String = "const DEFAULT_CONFIG = {"
- let defaultEnd: String = "};"
- javaScript.trim(javaScript: defaultStart, fromStart: true, inPath: filePath)
- javaScript.trim(javaScript: defaultEnd, toEnd: true, inPath: filePath)
- javaScript.replace(javaScript: defaultStart, withJavaScript: "", inPath: filePath)
- javaScript.replace(javaScript: defaultEnd, withJavaScript: "", inPath: filePath)
- }
- private func saveOptions() {
- let directoryPath: String = fileManager.currentDirectoryPath
- let filePath: String = directoryPath + optionsFilePath[0]
- let customStart: String = "var options = { "
- let customEnd: String = " }"
- let source: String = try! String(contentsOfFile: filePath, encoding: .utf8)
- var lines: [String] = source.components(separatedBy: ",")
- lines = lines.map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) })
- var options: String = lines.joined(separator: ",\n")
- options = customStart + options + customEnd
- defaults.set(options, forKey: "defaultOptions")
- defaults.set(nil, forKey: "customOptions")
- javaScript.save(asFileName: "options.js", inPath: filePath)
- }
- private func convertSingleFile() {
- let filePath = singleFileFilePath[0]
- let defaultStart = "return await page.evaluate(async options => {"
- let defaultEnd = "}, options);"
- let customStart = "async function runSingleFile() {"
- let customEnd = "webkit.messageHandlers.websiteHasBeenSaved.postMessage(html);"
- let defaultMiddle = "return await singleFile.getPageData();"
- let customMiddle = "var html = (await singleFile.getPageData()).content;"
- javaScript.trim(javaScript: defaultStart, fromStart: true, inPath: filePath)
- javaScript.trim(javaScript: defaultEnd, toEnd: true, inPath: filePath)
- javaScript.replace(javaScript: defaultMiddle, withJavaScript: customMiddle, inPath: filePath)
- javaScript.replace(javaScript: defaultStart, withJavaScript: customStart, inPath: filePath)
- javaScript.replace(javaScript: defaultEnd, withJavaScript: customEnd, inPath: filePath)
- javaScript.insert(javaScript: "}", atEnd: true, inPath: filePath)
- javaScript.save(asFileName: "singlefile.js", inPath: filePath)
- }
- private func removeDirectory() {
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement