youandme 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'getopt', "~> 1.4.1"
4
+ gem 'rpeg-multimarkdown', '~> 0.1.1', :require => 'multimarkdown'
5
+ gem 'libxslt-ruby', '~> 1.0.8 '
6
+
7
+ group :development do
8
+ gem "shoulda", ">= 0"
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.6.4"
11
+ gem "rcov", ">= 0"
12
+ end
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ getopt (1.4.1)
5
+ git (1.2.5)
6
+ jeweler (1.6.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ libxml-ruby (2.2.2)
11
+ libxslt-ruby (1.0.8)
12
+ libxml-ruby (>= 2.2.2)
13
+ rake (0.9.2.2)
14
+ rcov (0.9.11)
15
+ rpeg-multimarkdown (0.1.1)
16
+ shoulda (2.11.3)
17
+
18
+ PLATFORMS
19
+ ruby
20
+
21
+ DEPENDENCIES
22
+ bundler (~> 1.0.0)
23
+ getopt (~> 1.4.1)
24
+ jeweler (~> 1.6.4)
25
+ libxslt-ruby (~> 1.0.8)
26
+ rcov
27
+ rpeg-multimarkdown (~> 0.1.1)
28
+ shoulda
@@ -0,0 +1,13 @@
1
+ Copyright 2011 Preston Lee
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,23 @@
1
+ # youandme
2
+
3
+ An unofficial Ruby library and command-line application ("youandme") for quickly parsing 23andme raw data files into a plain Ruby structures for quick processing and analysis.
4
+
5
+ ## Installation ##
6
+
7
+ gem install youandme
8
+
9
+ ## Command-Line Usage
10
+
11
+ The primary command-line script is "youandme", which generates a simple side-by-side comparison report for two given 23andme raw data files. To generate the reports, grab a few raw 23andme data files (from 23andme.com, SNPedia etc.), and compare them like so:
12
+
13
+ bin/youandme --directory <output_directory> --left <23andme_data_file.txt> --right <23andme_data_file.txt>
14
+
15
+ For "full" files, this will take a LONG time to run. (As in, probably more than 24 hours.) I recommend breaking down the data files into chromosome-size chunks, and running each comparison through this script individually.
16
+
17
+ ## Authors ##
18
+
19
+ Preston Lee
20
+
21
+ ## Copyright
22
+
23
+ Copyright (c) 2011 Preston Lee. See LICENSE.txt for further details.
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "youandme"
18
+ gem.homepage = "http://github.com/preston/youandme"
19
+ gem.license = "Apache 2.0"
20
+ gem.summary = %Q{Data comparison and analysis tools for 23andme raw data files.}
21
+ gem.description = %Q{An unofficial ruby library for quickly parsing 23andme raw data files into a plain Ruby structures for quick processing and analysis.}
22
+ gem.email = "conmotto@gmail.com"
23
+ gem.authors = ["Preston Lee"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "youandme #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # An script to compare two 23andme SNP data files.
4
+ #
5
+ # Author: Preston Lee
6
+ # License: Apache 2
7
+
8
+ # Runtime libraries:
9
+ require 'erb'
10
+
11
+ # 3rd-party libraries:
12
+ require 'getopt/long'
13
+ require 'multimarkdown'
14
+
15
+ # Our libraries:
16
+ current_dir = File.dirname(File.expand_path(__FILE__))
17
+ gem_dir = File.join(current_dir, '..')
18
+ lib_path = File.join(gem_dir, 'lib')
19
+ $LOAD_PATH.unshift lib_path
20
+ require 'youandme'
21
+
22
+
23
+ def print_help_and_exit
24
+ puts "Usage:"
25
+ puts "\t#{$0} --directory <output_directory> --left <23andme_data_file.txt> --right <23andme_data_file.txt>"
26
+ puts "\t#{$0} -d <output_directory> -l <23andme_data_file.txt> -r <23andme_data_file.txt>"
27
+ exit(1)
28
+ end
29
+
30
+
31
+ begin
32
+ opt = Getopt::Long.getopts(
33
+ ["--left", "-l", Getopt::REQUIRED],
34
+ ["--right", "-r", Getopt::REQUIRED],
35
+ ["--directory", "-d", Getopt::REQUIRED],
36
+ ["--help", "-h", Getopt::BOOLEAN]
37
+ )
38
+ rescue
39
+ print_help_and_exit
40
+ end
41
+
42
+
43
+
44
+ if(opt['help'])
45
+ print_help_and_exit
46
+ end
47
+
48
+ puts "Checking data file existyness..."
49
+ loader = YouAndMe::RawDataFileLoader.new
50
+ left_file = opt['left']
51
+ right_file = opt['right']
52
+ unless(loader.check_file(left_file) and loader.check_file(right_file))
53
+ puts "Please specify valid data files!"
54
+ print_help_and_exit
55
+ end
56
+
57
+ puts "Parsing data files... (may take a while)"
58
+ max_rows = 1000
59
+ left = loader.load_file(left_file, max_rows).sort{|a,b| a[:rsid] <=> b[:rsid]}
60
+ puts "\tLoaded #{left.length} SNPs from #{left_file}"
61
+ # y left[0..4]
62
+ right = loader.load_file(right_file, max_rows).sort{|a,b| a[:rsid] <=> b[:rsid]}
63
+ puts "\tLoaded #{right.length} SNPs from #{right_file}"
64
+ processor = YouAndMe::DataProcessor.new(left, right)
65
+ processor.process(true)
66
+
67
+
68
+ puts "Writing reports..."
69
+ processor.to_multimarkdown(left_file, right_file)
70
+ path = File.expand_path("#{opt['directory']}")
71
+ processor.write_multimarkdown(path)
72
+ processor.write_latex(path)
73
+ processor.write_html(path)
74
+
75
+
76
+ puts "Done!"
Binary file
@@ -0,0 +1,2 @@
1
+ require 'youandme/raw_data_file_loader'
2
+ require 'youandme/data_processor'
@@ -0,0 +1,116 @@
1
+ require 'xml'
2
+ require 'libxslt'
3
+ require 'fileutils'
4
+
5
+
6
+ module YouAndMe
7
+
8
+ class DataProcessor
9
+
10
+ attr_accessor :left
11
+ attr_accessor :right
12
+ attr_accessor :rsid_same
13
+ attr_accessor :rsid_diff
14
+ attr_accessor :both_rsid
15
+
16
+ attr_accessor :multimarkdown_text
17
+
18
+
19
+ def initialize(left, right)
20
+ @left = left
21
+ @right = right
22
+ # @rsid_same = nil
23
+ # @rsid_diff = nil
24
+ # @both_rsid = nil
25
+ # process
26
+ end
27
+
28
+ def write_multimarkdown(path)
29
+ file_path = File.join(path, "report.md")
30
+ puts "\tMultiMarkdown #{file_path}..."
31
+ report = File.open(file_path, 'w')
32
+ report.write @multimarkdown_text
33
+ report.close
34
+ end
35
+
36
+ def write_latex(path)
37
+ file_path = File.join(path, "report.ltx")
38
+ puts "\tLaTeX #{file_path}..."
39
+ report = File.open(file_path, 'w')
40
+ mmd = MultiMarkdown.new(@multimarkdown_text)
41
+ report.write mmd.to_latex
42
+ report.close
43
+ end
44
+
45
+ def write_html(path)
46
+ # Write the default file first.
47
+ file_path = File.join(path, "report.html")
48
+ puts "\tHTML #{file_path}..."
49
+ report = File.open(file_path, 'w')
50
+ mmd = MultiMarkdown.new(@multimarkdown_text, :smart, :filter_html)
51
+ report.write mmd.to_html
52
+ report.close
53
+
54
+ # Load the XSL Transform.
55
+ stylesheet_doc = XML::Document.file(File.join(File.dirname(__FILE__), 'xhtml-toc.xslt'))
56
+ stylesheet = LibXSLT::XSLT::Stylesheet.new(stylesheet_doc)
57
+
58
+ # Apply it and re-write the document.
59
+ old_html = XML::Document.file(file_path)
60
+ new_html = stylesheet.apply(old_html)
61
+ report = File.open(file_path, 'w')
62
+ report.write new_html
63
+ report.close
64
+
65
+ # Copy the CSS file into place.
66
+ css_src = File.join(File.dirname(__FILE__), 'report.css')
67
+ css_dest = File.join(path, 'report.css')
68
+ FileUtils.copy(css_src, css_dest)
69
+ end
70
+
71
+ def to_multimarkdown(left_file, right_file)
72
+ @left_file = left_file
73
+ @right_file = right_file
74
+ dir = File.dirname(File.expand_path(__FILE__))
75
+ template_file = File.join(dir, 'report.md.erb')
76
+ template = ERB.new(File.read(template_file))
77
+ @multimarkdown_text = template.result(binding)
78
+ end
79
+
80
+ def process(status = false)
81
+ puts "Creating indexes..." if status
82
+ puts "\tIndexing left data..." if status
83
+ @left_rsid = @left.collect do |n| n[:rsid] end
84
+ @left_chromosome = @left.collect do |n| n[:chromosome] end
85
+ @left_position = @left.collect do |n| n[:position] end
86
+ @left_genotype = @left.collect do |n| n[:genotype] end
87
+
88
+ puts "\tIndexing right data..." if status
89
+ @right_rsid = @right.collect do |n| n[:rsid] end
90
+ @right_chromosome = @right.collect do |n| n[:chromosome] end
91
+ @right_position = @right.collect do |n| n[:position] end
92
+ @right_genotype = @right.collect do |n| n[:genotype] end
93
+
94
+ puts "Computing stuff..." if status
95
+ puts "\tDetecting basic commonalities..." if status
96
+ @both_rsid = @left_rsid & @right_rsid
97
+ both_position = @left_position & @right_position
98
+
99
+ puts "\tFinding dissimilar genotypes..." if status
100
+ @rsid_same = []
101
+ @rsid_diff = []
102
+ @both_rsid.each do |rsid|
103
+ l = left[@left_rsid.index(rsid)]
104
+ r = right[@right_rsid.index(rsid)]
105
+ if l[:genotype] == r[:genotype]
106
+ @rsid_same << [l, r]
107
+ else
108
+ @rsid_diff << [l, r]
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+
116
+ end
@@ -0,0 +1,48 @@
1
+ # Author: Preston Lee
2
+
3
+ module YouAndMe
4
+
5
+ # Tool for loading raw data files from 23andme into native Ruby structures
6
+ class RawDataFileLoader
7
+
8
+ # Returns Markdown-formatted URLs for the given SNP hash.
9
+ def markdown_links(snp)
10
+ "[dbSNP](http://www.ncbi.nlm.nih.gov/SNP/snp_ref.cgi?rs=#{snp[:rsid]}) [SNPedia](http://www.snpedia.com/index.php/#{snp[:rsid]})"
11
+ end
12
+
13
+ # Returns true if and only if the given file exists and is readable.
14
+ def check_file(file_name)
15
+ valid = false
16
+ if(file_name != nil && File.file?(file_name) && File.readable?(file_name))
17
+ valid = true
18
+ end
19
+ valid
20
+ end
21
+
22
+ # Reads the given raw 23andme data file, parses the data, and shoves it into a native Ruby data structure.
23
+ # The returned data is an +Array+ full of +Hash+es, where each hash has key/value pairs for the columns in the data file.
24
+ def load_file(file_name, max = 0)
25
+ snps = []
26
+ # Manually spliting seems to be faster than the built-in CSV parser for
27
+ rows = File.read(file_name).split("\n")
28
+ rows.each do |n|
29
+ row = n.chomp.split("\t")
30
+ # CSV.foreach(file_name, :col_sep => "\t") do |row|
31
+ # Skip if the the line is a comment
32
+ next if row[0][0] == '#'
33
+ break if max > 0 && snps.length >= max
34
+ snp = {
35
+ :rsid => row[0],
36
+ :chromosome => row[1],
37
+ :position => row[2],
38
+ :genotype => row[3]
39
+ }
40
+ # y snp
41
+ snps << snp
42
+ end
43
+ snps
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,235 @@
1
+
2
+
3
+ body blockquote {
4
+ margin-top: .75em;
5
+ line-height: 1.5;
6
+ margin-bottom: .75em;
7
+ }
8
+ html {
9
+ background: #f8f8f8;
10
+ }
11
+ html body {
12
+ background: #fff;
13
+ margin: 1em auto 1em auto;
14
+ padding: 40px 100px;
15
+ line-height: 1.8;
16
+ width: 1000px;
17
+ text-align: justify;
18
+ font: 1.2em/2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
19
+ font-size: 18px;
20
+ color: #444;
21
+ }
22
+
23
+ .legalnotice {
24
+ font-size: small;
25
+ font-variant: small-caps;
26
+ }
27
+
28
+ body div {
29
+ margin: 0;
30
+ }
31
+
32
+ dl {
33
+ margin: .8em 0;
34
+ line-height: 1.2;
35
+ }
36
+
37
+ body form {
38
+ margin: .6em 0;
39
+ }
40
+
41
+ h1, h2, h4, h5, h6,
42
+ div.example p b,
43
+ .question,
44
+ div.table p b,
45
+ div.procedure p b {
46
+ color: #005599;
47
+ font: bold 1.2em/2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
48
+ margin: 20px 0;
49
+ }
50
+
51
+ h1 {
52
+ border-bottom: 1px solid black;
53
+ }
54
+
55
+
56
+
57
+
58
+ body hr {
59
+ margin: .6em;
60
+ border-width: 0 0 1px 0;
61
+ border-style: solid;
62
+ border-color: #cecece;
63
+ }
64
+
65
+ body img.navheader {
66
+ margin: 0 0 0 -4%;
67
+ }
68
+
69
+ ol {
70
+ margin: 0 0 0 5%;
71
+ line-height: 1.2;
72
+ }
73
+
74
+ body pre {
75
+ margin: .75em 0;
76
+ line-height: 1.0;
77
+ font-family: monospace;
78
+ }
79
+
80
+ body td, body th {
81
+ line-height: 1.2;
82
+ }
83
+
84
+ ul, body dir, body menu {
85
+ margin: 0 0 0 5%;
86
+ line-height: 1.2;
87
+ }
88
+
89
+ html {
90
+ margin: 0;
91
+ padding: 0;
92
+ }
93
+
94
+ body p b.application {
95
+ color: #000000;
96
+ }
97
+
98
+ .FILENAME {
99
+ color: #007a00;
100
+ }
101
+
102
+ .GUIMENU, .GUIMENUITEM, .GUISUBMENU,
103
+ .GUILABEL, .INTERFACE,
104
+ .SHORTCUT, .SHORTCUT .KEYCAP {
105
+ font-weight: bold;
106
+ }
107
+
108
+ .GUIBUTTON {
109
+ background-color: #CFCFCF;
110
+ padding: 2px;
111
+ }
112
+
113
+ .ACCEL {
114
+ background-color: #F0F0F0;
115
+ text-decoration: underline;
116
+ }
117
+
118
+ .SCREEN {
119
+ padding: 1ex;
120
+ }
121
+
122
+ .PROGRAMLISTING {
123
+ padding: 1ex;
124
+ background-color: #eee;
125
+ border: 1px solid #ccc;
126
+ }
127
+
128
+ @media screen {/* hide from IE3 */
129
+ a[href]:hover {
130
+ background: #ffa
131
+ }
132
+
133
+ }
134
+
135
+ BLOCKQUOTE.NOTE {
136
+ color: #222;
137
+ background: #eee;
138
+ border: 1px solid #ccc;
139
+ padding: 0.4em 0.4em;
140
+ width: 85%;
141
+ }
142
+
143
+ BLOCKQUOTE.TIP {
144
+ color: #004F00;
145
+ background: #d8ecd6;
146
+ border: 1px solid green;
147
+ padding: 0.2em 2em;
148
+ width: 85%;
149
+ }
150
+
151
+ BLOCKQUOTE.IMPORTANT {
152
+ font-style: italic;
153
+ border: 1px solid #a00;
154
+ border-left: 12px solid #c00;
155
+ padding: 0.1em 1em;
156
+ }
157
+
158
+ BLOCKQUOTE.WARNING {
159
+ color: #9F1313;
160
+ background: #f8e8e8;
161
+ border: 1px solid #e59595;
162
+ padding: 0.2em 2em;
163
+ width: 85%;
164
+ }
165
+
166
+ .EXAMPLE {
167
+ background: #fefde6;
168
+ border: 1px solid #f1bb16;
169
+ margin: 1em 0;
170
+ padding: 0.2em 2em;
171
+ width: 90%;
172
+ }
173
+
174
+
175
+ table {
176
+ width: 90%;
177
+ border-top: 1px solid #e5eff8;
178
+ border-right: 1px solid #e5eff8;
179
+ margin: 1em auto;
180
+ border-collapse: collapse;
181
+ }
182
+ caption {
183
+ color: #9ba9b4;
184
+ font-size: .94em;
185
+ letter-spacing: .1em;
186
+ margin: 1em 0 0 0;
187
+ padding: 0;
188
+ caption-side: top;
189
+ text-align: center;
190
+ }
191
+ tr.odd td {
192
+ background: #f7fbff
193
+ }
194
+ tr.odd .column1 {
195
+ background: #f4f9fe;
196
+ }
197
+ .column1 {
198
+ background: #f9fcfe;
199
+ }
200
+ td {
201
+ color: #678197;
202
+ border-bottom: 1px solid #e5eff8;
203
+ border-left: 1px solid #e5eff8;
204
+ padding: .3em 1em;
205
+ text-align: center;
206
+ }
207
+ th {
208
+ font-weight: normal;
209
+ color: #678197;
210
+ text-align: left;
211
+ border-bottom: 1px solid #e5eff8;
212
+ border-left: 1px solid #e5eff8;
213
+ padding: .3em 1em;
214
+ }
215
+ thead th {
216
+ background: #f4f9fe;
217
+ text-align: center;
218
+ font: bold 1.2em/2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
219
+ color: #66a3d3
220
+ }
221
+ tfoot th {
222
+ text-align: center;
223
+ background: #f4f9fe;
224
+ }
225
+ tfoot th strong {
226
+ font: bold 1.2em "Century Gothic","Trebuchet MS",Arial,Helvetica,sans-serif;
227
+ margin: .5em .5em .5em 0;
228
+ color: #66a3d3;
229
+ }
230
+ tfoot th em {
231
+ color: #f03b58;
232
+ font-weight: bold;
233
+ font-size: 1.1em;
234
+ font-style: normal;
235
+ }
@@ -0,0 +1,37 @@
1
+ Title: SNV Comparison Report
2
+ Subtitle: A side-by-side comparison
3
+ Format: complete
4
+ CSS: report.css
5
+
6
+ # SNV Comparison Report
7
+
8
+ <% loader = YouAndMe::RawDataFileLoader.new %>
9
+
10
+ - Left file: <%= @left_file %>
11
+ - Right file: <%= @right_file %>
12
+ - SNPs sequenced in both profiles: <%= @both_rsid.length %> (<%= 100.0 * @both_rsid.length / @left.length %>% of left and <%= 100.0 * @both_rsid.length / @right.length %>% of right.)
13
+ - Same genotype when SNV in both profiles: <%= @rsid_same.length %> (<%= "%.3f" % (100.0 * @rsid_same.length / @left.length) %>% of left and <%= "%.3f" % (100.0 * @rsid_same.length / @right.length) %>% of right.))
14
+ - Differing genotypes when SNV in both profiles: <%= @rsid_diff.length %> (<%= "%.3f" % (100.0 * @rsid_diff.length / @left.length) %>% of left and <%= "%.3f" % (100.0 * @rsid_diff.length / @right.length) %>% of right.))
15
+ - Generated <%= Time.now.strftime("%m/%d/%Y at %I:%M%p") %>.
16
+
17
+ ## Same Genotype
18
+
19
+ The following <%= @rsid_same.length %> SNVs are the *same* in both profiles. Click the links in the last column for access to scientific literature.
20
+
21
+ [Same Genotype]
22
+ | rsID | Genotype | Reference Position | Links ||
23
+ -------- |
24
+ <% @rsid_same.each do |n| %><%= n[0][:rsid] %> | <%= n[0][:genotype] %> | <%= n[0][:position] %> |<%= loader.markdown_links(n[0]) %>
25
+ <% end %>
26
+
27
+
28
+ ## Different Genotype
29
+
30
+ The follow <%= @rsid_diff.length %> SNVs *differ* between the profiles. Click the links in the last column for access to scientific literature.
31
+
32
+ [Same Genotype]
33
+ | rsID | Left Genotype | Right Genotype | Reference Position | Links ||
34
+ -------- |
35
+ <% @rsid_diff.each do |n| %><%= n[0][:rsid] %> | <%= n[0][:genotype] %> | <%= n[1][:genotype] %> | <%= n[0][:position] %> | <%= loader.markdown_links(n[0]) %>
36
+ <% end %>
37
+
@@ -0,0 +1,134 @@
1
+ <?xml version='1.0' encoding='utf-8'?>
2
+
3
+ <!-- XHTML-to-XHTML converter by Fletcher Penney
4
+ specifically designed for use with MultiMarkdown created XHTML
5
+
6
+ Adds a Table of Contents to the top of the XHTML document,
7
+ and adds linkbacks from h1 and h2's.
8
+
9
+ Also, an example of the sorts of things that can be done to customize
10
+ the XHTML output of MultiMarkdown.
11
+
12
+ MultiMarkdown Version 2.0.b6
13
+
14
+ $Id: xhtml-toc.xslt 499 2008-03-23 13:03:19Z fletcher $
15
+
16
+ TODO: If a section has no children, a "<ol></ol>" is generated, which is invalid
17
+ -->
18
+
19
+ <!--
20
+ # Copyright (C) 2007-2008 Fletcher T. Penney <fletcher@fletcherpenney.net>
21
+ #
22
+ # This program is free software; you can redistribute it and/or modify
23
+ # it under the terms of the GNU General Public License as published by
24
+ # the Free Software Foundation; either version 2 of the License, or
25
+ # (at your option) any later version.
26
+ #
27
+ # This program is distributed in the hope that it will be useful,
28
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
29
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
+ # GNU General Public License for more details.
31
+ #
32
+ # You should have received a copy of the GNU General Public License
33
+ # along with this program; if not, write to the
34
+ # Free Software Foundation, Inc.
35
+ # 59 Temple Place, Suite 330
36
+ # Boston, MA 02111-1307 USA
37
+ -->
38
+
39
+
40
+ <xsl:stylesheet
41
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
42
+ xmlns:xhtml="http://www.w3.org/1999/xhtml"
43
+ xmlns="http://www.w3.org/1999/xhtml"
44
+ exclude-result-prefixes="xhtml xsl"
45
+ version="1.0">
46
+
47
+ <xsl:variable name="newline">
48
+ <xsl:text>
49
+ </xsl:text>
50
+ </xsl:variable>
51
+
52
+ <xsl:output method='xml' version="1.0" encoding='utf-8' doctype-public="-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" doctype-system="http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" indent="no"/>
53
+
54
+ <!-- the identity template, based on http://www.xmlplease.com/xhtmlxhtml -->
55
+ <xsl:template match="@*|node()">
56
+ <xsl:copy>
57
+ <xsl:apply-templates select="@*|node()"/>
58
+ </xsl:copy>
59
+ </xsl:template>
60
+
61
+ <!-- adjust the body to add a ToC -->
62
+ <!-- TODO: Will need to move this to just before first <h1> to allow for introductory comments -->
63
+ <xsl:template match="xhtml:body">
64
+ <xsl:copy>
65
+ <xsl:value-of select="$newline"/>
66
+ <h1>Table of Contents</h1>
67
+ <xsl:value-of select="$newline"/>
68
+ <ol>
69
+ <xsl:apply-templates select="xhtml:h1" mode="ToC"/>
70
+ <xsl:value-of select="$newline"/>
71
+ </ol>
72
+ <xsl:apply-templates select="@*|node()"/>
73
+ </xsl:copy>
74
+ </xsl:template>
75
+
76
+
77
+ <!-- create ToC entry -->
78
+ <xsl:template match="xhtml:h1" mode="ToC">
79
+ <xsl:value-of select="$newline"/>
80
+ <xsl:variable name="link">
81
+ <xsl:value-of select="@id"/>
82
+ </xsl:variable>
83
+ <xsl:variable name="myId">
84
+ <xsl:value-of select="generate-id(.)"/>
85
+ </xsl:variable>
86
+ <li>
87
+ <a id="ToC-{$link}" href="#{$link}">
88
+ <xsl:apply-templates select="node()"/>
89
+ </a>
90
+ <xsl:if test="following::xhtml:h2[1][preceding::xhtml:h1[1]]">
91
+ <xsl:value-of select="$newline"/>
92
+ <ol>
93
+ <xsl:apply-templates select="following::xhtml:h2[preceding::xhtml:h1[1][generate-id() = $myId]]" mode="ToC"/>
94
+ <xsl:value-of select="$newline"/>
95
+ </ol>
96
+ <xsl:value-of select="$newline"/>
97
+ </xsl:if>
98
+ </li>
99
+ </xsl:template>
100
+
101
+ <xsl:template match="xhtml:h2" mode="ToC">
102
+ <xsl:value-of select="$newline"/>
103
+ <xsl:variable name="link">
104
+ <xsl:value-of select="@id"/>
105
+ </xsl:variable>
106
+ <li>
107
+ <a id="ToC-{$link}" href="#{$link}">
108
+ <xsl:apply-templates select="node()"/>
109
+ </a>
110
+ </li>
111
+ </xsl:template>
112
+
113
+ <!-- h1 and h2's should point back to the ToC for easy navigation -->
114
+ <xsl:template match="xhtml:h1">
115
+ <xsl:variable name="link">
116
+ <xsl:value-of select="@id"/>
117
+ </xsl:variable>
118
+ <xsl:copy>
119
+ <xsl:apply-templates select="@*|node()"/>
120
+ <a href="#ToC-{$link}">&#160;&#8617;</a>
121
+ </xsl:copy>
122
+ </xsl:template>
123
+
124
+ <xsl:template match="xhtml:h2">
125
+ <xsl:variable name="link">
126
+ <xsl:value-of select="@id"/>
127
+ </xsl:variable>
128
+ <xsl:copy>
129
+ <xsl:apply-templates select="@*|node()"/>
130
+ <a href="#ToC-{$link}">&#160;&#8617;</a>
131
+ </xsl:copy>
132
+ </xsl:template>
133
+
134
+ </xsl:stylesheet>
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'youandme'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestYouandme < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: youandme
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Preston Lee
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: getopt
16
+ requirement: &70244552095660 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70244552095660
25
+ - !ruby/object:Gem::Dependency
26
+ name: rpeg-multimarkdown
27
+ requirement: &70244552094940 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.1
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70244552094940
36
+ - !ruby/object:Gem::Dependency
37
+ name: libxslt-ruby
38
+ requirement: &70244552094060 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.8
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70244552094060
47
+ - !ruby/object:Gem::Dependency
48
+ name: shoulda
49
+ requirement: &70244552093220 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70244552093220
58
+ - !ruby/object:Gem::Dependency
59
+ name: bundler
60
+ requirement: &70244552091740 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.0.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70244552091740
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: &70244552090860 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.6.4
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70244552090860
80
+ - !ruby/object:Gem::Dependency
81
+ name: rcov
82
+ requirement: &70244552090000 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70244552090000
91
+ description: An unofficial ruby library for quickly parsing 23andme raw data files
92
+ into a plain Ruby structures for quick processing and analysis.
93
+ email: conmotto@gmail.com
94
+ executables:
95
+ - youandme
96
+ extensions: []
97
+ extra_rdoc_files:
98
+ - LICENSE.txt
99
+ - README.md
100
+ files:
101
+ - .document
102
+ - Gemfile
103
+ - Gemfile.lock
104
+ - LICENSE.txt
105
+ - README.md
106
+ - Rakefile
107
+ - VERSION
108
+ - bin/youandme
109
+ - lib/.DS_Store
110
+ - lib/youandme.rb
111
+ - lib/youandme/data_processor.rb
112
+ - lib/youandme/raw_data_file_loader.rb
113
+ - lib/youandme/report.css
114
+ - lib/youandme/report.md.erb
115
+ - lib/youandme/xhtml-toc.xslt
116
+ - test/helper.rb
117
+ - test/test_youandme.rb
118
+ homepage: http://github.com/preston/youandme
119
+ licenses:
120
+ - Apache 2.0
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ segments:
132
+ - 0
133
+ hash: -3067078396370175135
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 1.8.11
143
+ signing_key:
144
+ specification_version: 3
145
+ summary: Data comparison and analysis tools for 23andme raw data files.
146
+ test_files: []