Skip to content

Commit

Permalink
Add CSV/TSV support
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelmeuli committed Mar 11, 2020
1 parent 59f7377 commit 4acf10b
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 9 deletions.
24 changes: 24 additions & 0 deletions Glance.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
7E1DC528240E6F4A00D0A061 /* RendererFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E1DC527240E6F4A00D0A061 /* RendererFactory.swift */; };
7E1DC52A240E6FDE00D0A061 /* CodeRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E1DC529240E6FDE00D0A061 /* CodeRenderer.swift */; };
7E35BFC42410FDD800AB0A3C /* minireset.min.css in Resources */ = {isa = PBXBuildFile; fileRef = 7E35BFC32410FDD800AB0A3C /* minireset.min.css */; };
7E413F802418DD6200CFBB1D /* CsvRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E413F7F2418DD6200CFBB1D /* CsvRenderer.swift */; };
7E413F822418EB4B00CFBB1D /* csv-papaparse.min.js in Resources */ = {isa = PBXBuildFile; fileRef = 7E413F812418EB4B00CFBB1D /* csv-papaparse.min.js */; };
7E413F842418EB7E00CFBB1D /* csv-main.css in Resources */ = {isa = PBXBuildFile; fileRef = 7E413F832418EB7E00CFBB1D /* csv-main.css */; };
7E413F862418EEC100CFBB1D /* csv-main.js in Resources */ = {isa = PBXBuildFile; fileRef = 7E413F852418EEC100CFBB1D /* csv-main.js */; };
7E59DDD7240CC3B2009A4E05 /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = 7E59DDD6240CC3B2009A4E05 /* .gitignore */; };
7E6EF1FD240CC802009E4199 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E6EF1FC240CC802009E4199 /* Quartz.framework */; };
7E6EF200240CC802009E4199 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E6EF1FF240CC802009E4199 /* PreviewViewController.swift */; };
Expand Down Expand Up @@ -77,6 +81,10 @@
7E1DC527240E6F4A00D0A061 /* RendererFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RendererFactory.swift; sourceTree = "<group>"; };
7E1DC529240E6FDE00D0A061 /* CodeRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeRenderer.swift; sourceTree = "<group>"; };
7E35BFC32410FDD800AB0A3C /* minireset.min.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = minireset.min.css; path = QLPlugin/Assets/minireset.min.css; sourceTree = SOURCE_ROOT; };
7E413F7F2418DD6200CFBB1D /* CsvRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CsvRenderer.swift; sourceTree = "<group>"; };
7E413F812418EB4B00CFBB1D /* csv-papaparse.min.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "csv-papaparse.min.js"; sourceTree = "<group>"; };
7E413F832418EB7E00CFBB1D /* csv-main.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "csv-main.css"; sourceTree = "<group>"; };
7E413F852418EEC100CFBB1D /* csv-main.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = "csv-main.js"; sourceTree = "<group>"; };
7E59DDD6240CC3B2009A4E05 /* .gitignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitignore; sourceTree = SOURCE_ROOT; };
7E6EF1FA240CC802009E4199 /* QLPlugin.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = QLPlugin.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7E6EF1FC240CC802009E4199 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -147,6 +155,7 @@
isa = PBXGroup;
children = (
7E1DC52D240E9D2C00D0A061 /* code */,
7E413F7E2418DD3000CFBB1D /* csv */,
7E9F0D622416563E007F1008 /* markdown */,
7E35BFC32410FDD800AB0A3C /* minireset.min.css */,
7E1DC50A240E5A4B00D0A061 /* shared.css */,
Expand All @@ -158,6 +167,7 @@
isa = PBXGroup;
children = (
7E1DC529240E6FDE00D0A061 /* CodeRenderer.swift */,
7E413F7F2418DD6200CFBB1D /* CsvRenderer.swift */,
7E1DC520240E6D8000D0A061 /* MarkdownRenderer.swift */,
);
path = FileTypeRenderers;
Expand All @@ -171,6 +181,16 @@
path = code;
sourceTree = "<group>";
};
7E413F7E2418DD3000CFBB1D /* csv */ = {
isa = PBXGroup;
children = (
7E413F832418EB7E00CFBB1D /* csv-main.css */,
7E413F852418EEC100CFBB1D /* csv-main.js */,
7E413F812418EB4B00CFBB1D /* csv-papaparse.min.js */,
);
path = csv;
sourceTree = "<group>";
};
7E6EF1FB240CC802009E4199 /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -358,6 +378,9 @@
7E35BFC42410FDD800AB0A3C /* minireset.min.css in Resources */,
7E9F0D7424168685007F1008 /* github-markdown-css.min.css in Resources */,
7E9F0D6124164D35007F1008 /* code.css in Resources */,
7E413F862418EEC100CFBB1D /* csv-main.js in Resources */,
7E413F822418EB4B00CFBB1D /* csv-papaparse.min.js in Resources */,
7E413F842418EB7E00CFBB1D /* csv-main.css in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -386,6 +409,7 @@
7E6EF200240CC802009E4199 /* PreviewViewController.swift in Sources */,
7E1DC528240E6F4A00D0A061 /* RendererFactory.swift in Sources */,
7E1DC521240E6D8000D0A061 /* MarkdownRenderer.swift in Sources */,
7E413F802418DD6200CFBB1D /* CsvRenderer.swift in Sources */,
7E9F0D57241625A9007F1008 /* Shell.swift in Sources */,
7E1DC52A240E6FDE00D0A061 /* CodeRenderer.swift in Sources */,
7E9F0D7E24168870007F1008 /* Script.swift in Sources */,
Expand Down
13 changes: 13 additions & 0 deletions QLPlugin/Assets/csv/csv-main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
table {
border-collapse: collapse;
}

