Skip to content

Commit 52f59db

Browse files
committed
A little Rakefile to generate QuickJSON/quicklookjson.c from readable source.
1 parent e4727ab commit 52f59db

5 files changed

Lines changed: 439 additions & 0 deletions

File tree

Rakefile

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
require 'etc'
2+
require 'json'
3+
require 'hpricot'
4+
require 'shellwords'
5+
6+
SubstVars = %w(DEV_MODE VERSION GIT_HASH HTML_HEADER HTML_FOOTER)
7+
#ENV['VERSION'] = IO.read('VERSION').chomp
8+
ENV["GIT_HASH"] = IO.popen("git log --format=%H -n 1") { |f| f.gets.chomp }
9+
10+
# not used yet
11+
#if ENV['DEV'] then
12+
# ENV['DEV_MODE'] ||= 'true'
13+
#else
14+
# ENV['DEV_MODE'] ||= 'false'
15+
#end
16+
17+
task :default => 'QuickJSON/quicklookjson.c'
18+
19+
desc 'build everything'
20+
task :all => %w(
21+
QuickJSON/quicklookjson.c
22+
)
23+
24+
desc 'cleanup'
25+
task :clean do |t|
26+
#verbose(true) { rm_rf FileList['build/*'] }
27+
end
28+
29+
desc 'Generates the quicklook source code from the test web page.'
30+
file 'QuickJSON/quicklookjson.c' => FileList['json-viewer/quicklook.*'] do |t|
31+
announce t
32+
33+
# fetch the html, inlining and minifying <script> tags we find
34+
cd 'json-viewer' do
35+
quicklook_html = IO.read('quicklook.html')
36+
dom = Hpricot.parse(quicklook_html)
37+
dom.search('script[@src]').each do |script|
38+
src = script.attributes['src']
39+
script.remove_attribute('src')
40+
script.inner_html =
41+
IO.popen("../bin/jsmin #{Shellwords.escape(src)}") do |stdout|
42+
stdout.read.gsub(/\n/, ' ')
43+
end
44+
end
45+
46+
# next, grab the leading and trailing portions and escape them to C strings
47+
dom.to_s =~ /\A(.*)__JSON__(.*)\Z/m
48+
ENV['HTML_HEADER'] = $1.to_json
49+
ENV['HTML_FOOTER'] = $2.to_json
50+
end
51+
52+
# move our C file template into place and perform __MAGIC__ expansion on it
53+
cp 'json-viewer/quicklook.c', t.name
54+
write_file t.name
55+
end
56+
57+
def announce(task, action = 'building')
58+
puts "#{action} #{task.name}"
59+
end
60+
61+
# edit a file in place, replacing __FOO__ any occurrences with ENV['FOO']
62+
def write_file(file, str = nil, no_subst = false)
63+
str = IO.read(file) unless str
64+
when_writing do
65+
File.open(file, 'w') {|f| f.write(no_subst ? str : vars_subst(str)) }
66+
end
67+
end
68+
69+
$blabbed = {}
70+
def vars_subst(str)
71+
str = str.dup
72+
for var in SubstVars
73+
if ENV[var] && str.gsub!("__#{var}__") { ENV[var] } &&
74+
($blabbed[var] || '') != ENV[var]
75+
show = truncate_if_longer_than(ENV[var], 70 - var.length)
76+
puts "#{var} is #{show}"
77+
$blabbed[var] = ENV[var]
78+
end
79+
end
80+
str
81+
end
82+
83+
def truncate_if_longer_than(what, max)
84+
if (what.size <= max+10) then
85+
what
86+
else
87+
/\A([^\n]{0,20}\b).*?(\b\S[^\n]{0,20})\Z/m.match(what) || # tries to
88+
/\A([^\n]{0,20}\b).*?(\S[^\n]{0,20})\Z/m.match(what) || # truncate
89+
/\A([^\n]{0,20}).*?(\b\S[^\n]{0,20})\Z/m.match(what) || # to word
90+
/\A([^\n]{0,20}).*?(\S[^\n]{0,20})\Z/m.match(what) # boundary
91+
$1 +
92+
' ... ' + nice_bytes(what.length - $1.length - $2.length, 2) +
93+
' ... ' + $2
94+
end
95+
end
96+
97+
# poached from Ramaze::Helper::NiceBytes
98+
K = 2.0**10
99+
M = 2.0**20
100+
G = 2.0**30
101+
T = 2.0**40
102+
def nice_bytes(bytes, max_digits=3)
103+
value, suffix, precision = case bytes
104+
when 0...K
105+
[ bytes, 'b', 0 ]
106+
else
107+
value, suffix = case bytes
108+
when K...M : [ bytes / K, 'KiB' ]
109+
when M...G : [ bytes / M, 'MiB' ]
110+
when G...T : [ bytes / G, 'GiB' ]
111+
else [ bytes / T, 'TiB' ]
112+
end
113+
used_digits = case value
114+
when 0...10 : 1
115+
when 10...100 : 2
116+
when 100...1000 : 3
117+
end
118+
leftover_digits = max_digits - used_digits
119+
[ value, suffix, leftover_digits > 0 ? leftover_digits : 0 ]
120+
end
121+
"%.#{precision}f#{suffix}" % value
122+
end

