showmd 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,108 @@
1
+ (function () {
2
+ var output, Converter;
3
+ if (typeof exports === "object" && typeof require === "function") { // we're in a CommonJS (e.g. Node.js) module
4
+ output = exports;
5
+ Converter = require("./Markdown.Converter").Converter;
6
+ } else {
7
+ output = window.Markdown;
8
+ Converter = output.Converter;
9
+ }
10
+
11
+ output.getSanitizingConverter = function () {
12
+ var converter = new Converter();
13
+ converter.hooks.chain("postConversion", sanitizeHtml);
14
+ converter.hooks.chain("postConversion", balanceTags);
15
+ return converter;
16
+ }
17
+
18
+ function sanitizeHtml(html) {
19
+ return html.replace(/<[^>]*>?/gi, sanitizeTag);
20
+ }
21
+
22
+ // (tags that can be opened/closed) | (tags that stand alone)
23
+ var basic_tag_whitelist = /^(<\/?(b|blockquote|code|del|dd|dl|dt|em|h1|h2|h3|i|kbd|li|ol|p|pre|s|sup|sub|strong|strike|ul)>|<(br|hr)\s?\/?>)$/i;
24
+ // <a href="url..." optional title>|</a>
25
+ var a_white = /^(<a\shref="((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\stitle="[^"<>]+")?\s?>|<\/a>)$/i;
26
+
27
+ // <img src="url..." optional width optional height optional alt optional title
28
+ var img_white = /^(<img\ssrc="(https?:\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+"(\swidth="\d{1,3}")?(\sheight="\d{1,3}")?(\salt="[^"<>]*")?(\stitle="[^"<>]*")?\s?\/?>)$/i;
29
+
30
+ function sanitizeTag(tag) {
31
+ if (tag.match(basic_tag_whitelist) || tag.match(a_white) || tag.match(img_white))
32
+ return tag;
33
+ else
34
+ return "";
35
+ }
36
+
37
+ /// <summary>
38
+ /// attempt to balance HTML tags in the html string
39
+ /// by removing any unmatched opening or closing tags
40
+ /// IMPORTANT: we *assume* HTML has *already* been
41
+ /// sanitized and is safe/sane before balancing!
42
+ ///
43
+ /// adapted from CODESNIPPET: A8591DBA-D1D3-11DE-947C-BA5556D89593
44
+ /// </summary>
45
+ function balanceTags(html) {
46
+
47
+ if (html == "")
48
+ return "";
49
+
50
+ var re = /<\/?\w+[^>]*(\s|$|>)/g;
51
+ // convert everything to lower case; this makes
52
+ // our case insensitive comparisons easier
53
+ var tags = html.toLowerCase().match(re);
54
+
55
+ // no HTML tags present? nothing to do; exit now
56
+ var tagcount = (tags || []).length;
57
+ if (tagcount == 0)
58
+ return html;
59
+
60
+ var tagname, tag;
61
+ var ignoredtags = "<p><img><br><li><hr>";
62
+ var match;
63
+ var tagpaired = [];
64
+ var tagremove = [];
65
+ var needsRemoval = false;
66
+
67
+ // loop through matched tags in forward order
68
+ for (var ctag = 0; ctag < tagcount; ctag++) {
69
+ tagname = tags[ctag].replace(/<\/?(\w+).*/, "$1");
70
+ // skip any already paired tags
71
+ // and skip tags in our ignore list; assume they're self-closed
72
+ if (tagpaired[ctag] || ignoredtags.search("<" + tagname + ">") > -1)
73
+ continue;
74
+
75
+ tag = tags[ctag];
76
+ match = -1;
77
+
78
+ if (!/^<\//.test(tag)) {
79
+ // this is an opening tag
80
+ // search forwards (next tags), look for closing tags
81
+ for (var ntag = ctag + 1; ntag < tagcount; ntag++) {
82
+ if (!tagpaired[ntag] && tags[ntag] == "</" + tagname + ">") {
83
+ match = ntag;
84
+ break;
85
+ }
86
+ }
87
+ }
88
+
89
+ if (match == -1)
90
+ needsRemoval = tagremove[ctag] = true; // mark for removal
91
+ else
92
+ tagpaired[match] = true; // mark paired
93
+ }
94
+
95
+ if (!needsRemoval)
96
+ return html;
97
+
98
+ // delete all orphaned tags from the string
99
+
100
+ var ctag = 0;
101
+ html = html.replace(re, function (match) {
102
+ var res = tagremove[ctag] ? "" : match;
103
+ ctag++;
104
+ return res;
105
+ });
106
+ return html;
107
+ }
108
+ })();
@@ -0,0 +1,9 @@
1
+ require_relative "showmd/preview_generator"
2
+
3
+ if ARGV.size != 1
4
+ puts "Argument error, showmd only accepts one argument. It must me a path to a markdown file."
5
+ else
6
+ file_path = File.join(Dir.pwd, ARGV[0])
7
+ puts "Generating Preview #{file_path}"
8
+ Showmd::PreviewGenerator.new(file_path).generate
9
+ end
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>README.md - showmd preview</title>
5
+ <style type="text/css">
6
+ #preview{
7
+ width: 80%;
8
+ margin: auto;
9
+ background: white;
10
+ padding: 10px 30px;
11
+ box-shadow: 5px 5px 1px grey;
12
+ }
13
+ body{
14
+ background: #d3d3d3;
15
+ }
16
+ footer{
17
+ width: 80%;
18
+ margin:auto;
19
+ text-align: right;
20
+ padding-top: 15px;
21
+ }
22
+ img{
23
+ max-width: 100%;
24
+ }
25
+ </style>
26
+ <script type="text/javascript" src="../pagedown/Markdown.Converter.js"></script>
27
+ <script type="text/javascript" src="../pagedown/Markdown.Sanitizer.js"></script>
28
+ <script type="text/javascript" src="../pagedown/Markdown.Extra.js"></script>
29
+ </head>
30
+
31
+ <body>
32
+ <div id="markdown">## Showmd
33
+ ### An executable to preview markdown in your browser
34
+
35
+ Showmd lets you preview markdown files in your browser from the command line, it's a lightweight utility that will take the path to a markdown file and open up a preview in your browser. The markdown file is read and converted to HTML using [pagedown](https://code.google.com/p/pagedown/) and [pagedown-extra](https://github.com/jmcmanus/pagedown-extra) javascript libraries, a temporary file is created and previewed using [launchy](http://github.com), so as everything is done client side you don't even need a net connection.
36
+
37
+ ### Installation
38
+
39
+ ```
40
+ gem install showmd
41
+ ```
42
+
43
+ ### Usage
44
+
45
+ ```
46
+ showmd my_project/README.md
47
+ ```
48
+
49
+ ### Screenshot
50
+
51
+ ![](http://cih-static.s3.amazonaws.com/blog/showmd-screenshot.png)
52
+
53
+ ### Tests
54
+
55
+ ```
56
+ rake test
57
+ ```
58
+
59
+ ### Licence
60
+
61
+ See [Licence.txt](https://github.com/cih/showmd/blob/master/Licence.txt)
62
+ </div>
63
+ <div id="preview"></div>
64
+ <footer>Preview generated using <a href="http://github.com/cih/showmd">showmd</footer>
65
+
66
+ <script type="text/javascript">
67
+ (function () {
68
+ var converter = Markdown.getSanitizingConverter();
69
+ var markdown = document.getElementById("markdown");
70
+ var preview = document.getElementById("preview")
71
+ Markdown.Extra.init(converter);
72
+ preview.innerHTML = converter.makeHtml(markdown.innerHTML);
73
+ markdown.innerHTML = "";
74
+ })();
75
+ </script>
76
+ </body>
77
+ </html>
@@ -0,0 +1,41 @@
1
+ require 'launchy'
2
+
3
+ module Showmd
4
+ class InputError < StandardError;end;
5
+ class PreviewGenerator
6
+ # Pass in a md file path, read the file, build an html file and open in the default browser
7
+ attr_accessor :input_path, :output_path, :template_path, :markdown
8
+
9
+ def initialize(file)
10
+ @input_path = file
11
+ @output_path = File.expand_path(File.join(File.dirname(__FILE__), "markdown_preview.html"))
12
+ @template_path = File.expand_path(File.join(File.dirname(__FILE__), "template.html"))
13
+ end
14
+
15
+ def generate
16
+ read_md_file
17
+ build_html_file
18
+ open_in_browser
19
+ end
20
+
21
+ def read_md_file
22
+ begin
23
+ @markdown = File.read(input_path)
24
+ rescue => exception
25
+ raise InputError, "Sorry showmd was unable to read the file, please use a valid markdown file."
26
+ end
27
+ end
28
+
29
+ def build_html_file
30
+ template_text = File.read(template_path)
31
+ html_string = template_text.gsub(/<% markdown %>/, markdown)
32
+ html_string.gsub!(/<% page_title %>/, File.basename(input_path))
33
+
34
+ File.open(output_path, "w") {|file| file.puts html_string}
35
+ end
36
+
37
+ def open_in_browser
38
+ Launchy.open("file://localhost/#{output_path}")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><% page_title %> - showmd preview</title>
5
+ <style type="text/css">
6
+ #preview{
7
+ width: 80%;
8
+ margin: auto;
9
+ background: white;
10
+ padding: 10px 30px;
11
+ box-shadow: 5px 5px 1px grey;
12
+ }
13
+ body{
14
+ background: #d3d3d3;
15
+ }
16
+ footer{
17
+ width: 80%;
18
+ margin:auto;
19
+ text-align: right;
20
+ padding-top: 15px;
21
+ }
22
+ img{
23
+ max-width: 100%;
24
+ }
25
+ </style>
26
+ <script type="text/javascript" src="../pagedown/Markdown.Converter.js"></script>
27
+ <script type="text/javascript" src="../pagedown/Markdown.Sanitizer.js"></script>
28
+ <script type="text/javascript" src="../pagedown/Markdown.Extra.js"></script>
29
+ </head>
30
+
31
+ <body>
32
+ <div id="markdown"><% markdown %></div>
33
+ <div id="preview"></div>
34
+ <footer>Preview generated using <a href="http://github.com/cih/showmd">showmd</footer>
35
+
36
+ <script type="text/javascript">
37
+ (function () {
38
+ var converter = Markdown.getSanitizingConverter();
39
+ var markdown = document.getElementById("markdown");
40
+ var preview = document.getElementById("preview")
41
+ Markdown.Extra.init(converter);
42
+ preview.innerHTML = converter.makeHtml(markdown.innerHTML);
43
+ markdown.innerHTML = "";
44
+ })();
45
+ </script>
46
+ </body>
47
+ </html>
@@ -0,0 +1,3 @@
1
+ module Showmd
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'showmd/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "showmd"
8
+ spec.version = Showmd::VERSION
9
+ spec.authors = ["Chris Holmes"]
10
+ spec.email = ["tochrisholmes@gmail.com"]
11
+ spec.description = %q{An executable to preview markdown in your browser}
12
+ spec.summary = %q{Showmd lets you preview markdown files in your browser from the command line, it's a lightweight utility that will take the path to a markdown file and open up a preview in your browser.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = ["showmd"]
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "minitest"
24
+
25
+ spec.add_dependency "launchy"
26
+ end
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>valid.md - showmd preview</title>
5
+ </head>
6
+
7
+ <body>
8
+ <% markdown %>
9
+ <h1>HTML Template!</h1>
10
+ </body>
11
+ </html>
@@ -0,0 +1,3 @@
1
+ ### showmd testfile
2
+
3
+ *Here we have some markdown!*
@@ -0,0 +1,61 @@
1
+ require_relative '../lib/showmd/preview_generator'
2
+ require 'minitest/autorun'
3
+ require 'minitest/spec'
4
+ require 'minitest/pride'
5
+
6
+ module Showmd
7
+ class PreviewGeneratorSpec < MiniTest::Test
8
+
9
+ INVALID_FILE = File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "doesnt_exist.html"))
10
+ TEST_OUTPUT_PATH = File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "preview.html"))
11
+ TEST_TEMPLATE_PATH = File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "template.html"))
12
+ VALID_MD_FILE = File.expand_path(File.join(File.dirname(__FILE__), "fixtures", "valid.md"))
13
+
14
+ describe "read_md_file" do
15
+ it "should read a valid file" do
16
+ preview_generator = Showmd::PreviewGenerator.new(VALID_MD_FILE)
17
+ preview_generator.read_md_file.must_match "*Here we have some markdown!*"
18
+ end
19
+
20
+ it "should raise if file is invalid" do
21
+ lambda do
22
+ Showmd::PreviewGenerator.new(INVALID_FILE).read_md_file
23
+ end.must_raise(Showmd::InputError)
24
+ end
25
+ end
26
+
27
+ describe "build_html_file" do
28
+ before do
29
+ @preview_generator = Showmd::PreviewGenerator.new(VALID_MD_FILE)
30
+ @preview_generator.read_md_file
31
+ @preview_generator.output_path = TEST_OUTPUT_PATH
32
+ @preview_generator.template_path = TEST_TEMPLATE_PATH
33
+ end
34
+ it "should read from the html template" do
35
+ @preview_generator.build_html_file
36
+
37
+ File.exist?(@preview_generator.output_path).must_be :==, true
38
+ File.delete(@preview_generator.output_path)
39
+ end
40
+
41
+ it "should contain the markdown string" do
42
+ @preview_generator.build_html_file
43
+
44
+ File.read(@preview_generator.output_path).must_match "*Here we have some markdown!*"
45
+ File.delete(@preview_generator.output_path)
46
+ end
47
+ end
48
+
49
+ describe "generate" do
50
+ it "should call methods to read, build and open" do
51
+ showmd = MiniTest::Mock.new
52
+ def Launchy.open(x);;end
53
+ preview_generator = Showmd::PreviewGenerator.new(VALID_MD_FILE).generate
54
+
55
+ showmd.expect :read_md_file, true
56
+ showmd.expect :build_html_file, true
57
+ showmd.expect :open_in_browser, true
58
+ end
59
+ end
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: showmd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Holmes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: launchy
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: An executable to preview markdown in your browser
70
+ email:
71
+ - tochrisholmes@gmail.com
72
+ executables:
73
+ - showmd
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - bin/showmd
83
+ - lib/.DS_Store
84
+ - lib/pagedown/Markdown.Converter.js
85
+ - lib/pagedown/Markdown.Editor.js
86
+ - lib/pagedown/Markdown.Extra.js
87
+ - lib/pagedown/Markdown.Sanitizer.js
88
+ - lib/showmd.rb
89
+ - lib/showmd/markdown_preview.html
90
+ - lib/showmd/preview_generator.rb
91
+ - lib/showmd/template.html
92
+ - lib/showmd/version.rb
93
+ - showmd.gemspec
94
+ - spec/fixtures/template.html
95
+ - spec/fixtures/valid.md
96
+ - spec/preview_generator_spec.rb
97
+ homepage: ''
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.0.5
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Showmd lets you preview markdown files in your browser from the command line,
121
+ it's a lightweight utility that will take the path to a markdown file and open up
122
+ a preview in your browser.
123
+ test_files:
124
+ - spec/fixtures/template.html
125
+ - spec/fixtures/valid.md
126
+ - spec/preview_generator_spec.rb