table,
td {
padding: 5px 7px;
border: 1px solid var(--color-border);
}

tr:first-child td {
background: var(--color-border);
}
19 changes: 19 additions & 0 deletions QLPlugin/Assets/csv/csv-main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function render(fileContent) {
// Create HTML table
const previewDiv = document.getElementById("csv-preview");
const tableElement = document.createElement("table");
previewDiv.append(tableElement);

function appendRows(rows) {
const rowElements = rows
.map(row => `<tr>${row.map(column => `<td>${column}</td>`).join("\n")}</tr>`)
.join("\n");
tableElement.innerHTML = rowElements;
}

// Parse CSV
Papa.parse(fileContent, {
worker: true,
chunk: results => appendRows(results.data),
});
}
25 changes: 25 additions & 0 deletions QLPlugin/Assets/csv/csv-papaparse.min.js

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions QLPlugin/Assets/csv/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

<link rel="stylesheet" type="text/css" href="../minireset.min.css" />
<link rel="stylesheet" type="text/css" href="../shared.css" />
<link rel="stylesheet" type="text/css" href="./csv-main.css" />
</head>

<body>
<div id="csv-preview"></div>

<script src="csv-papaparse.min.js"></script>
<script src="csv-main.js"></script>
<script>
const fileContent = `id,first_name,last_name,email,gender
1,First name 1,Last name 1,[email protected],Male
2,First name 2,Last name 2,[email protected],Female
3,First name 3,Last name 3,[email protected],Male
4,First name 4,Last name 4,[email protected],Female`;
render(fileContent);
</script>
</body>
</html>
26 changes: 18 additions & 8 deletions QLPlugin/Assets/shared.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
/* Variables */
body {
--color-background: #ffffff;
--color-border: #b5b5b5;
--color-text: #000000;
}

@media (prefers-color-scheme: dark) {
/* Dark mode */
body {
--color-background: #1e1e1e;
--color-border: #6f6f6f;
--color-text: #ffffff;
}
}

body {
font-family: -apple-system, BlinkMacSystemFont, "Helvetica", "Arial", sans-serif;
font-size: 12px;
tab-size: 4;
padding: 12px;
line-height: 1.4;
overflow: auto;
background: var(--color-background);
color: var(--color-text);
}

/* Large previews (e.g. Quick Look) */
Expand All @@ -14,14 +32,6 @@ body {
}
}

/* Dark mode */
@media (prefers-color-scheme: dark) {
body {
background: #1e1e1e;
color: #ffffff;
}
}

pre,
code {
font-family: Menlo, monospace;
Expand Down
5 changes: 5 additions & 0 deletions QLPlugin/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@
<string>dyn.ah62d4rv4ge81g25xsq</string>
<string>dyn.ah62d4rv4ge81g6pq</string>
<string>dyn.ah62d4rv4ge80g55sq2</string>

<!-- CSV -->
<string>dyn.ah62d4rv4ge81k2pc</string> <!-- .tab -->
<string>public.comma-separated-values-text</string> <!-- .csv -->
<string>public.tab-separated-values-text</string> <!-- .tsv -->
</array>
<key>QLSupportsSearchableItems</key>
<true/>
Expand Down
1 change: 0 additions & 1 deletion QLPlugin/Renderers/FileTypeRenderers/CodeRenderer.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Foundation
import JavaScriptCore
import os.log

class CodeRenderer: Renderer {
Expand Down
51 changes: 51 additions & 0 deletions QLPlugin/Renderers/FileTypeRenderers/CsvRenderer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Foundation
import os.log

class CsvRenderer: Renderer {
private let cssUrl = Bundle.main.url(forResource: "csv-main", withExtension: "css")
private let papaParsejsUrl = Bundle.main.url(
forResource: "csv-papaparse.min",
withExtension: "js"
)
private let renderjsUrl = Bundle.main.url(forResource: "csv-main", withExtension: "js")

override func getStylesheets() -> [Stylesheet] {
var stylesheets = super.getStylesheets()
if let cssUrl = cssUrl {
stylesheets.append(Stylesheet(url: cssUrl))
} else {
os_log("Could not find main CSV stylesheet", type: .error)
}
return stylesheets
}

override func getHtml() -> String {
"<div id=\"csv-preview\"></div>"
}

override func getScripts() -> [Script] {
var scripts = super.getScripts()

// Papa Parse library (parses CSV files)
if let papaParsejsUrl = papaParsejsUrl {
scripts.append(Script(url: papaParsejsUrl))
} else {
os_log("Could not find Papa Parse script", type: .error)
}

// Render script (generates HTML table from parsed CSV)
if let renderjsUrl = renderjsUrl {
scripts.append(Script(url: renderjsUrl))
} else {
os_log("Could not find CSV render script", type: .error)
}

// Main script (calls render function with file content)
scripts.append(Script(content: """
const fileContent = `\(fileContent.replacingOccurrences(of: "`", with: "\\`"))`;
render(fileContent);
"""))

return scripts
}
}
2 changes: 2 additions & 0 deletions QLPlugin/Renderers/RendererFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class RendererFactory {
) -> Renderer {
var renderer: Renderer.Type
switch fileExtension {
case "csv", "tab", "tsv":
renderer = CsvRenderer.self
case "md", "markdown", "mdown", "mkdn", "mkd":
renderer = MarkdownRenderer.self
default:
Expand Down

0 comments on commit 4acf10b

Please sign in to comment.