bin/jsmin

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#! /usr/bin/env node
2+
3+
var jsmin = require('jsmin').jsmin
4+
, ALL = 3, MOST = 2, KEEP_NL = 1
5+
, LEVEL = ALL
6+
, fs = require('fs')
7+
, _ = require('underscore')
8+
, files = _.uniq(process.argv.slice(2))
9+
, count = files.length
10+
;
11+
12+
if (files.length)
13+
load(files.shift());
14+
15+
function load(fn) {
16+
fs.readFile(fn, 'utf-8', function gotFile(e, file) {
17+
if (e) return fail(e, 'loading '+ fn);
18+
return minify(fn, file);
19+
});
20+
}
21+
22+
function fail(e, when) {
23+
console.error('jsmin error '+ when +': '+ e);
24+
process.exit(1 + count - files.length);
25+
}
26+
27+
function minify(fn, js) {
28+
process.stdout.write(jsmin(js, LEVEL));
29+
done();
30+
}
31+
32+
function done(e, fn) {
33+
if (e)
34+
fail(e, 'saving '+ fn);
35+
else if (files.length)
36+
load(files.shift());
37+
else
38+
process.exit(0);
39+
}

json-viewer/quicklook.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "quicklookjson.h"
2+
3+
#define HTML_HEADER __HTML_HEADER__
4+
#define HTML_FOOTER __HTML_FOOTER__
5+
6+
int main(int argc, char* argv[]) {
7+
if (argc < 2) {
8+
printf("Usage: quicklookjson <json file>\n");
9+
return 1;
10+
}
11+
CFStringRef path = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
12+
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, false);
13+
CFRelease(path);
14+
CFDataRef text = createDataFromURL(url);
15+
CFRelease(url);
16+
if (!text) {
17+
printf("File not found.\n");
18+
return 2;
19+
}
20+
CFDataRef result = text;
21+
CFRelease(text);
22+
printf("%s", CFDataGetBytePtr(result));
23+
return 0;
24+
}
25+
26+
CFDataRef createHTMLPreview(CFURLRef url)
27+
{
28+
CFDataRef text = createDataFromURL(url);
29+
if (!text) return NULL;
30+
CFDataRef result = createHTMLData(text);
31+
CFRelease(text);
32+
return result;
33+
}
34+
35+
CFDataRef createDataFromURL(CFURLRef url)
36+
{
37+
SInt32 errorCode = 0;
38+
39+
CFDataRef fileContent;
40+
CFDictionaryRef dict;
41+
CFArrayRef arr = CFArrayCreate(NULL, NULL, 0, NULL);
42+
43+
Boolean success = CFURLCreateDataAndPropertiesFromResource (NULL,
44+
url,
45+
&fileContent,
46+
&dict,
47+
arr,
48+
&errorCode);
49+
CFRelease(arr);
50+
CFRelease(dict);
51+
52+
if (!success) {
53+
return NULL;
54+
}
55+
56+
return fileContent;
57+
}
58+
59+
60+
CFDataRef createHTMLData(CFDataRef json)
61+
{
62+
CFMutableDataRef html = CFDataCreateMutable(NULL, 0);
63+
64+
CFDataAppendBytes(html, (const UInt8*) HTML_HEADER, sizeof(HTML_HEADER));
65+
CFDataAppendBytes(html, CFDataGetBytePtr(json), CFDataGetLength(json));
66+
CFDataAppendBytes(html, (const UInt8*) HTML_FOOTER, sizeof(HTML_FOOTER));
67+
68+
return html;
69+
}

json-viewer/quicklook.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5+
<script src="quicklook.js"></script>
6+
</head>
7+
<body onload="init()">
8+
<script id="json" type="application/json">
9+
__JSON__
10+
</script>
11+
</body>
12+
</html>

0 commit comments

Comments
 (0)