├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .hound.yml ├── .rspec ├── .rubocop.yml ├── A.png ├── B.png ├── Gemfile ├── Guardfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin └── vimwiki_markdown ├── changelog.md ├── example_files └── default.tpl ├── lib ├── vimwiki_markdown.rb └── vimwiki_markdown │ ├── exceptions.rb │ ├── options.rb │ ├── template.rb │ ├── version.rb │ ├── vimwiki_link.rb │ ├── vimwiki_toc_filter.rb │ └── wiki_body.rb ├── spec ├── lib │ └── vimwiki_markdown │ │ ├── options_spec.rb │ │ ├── template_spec.rb │ │ ├── vimwiki_link_spec.rb │ │ └── wiki_body_spec.rb └── spec_helper.rb └── vimwiki_markdown.gemspec /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 4 | on: 5 | pull_request: 6 | branches: 7 | - '*' 8 | push: 9 | branches: 10 | - master 11 | jobs: 12 | # SQLITE 13 | testrunner: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | ruby: ['2.7', '3.0', '3.1'] 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Set up Ruby ${{ matrix.ruby }} 22 | uses: ruby/setup-ruby@v1 23 | with: 24 | ruby-version: ${{ matrix.ruby }} 25 | bundler-cache: true 26 | 27 | - name: Run tests 28 | run: | 29 | bundle exec rspec spec 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | *.bundle 19 | *.so 20 | *.o 21 | *.a 22 | mkmf.log 23 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | ruby: 2 | config_file: .rubocop.yml 3 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | TargetRubyVersion: 2.3 3 | 4 | Style/StringLiterals: 5 | EnforcedStyle: double_quotes 6 | 7 | Style/DoubleNegation: 8 | Enabled: false 9 | 10 | Style/AndOr: 11 | EnforcedStyle: conditionals 12 | 13 | Style/SymbolArray: 14 | Enabled: false 15 | 16 | Style/SafeNavigation: 17 | Enabled: false 18 | 19 | Layout/HeredocIndentation: 20 | Enabled: false 21 | 22 | Layout/FirstParameterIndentation: 23 | EnforcedStyle: consistent 24 | 25 | Layout/EmptyLines: 26 | Enabled: false 27 | 28 | Style/NumericLiterals: 29 | Enabled: false 30 | 31 | Style/FrozenStringLiteralComment: 32 | Enabled: false 33 | 34 | Style/RaiseArgs: 35 | EnforcedStyle: compact 36 | 37 | Documentation: 38 | Enabled: false 39 | 40 | Metrics/LineLength: 41 | Exclude: 42 | - spec/**/* 43 | Max: 120 44 | 45 | Metrics/BlockLength: 46 | Exclude: 47 | - 'Rakefile' 48 | - 'spec/**/*.rb' 49 | 50 | Lint/AmbiguousBlockAssociation: 51 | Exclude: 52 | - "spec/**/*" 53 | 54 | Layout/MultilineMethodCallIndentation: 55 | Enabled: true 56 | EnforcedStyle: indented 57 | SupportedStyles: 58 | - aligned 59 | - indented 60 | 61 | Metrics/AbcSize: 62 | Enabled: true 63 | Max: 20 64 | 65 | Metrics/MethodLength: 66 | Enabled: true 67 | CountComments: false 68 | Max: 20 69 | Exclude: 70 | - "spec/**/*" 71 | 72 | -------------------------------------------------------------------------------- /A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickdavey/vimwiki_markdown/cd15e729489cc20cb1344c51a3a6e050b6a238c4/A.png -------------------------------------------------------------------------------- /B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patrickdavey/vimwiki_markdown/cd15e729489cc20cb1344c51a3a6e050b6a238c4/B.png -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in vimwiki_markdown.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | guard :rspec, cmd: 'bundle exec rspec' do 2 | watch(%r{^spec/.+_spec\.rb$}) 3 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } 4 | watch('spec/spec_helper.rb') { "spec" } 5 | end 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Patrick Davey 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VimwikiMarkdown 2 | [![Code Climate](https://codeclimate.com/github/patrickdavey/vimwiki_markdown/badges/gpa.svg)](https://codeclimate.com/github/patrickdavey/vimwiki_markdown) [![CI](https://github.com/patrickdavey/vimwiki_markdown/actions/workflows/ci.yml/badge.svg)](https://github.com/patrickdavey/vimwiki_markdown/actions/workflows/ci.yml) 3 | 4 | This gem allows vimwiki pages written in (github enhanced) markdown 5 | to be converted to HTML. 6 | 7 | It is currently a work in progress (but working for me ;) 8 | 9 | ## Example 10 | It turns this: 11 | 12 | ![markdown](A.png) 13 | 14 | into 15 | 16 | ![finished](B.png) 17 | 18 | ## Requirements 19 | 20 | Ruby installed on your computer & up to date version of vimwiki 21 | 22 | https://www.ruby-lang.org/en/installation/ 23 | 24 | Install the vimwiki_markdown gem 25 | 26 | $ gem install vimwiki_markdown 27 | 28 | ## Setup 29 | 30 | vimwiki_markdown works best with a recent version of [vimwiki](https://github.com/vimwiki/vimwiki). Use the `dev` branch for best results. 31 | 32 | Ensure that your vimiwiki directive in your .vimrc is setup for markdown. For 33 | this we use the custom_wiki2html parameter. My .vimrc looks like this: 34 | 35 | let g:vimwiki_list = [{'path': '~/vimwiki', 'template_path': '~/vimwiki/templates/', 36 | \ 'template_default': 'default', 'syntax': 'markdown', 'ext': '.md', 37 | \ 'path_html': '~/vimwiki/site_html/', 'custom_wiki2html': 'vimwiki_markdown', 38 | \ 'html_filename_parameterization': 1, 39 | \ 'template_ext': '.tpl'}] 40 | 41 | The most important parts are the *'custom_wiki2html': 'vimwiki_markdown'* and the *'html_filename_parameterization': 1*. The custom_wiki2html tells vimwiki to use this gem for creating html, the html_filename_parameterization tells vimwiki to match the filenames that vimwiki_markdown produces. 42 | 43 | ### Install issues. 44 | There have been some issues with getting dependencies installed. Before opening an issue, please check if you can use [rvm](http://rvm.io/) to install the gem, as RVM is magic and makes everything work ;) 45 | 46 | ### VimWiki Template 47 | 48 | It is a requirement that your template file contain a placeholder 49 | for the syntax highlighting code to be placed. In order to do this, 50 | open up your default.tpl (or whatever your template file is called) 51 | and ensure that before the closing tag you put 52 | `%pygments%`. You also have the option to put `%dark_pygments%` if you want to have "dark mode" syntax highlighting. 53 | 54 | A sample tpl file is available here https://raw.githubusercontent.com/patrickdavey/vimwiki_markdown/master/example_files/default.tpl 55 | 56 | #### Optional %root_html% marker. 57 | 58 | You can also have a `%root_html%` marker in your template file, thanks 59 | to [this commit](https://github.com/patrickdavey/vimwiki_markdown/commit/8645883b96df9962aba616d0d12961285cd3f4d7). 60 | It will get rewritten with the relative path to the root 61 | of the site (e.g. `./` or `../../` etc) 62 | 63 | #### Optional %date% marker. 64 | 65 | You can also have a `%date%` marker in your template file 66 | It will get rewritten with todays date in the format 29 March 2019 67 | 68 | #### Support for tasklists 69 | Vimwiki has support for complex todo lists which you can [read about in their help.txt](https://github.com/vimwiki/vimwiki/blob/619f04f89861c58e5a6415a4f83847752928252d/doc/vimwiki.txt#L1768). We do support turning them into HTML. This is _slightly different_ from the way that GitHub checklists are rendered, but, the syntax is a subset of GitHub lists so it should be fine. You can read about it in the [issue](https://github.com/patrickdavey/vimwiki_markdown/issues/27), but basically it should work fine. You will want to add `styles` in for the various states that the todo lists can be in. The easiest way is to simply add the `styles` into your template. You can see the styles [in the sample template here](https://github.com/patrickdavey/vimwiki_markdown/blob/293f99e656819b9c5ecc0c831698ce58904eb774/example_files/default.tpl#L7-L45) 70 | 71 | #### Support for :local and :file links 72 | 73 | We have partial support for the `:local` and `:file` link types for vimwiki. 74 | If you are editing `foo.md` (in the root dir of your wiki) and you are linking to `bar.txt` stored in the same directory as `foo.md` you can do: 75 | 76 | * `[link text](local:bar.txt)` when output to HTML becomes `link text` 77 | * `[link text](file:bar.txt)` when output to HTML becomes `link text` 78 | 79 | #### Optional %nohtml 80 | 81 | If you place the text %nohtml anywhere in a wiki page, it will not be processed into html 82 | 83 | ## Contributing 84 | 85 | Pull requests are very welcome 86 | 87 | 1. Fork it ( https://github.com/patrickdavey/vimwiki_markdown/fork ) 88 | 2. Create your feature branch (`git checkout -b my-new-feature`) 89 | 3. Commit your changes (`git commit -am 'Add some feature'`) 90 | 4. Push to the branch (`git push origin my-new-feature`) 91 | 5. Create a new Pull Request 92 | 93 | ## License 94 | 95 | [MIT License](http://opensource.org/licenses/mit-license.php) 96 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rspec/core/rake_task' 2 | require 'bundler/gem_tasks' 3 | 4 | # Default directory to look in is `/specs` 5 | # Run with `rake spec` 6 | RSpec::Core::RakeTask.new(:spec) do |task| 7 | task.rspec_opts = ['--color', '--format', 'documentation'] 8 | end 9 | 10 | task :default => :spec 11 | 12 | -------------------------------------------------------------------------------- /bin/vimwiki_markdown: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'vimwiki_markdown' 3 | 4 | if ARGV.include?("--version") || ARGV.include?("-v") 5 | puts "vimwiki_markdown #{VimwikiMarkdown::VERSION}" 6 | exit 0 7 | else 8 | VimwikiMarkdown.convert_wikimarkdown_to_html 9 | end 10 | 11 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## 0.9.3 [08 Feb 2025] 2 | Add a --version flag to the command line tool 3 | 4 | ## 0.9.2 [02 April 2023] 5 | Just bump activesupport version for security advisories 6 | 7 | ## 0.9.1 [02 April 2023] 8 | Bugfix that both pygments and dark_pygments placeholers were required. 9 | 10 | ## 0.9.0 [02 April 2023] 11 | Add support for dark mode. Drop support for ruby < 2.7 12 | 13 | ## 0.8.2 [22 June 2022] 14 | Remove deprecation warning for EscapeUtils.escape_html 15 | see https://github.com/patrickdavey/vimwiki_markdown/pull/43 16 | 17 | ## 0.8.1 [March 7 2022] 18 | Update commonmarker version, fixes security issue! 19 | 20 | ## 0.8.0 [March 7 2022] 21 | Fixes an issue where VimwikiTOC generated table of contents where there are duplicate heading names did not match the output HTML from the Github pipeline. 22 | 23 | This means any generated (dupliate) bookmarks are going to be broken though, so, this is backwardly incompatible 24 | 25 | see https://github.com/patrickdavey/vimwiki_markdown/pull/39 26 | 27 | ## 0.7.0 [July 8 2021] 28 | Fixes an issue whereby non english filenames were being replaced with empty strings 29 | see https://github.com/patrickdavey/vimwiki_markdown/pull/35 30 | 31 | ## 0.6.0 [April 26 2020] 32 | Support for todo lists with enhanced state options. Thanks to @primercuervo 33 | 34 | ## 0.5.0 [April 26 2020] 35 | Partial support for `local` and `file` links in urls. Thanks to @tfachmann for the PR 36 | 37 | ## 0.4.4 [June 16 2019] 38 | Allow fragments if they are for local vimwiki links only 39 | 40 | ## 0.4.3 [June 16 2019] 41 | temporarily revoke fragments until we're not altering old links 42 | 43 | ## 0.4.2 [June 16 2019] 44 | Allow "fragments" in markdown style links such as those generated by :VimwikiTOC or or when using a diary_caption_level. 45 | Thanks to @djeremiah - see https://github.com/patrickdavey/vimwiki_markdown/pull/23 46 | 47 | ## 0.4.1 [June 16 2019] 48 | Allow "unsafe" HTML tags in markdown content (iframe etc.) 49 | 50 | ## 0.4.0 [June 16 2019] 51 | Support HTML tags in markdown content again. 52 | 53 | ## 0.3.3 [March 29 2019] 54 | Support for %date% and %nohtml tags 55 | Add information about html_filename_parameterization. 56 | 57 | ## 0.3.2 [March 28 2019] 58 | 59 | Bugfix 60 | 61 | Files were changed to be written out using their actual filename, rather than the 62 | parameterized version, this is fixed now. 63 | 64 | ## 0.3.1 [March 10 2019] 65 | Adds the ability to strip the extension correctly from vimwiki files. 66 | For example, the file index.wiki was converted to index.wiki.html. 67 | 68 | Thanks to @bowmanat for the PR. 69 | 70 | This may also very likely break existing links, so, watch out there ;) 71 | 72 | ## 0.3.0 [March 10 2019] 73 | Rebuilds vimwiki_markdown against the latest versions of Github/Markup etc. 74 | 75 | The tools are somewhat different and so it's quite possible there will be breaking changes here, especially if 76 | you have embedded HTML tags inside your markdown files. With a later version of https://github.com/github/markup 77 | we should be able to pass options to commonmark and give ourselves more options. 78 | 79 | This also uses rouge for syntax highlighting (fenced code blocks). Finding the documentation for that was fun ;) 80 | 81 | ### Breaking changes with 0.3 82 | * This removes the title tag functionality which was introduced in 0.2.6 Unfortunately, having spaces in links meant that the new markdown parsing did not see the link as being valid (at least for [foo bar](foo bar) links). This may be reintroduced later. 83 | * Requires ruby >= 2.3.8 84 | 85 | 86 | ## 0.2.6 [Jan 18 2018] 87 | Add %template and %title options 88 | 89 | ## 0.2.4 [Jan 01 2017] 90 | Make directory links work correctly. If you now link to 91 | a directory [somedir](somedir/) then that link will be preserved 92 | correctly. 93 | 94 | ## 0.2.3 [December 15th 2016] 95 | Bugfix - multiple links on the same line were not processed correctly. 96 | 97 | ## 0.2.1 [December 15th 2016] 98 | Allow %root_path% substitution in template file. 99 | 100 | ## 0.2.0 [March 6th 2016] 101 | * Adds the ability for `[[source|title]]` style links to be parsed correctly 102 | * Allows links with subdirectories `[[path/in/a/subdir/file]]` links to work 103 | * Also allows vimwiki links formatted with markdown syntax to work, this 104 | feature is currently implemented on the dev branch. This means you can 105 | link to [my markdownfile](blah.md) and it'll be parsed correctly 106 | 107 | ## 0.1.3 [August 11th 2015] 108 | * Adding the TableOfContents filter so that bookmarks are created. 109 | 110 | ## 0.1.1 [April 22nd 2015] 111 | * Aaaaannnnd reverting that change. While it totally works, it probably 112 | is overkill to have Druby running. The major issue is that vimwiki 113 | deletes the old files as the filenames do not match. Have added a 114 | note in the README to tell people how to make it faster. 115 | 116 | ## 0.1.0 [April 18th 2015] 117 | * Quite a major change, we now spin up a Druby server in the background 118 | and then send the files across the wire to it. This is somewhat 119 | invasive, but, on the plus side, takes the compilation time from 120 | several minutes down to seconds as we're not having to start 121 | up and require a whole bunch of files all the time. 122 | 123 | ## 0.0.4 [Dec 9th 2014] 124 | * Use Github::Markup to prerender the markdown 125 | 126 | ## 0.0.3 [Oct 30th 2014] 127 | 128 | * Raise warning if pygments placeholder is not present 129 | 130 | ## 0.0.2 [Sept 2014] 131 | 132 | * Initial beta release of the vimwiki_markdown gem 133 | -------------------------------------------------------------------------------- /example_files/default.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %title% 5 | 6 | %pygments% 7 | 8 | 46 | 47 | 48 |

%title%

49 | %content% 50 | 51 | 52 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown.rb: -------------------------------------------------------------------------------- 1 | require "vimwiki_markdown/version" 2 | require "vimwiki_markdown/options" 3 | require "vimwiki_markdown/template" 4 | require "vimwiki_markdown/vimwiki_link" 5 | require "vimwiki_markdown/wiki_body" 6 | require "vimwiki_markdown/exceptions" 7 | 8 | module VimwikiMarkdown 9 | def self.convert_wikimarkdown_to_html 10 | ::I18n.enforce_available_locales = false 11 | 12 | options = Options.new 13 | template_html = Template.new(options) 14 | body_html = WikiBody.new(options) 15 | 16 | return if body_html.to_s =~ /%nohtml/ 17 | 18 | combined_body_template = template_html.to_s.gsub('%content%', body_html.to_s) 19 | 20 | File.write(options.output_fullpath, combined_body_template) 21 | 22 | rescue MissingRequiredParamError => e 23 | warn e.message 24 | exit(0) 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/exceptions.rb: -------------------------------------------------------------------------------- 1 | module VimwikiMarkdown 2 | class MissingRequiredParamError < StandardError 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/options.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/inflector' 2 | 3 | module VimwikiMarkdown 4 | class Options 5 | DEFAULTS = ["1", #force - 1/0 6 | "markdown", 7 | "md", 8 | "~/vimwiki/site_html/", 9 | "~/vimwiki/index.md", 10 | "~/vimwiki/site_html/style.css", 11 | "~/vimwiki/templates/", 12 | "default", 13 | ".tpl", 14 | "-"].freeze 15 | 16 | FORCE = 0 17 | SYNTAX = 1 18 | EXTENSION = 2 19 | OUTPUT_DIR = 3 20 | INPUT_FILE = 4 21 | CSS_FILE = 5 22 | TEMPLATE_PATH = 6 23 | TEMPLATE_DEFAULT = 7 24 | TEMPLATE_EXT = 8 25 | ROOT_PATH = 9 26 | 27 | attr_reader :force, :syntax, :extension, :output_dir, 28 | :input_file, :css_file, :template_path, 29 | :template_default, :template_ext, :root_path 30 | 31 | =begin force : [0/1] overwrite an existing file 32 | syntax : the syntax chosen for this wiki 33 | extension : the file extension for this wiki 34 | output_dir : the full path of the output directory, i.e. 'path_html' 35 | input_file : the full path of the wiki page 36 | css_file : the full path of the css file for this wiki 37 | template_path : the full path to the wiki's templates 38 | template_default : the default template name 39 | template_ext : the extension of template files 40 | root_path : a count of ../ for pages buried in subdirs 41 | if you have wikilink [[dir1/dir2/dir3/my page in a subdir]] 42 | then e %root_path% is replaced by '../../../'. 43 | =end 44 | 45 | def initialize 46 | @force = arguments[FORCE] == "1" ? true : false 47 | @syntax = arguments[SYNTAX] 48 | @extension = ".#{arguments[EXTENSION]}" 49 | @output_dir = arguments[OUTPUT_DIR] 50 | @input_file = arguments[INPUT_FILE] 51 | @css_file = arguments[CSS_FILE] 52 | @template_path = arguments[TEMPLATE_PATH] 53 | @template_default = arguments[TEMPLATE_DEFAULT] 54 | @template_ext = arguments[TEMPLATE_EXT] 55 | @root_path = arguments[ROOT_PATH] 56 | @root_path = "./" if @root_path == "-" 57 | raise "Must be markdown" unless syntax == 'markdown' 58 | end 59 | 60 | def template_filename 61 | "#{template_path}#{template_default}#{template_ext}" 62 | end 63 | 64 | def self.arguments 65 | ARGV.empty? ? DEFAULTS : ARGV 66 | end 67 | 68 | def title 69 | File.basename(input_file, "#{extension}").capitalize 70 | end 71 | 72 | def output_fullpath 73 | filename = title.parameterize =~ /^\s*$/ ? title : title.parameterize 74 | "#{output_dir}#{filename}.html" 75 | end 76 | 77 | 78 | private 79 | 80 | def arguments 81 | Options.arguments 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/template.rb: -------------------------------------------------------------------------------- 1 | require 'rouge' 2 | require 'date' 3 | 4 | module VimwikiMarkdown 5 | class Template 6 | 7 | def initialize(options) 8 | @options = options 9 | get_template_contents 10 | 11 | validate_template 12 | end 13 | 14 | def to_s 15 | fixtags(template) 16 | end 17 | 18 | 19 | private 20 | 21 | attr_reader :options, :template 22 | 23 | def get_template_contents 24 | file = File.open(options.template_filename, "r") 25 | @template = file.read 26 | end 27 | 28 | def fixtags(template) 29 | @template = template.gsub('%title%',title) 30 | .gsub(pygments_marker,pygments_wrapped_in_tags) 31 | .gsub('%root_path%', root_path) 32 | .gsub('%date%', Date.today.strftime("%e %b %Y")) 33 | end 34 | 35 | def pygments_wrapped_in_tags 36 | Rouge::Themes::Github.dark! if dark_template? 37 | 38 | "" 41 | end 42 | 43 | def root_path 44 | options.root_path 45 | end 46 | 47 | def title 48 | options.title 49 | end 50 | 51 | def validate_template 52 | return if dark_template? || regular_template? 53 | 54 | raise MissingRequiredParamError.new("ERROR: vimwiki template must contain %pygments% placeholder token. Please visit https://github.com/patrickdavey/vimwiki_markdown for more information") 55 | end 56 | 57 | def pygments_marker 58 | dark_template? ? "%dark_pygments%" : "%pygments%" 59 | end 60 | 61 | def dark_template? 62 | @template =~ /%dark_pygments%/ 63 | end 64 | 65 | def regular_template? 66 | @template =~ /%pygments%/ 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/version.rb: -------------------------------------------------------------------------------- 1 | module VimwikiMarkdown 2 | VERSION = "0.9.3".freeze 3 | end 4 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/vimwiki_link.rb: -------------------------------------------------------------------------------- 1 | # This class takes in a string of a markdown link and spits out 2 | # a correctly formed markdown link, with absolute and relative 3 | # links to markdown files correctly altered. 4 | # 5 | # The main thing we're working around is that markdown files can 6 | # be linked to with (or without) an extension. That and we're also 7 | # rewiring the filenames to be parameterized 8 | 9 | 10 | module VimwikiMarkdown 11 | class VimwikiLink 12 | MARKDOWN_LINK_REGEX = /\[(?.*)\]\((?<uri>(?:(?!#).)*)(?<fragment>(?:#)?.*)\)/ 13 | 14 | attr_reader :title, :uri, :fragment, :source_markdown_directory, :markdown_extension, :root_path, :output_dir 15 | 16 | def initialize(markdown_link, source_markdown_filepath, markdown_extension, root_path, output_dir) 17 | @title = markdown_link.match(MARKDOWN_LINK_REGEX)[:title] 18 | @uri = markdown_link.match(MARKDOWN_LINK_REGEX)[:uri] 19 | @fragment = markdown_link.match(MARKDOWN_LINK_REGEX)[:fragment] 20 | @markdown_extension = markdown_extension 21 | @root_path = root_path 22 | @source_markdown_directory = Pathname.new(source_markdown_filepath).dirname 23 | @output_dir = output_dir 24 | rewrite_local_links! 25 | end 26 | 27 | 28 | def to_s 29 | "[#{title}](#{uri}#{fragment})" 30 | end 31 | 32 | private 33 | 34 | def rewrite_local_links! 35 | if vimwiki_markdown_file_exists? 36 | path = Pathname.new(uri) 37 | 38 | link_path = path.basename(markdown_extension).to_s.parameterize 39 | 40 | link_path = path.basename(markdown_extension).to_s if link_path.match(/^\s*$/) 41 | 42 | @uri = "#{path.dirname + link_path}.html" 43 | @fragment = fragment.parameterize.prepend("#") unless fragment.empty? 44 | elsif /^file:/.match(uri) 45 | # begins with file: -> force absolute path if file exists 46 | @uri = "#{source_markdown_directory + uri}" if uri_relative_path_exists? 47 | elsif /^local:/.match(uri) 48 | # begins with local: -> force relative path if file exists 49 | source = Pathname.new(source_markdown_directory) 50 | output = Pathname.new(output_dir) 51 | @uri = "#{source.relative_path_from(output) + uri}" if uri_relative_path_exists? 52 | end 53 | end 54 | 55 | def uri_relative_path_exists? 56 | # remove file: or local: prefix 57 | tmp = uri.sub(/^file:|^local:/, "") if uri.present? 58 | path, title = tmp.split(/\.?\s+\"/) # handle image title 59 | path = Pathname.new(path) 60 | path = path.realpath.relative_path_from(source_markdown_directory) if path.absolute? 61 | 62 | if File.exist?(source_markdown_directory + path) 63 | title = "\"#{title}" unless title.nil? || title.empty? 64 | @uri = "#{path.to_s.gsub(/\ /, '%20')} #{title}".strip 65 | return true 66 | end 67 | false 68 | end 69 | 70 | def vimwiki_markdown_file_exists? 71 | File.exist?((source_markdown_directory + uri).sub_ext(markdown_extension)) || 72 | absolute_path_to_markdown_file_exists? 73 | end 74 | 75 | def absolute_path_to_markdown_file_exists? 76 | path = Pathname(uri) 77 | filepath = Pathname.new(source_markdown_directory + root_path + path.to_s.sub(/^\//,"")). 78 | sub_ext(markdown_extension) 79 | 80 | path.absolute? && File.exist?(filepath) 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/vimwiki_toc_filter.rb: -------------------------------------------------------------------------------- 1 | require "cgi" 2 | 3 | class VimwikiTOCFilter < HTML::Pipeline::TableOfContentsFilter 4 | def call 5 | result[:toc] = String.new('') 6 | 7 | headers = Hash.new(1) 8 | doc.css('h1, h2, h3, h4, h5, h6').each do |node| 9 | text = node.text 10 | id = ascii_downcase(text) 11 | id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation 12 | id.tr!(' ', '-') # replace spaces with dash 13 | 14 | uniq = headers[id] > 1 ? "-#{headers[id]}" : '' 15 | headers[id] += 1 16 | if header_content = node.children.first 17 | result[:toc] << %(<li><a href="##{id}#{uniq}">#{CGI.escape_html(text)}</a></li>\n) 18 | header_content.add_previous_sibling(%(<a id="#{id}#{uniq}" class="anchor" href="##{id}#{uniq}" aria-hidden="true">#{anchor_icon}</a>)) 19 | end 20 | end 21 | result[:toc] = %(<ul class="section-nav">\n#{result[:toc]}</ul>) unless result[:toc].empty? 22 | doc 23 | end 24 | 25 | if RUBY_VERSION >= '2.4' 26 | def ascii_downcase(str) 27 | str.downcase(:ascii) 28 | end 29 | else 30 | def ascii_downcase(str) 31 | str.downcase 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/vimwiki_markdown/wiki_body.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/inflector' 2 | require 'github/markup' 3 | require 'html/pipeline' 4 | require 'pathname' 5 | require "vimwiki_markdown/vimwiki_link" 6 | require "vimwiki_markdown/vimwiki_toc_filter" 7 | 8 | class VimwikiMarkdown::WikiBody 9 | 10 | def initialize(options) 11 | @options = options 12 | end 13 | 14 | def to_s 15 | hack_replace_commonmarker_proc! 16 | 17 | @markdown_body = get_wiki_markdown_contents 18 | fixlinks 19 | html = GitHub::Markup.render_s( 20 | GitHub::Markups::MARKUP_MARKDOWN, 21 | markdown_body, 22 | options: { commonmarker_opts: [:UNSAFE] } 23 | ) 24 | 25 | pipeline = HTML::Pipeline.new([ 26 | HTML::Pipeline::SyntaxHighlightFilter, 27 | VimwikiTOCFilter 28 | ], { scope: "highlight"}) 29 | @result = pipeline.call(html) 30 | @result = @result[:output].to_s 31 | enrich_li_class! 32 | end 33 | 34 | 35 | private 36 | 37 | attr_reader :options, :markdown_body 38 | 39 | def get_wiki_markdown_contents 40 | file = File.open(options.input_file, "r") 41 | file.read 42 | end 43 | 44 | def fixlinks 45 | convert_wiki_style_links_with_title_bar! 46 | convert_wiki_style_links! 47 | convert_markdown_local_links! 48 | end 49 | 50 | def convert_wiki_style_links_with_title_bar! 51 | wiki_bar = /\[\[(?<source>.*)\|(?<title>.*)\]\]/ 52 | @markdown_body.gsub!(wiki_bar) do 53 | source = Regexp.last_match[:source] 54 | title = Regexp.last_match[:title] 55 | "[#{title}](#{source})" 56 | end 57 | end 58 | 59 | def convert_wiki_style_links! 60 | @markdown_body.gsub!(/\[\[(.*?)\]\]/) do 61 | link= Regexp.last_match[1] 62 | "[#{link}](#{link})" 63 | end 64 | end 65 | 66 | def convert_markdown_local_links! 67 | @markdown_body = @markdown_body.gsub(/\[.*?\]\(.*?\)/) do |match| 68 | VimwikiMarkdown::VimwikiLink.new(match, options.input_file, options.extension, options.root_path, options.output_dir).to_s 69 | end 70 | end 71 | 72 | def hack_replace_commonmarker_proc! 73 | GitHub::Markup::Markdown::MARKDOWN_GEMS["commonmarker"] = proc { |content, options: {}| 74 | commonmarker_opts = [:GITHUB_PRE_LANG].concat(options.fetch(:commonmarker_opts, [])) 75 | commonmarker_exts = options.fetch(:commonmarker_exts, [:autolink, :table, :strikethrough]) 76 | CommonMarker.render_html(content, commonmarker_opts, commonmarker_exts) 77 | } 78 | end 79 | 80 | def enrich_li_class! 81 | syms_hash = { " ]" => 0, ".]" => 1, "o]" => 2, "O]" => 3, "X]" => 4 } 82 | checkbox = /<li>\s*\[[\s.oOX]\]/ 83 | checkbox_start = /<li>\s*\[/ 84 | @result.gsub!(checkbox) do |m| 85 | m.sub(checkbox_start, '<li class="done') 86 | .sub(/[\s.oOX\]]*$/, syms_hash) << '">' 87 | end 88 | @result 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/lib/vimwiki_markdown/options_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'vimwiki_markdown/options' 3 | 4 | module VimwikiMarkdown 5 | describe Options do 6 | subject { Options.new } 7 | 8 | context "no options passed" do 9 | before do 10 | allow(Options).to receive(:arguments).and_return(Options::DEFAULTS) 11 | end 12 | 13 | its(:force) { should be(true) } 14 | its(:syntax) { should eq('markdown') } 15 | its(:template_filename) { should eq('~/vimwiki/templates/default.tpl') } 16 | 17 | describe "extension" do 18 | it "deals with a different wiki extension correctly" do 19 | allow(Options).to receive(:arguments).and_return( 20 | ["1", #force - 1/0 21 | "markdown", 22 | "wiki", 23 | "~/vimwiki/site_html/", 24 | "~/vimwiki/index.wiki", 25 | "~/vimwiki/site_html/style.css", 26 | "~/vimwiki/templates/", 27 | "default", 28 | ".tpl", 29 | "-"] 30 | ) 31 | 32 | expect(Options.new.title).to eq("Index") 33 | end 34 | end 35 | 36 | describe "#output_fullpath" do 37 | it "must rewrite files so that they match the paramaterized title" do 38 | expect(Options.new.output_fullpath).to eq("#{subject.output_dir}#{subject.title.parameterize}.html") 39 | end 40 | 41 | it "must correctly deal with filenames with spaces in them" do 42 | allow_any_instance_of(Options).to receive(:input_file) { "~/foo/name with spaces.md" } 43 | expect(Options.new.output_fullpath).to eq("#{subject.output_dir}name-with-spaces.html") 44 | end 45 | 46 | it "must not change filenames if paramteriezed returns an empty string" do 47 | allow_any_instance_of(Options).to receive(:input_file) { "~/foo/世界.md" } 48 | expect(Options.new.output_fullpath).to eq("#{subject.output_dir}世界.html") 49 | end 50 | 51 | it "must correctly deal with filenames with capitalization issues" do 52 | allow_any_instance_of(Options).to receive(:input_file) { "~/foo/NAME WITH SPACES.md" } 53 | expect(Options.new.output_fullpath).to eq("#{subject.output_dir}name-with-spaces.html") 54 | end 55 | 56 | it "must correctly deal with filenames with spaces and a different extension" do 57 | allow_any_instance_of(Options).to receive(:extension) { "wiki" } 58 | allow_any_instance_of(Options).to receive(:input_file) { "~/foo/name with spaces.wiki" } 59 | expect(Options.new.output_fullpath).to eq("#{subject.output_dir}name-with-spaces.html") 60 | end 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /spec/lib/vimwiki_markdown/template_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'vimwiki_markdown/options' 3 | require 'vimwiki_markdown/template' 4 | require 'vimwiki_markdown/exceptions' 5 | require 'rspec-html-matchers' 6 | require 'date' 7 | 8 | module VimwikiMarkdown 9 | describe Template do 10 | let(:options) { Options.new } 11 | 12 | context "template" do 13 | 14 | subject { Template.new(options).to_s } 15 | before do 16 | allow(Options).to receive(:arguments).and_return(Options::DEFAULTS) 17 | allow(File).to receive(:open).with(options.template_filename,"r").and_return(StringIO.new(wiki_template)) 18 | end 19 | 20 | it { should have_tag('title', text: 'Index') } 21 | it { should have_tag('h2', text: 'Index') } 22 | end 23 | 24 | context "missing pygments" do 25 | before do 26 | allow(Options).to receive(:arguments).and_return(Options::DEFAULTS) 27 | end 28 | 29 | it "should raise an invalid exception for missing pygments" do 30 | allow(File).to receive(:open).with(options.template_filename,"r").and_return(StringIO.new(template_missing_pygments)) 31 | expect { Template.new(options).to_s }.to raise_exception(MissingRequiredParamError) 32 | end 33 | end 34 | 35 | context "dark pygments" do 36 | before do 37 | allow(Options).to receive(:arguments).and_return(Options::DEFAULTS) 38 | end 39 | 40 | it "should raise an invalid exception for missing pygments" do 41 | allow(File).to receive(:open).with(options.template_filename, "r").and_return(StringIO.new(dark_pygments)) 42 | expect(Rouge::Themes::Github).to receive(:dark!) { true } 43 | Template.new(options).to_s 44 | end 45 | end 46 | 47 | context "using %root_path%" do 48 | before do 49 | allow(Options).to receive(:arguments).and_return(Options::DEFAULTS) 50 | end 51 | 52 | it "correctly substitute %root_path%" do 53 | allow(File).to receive(:open).with(options.template_filename,"r").and_return(StringIO.new(wiki_template)) 54 | 55 | rendered_template = Template.new(options).to_s 56 | expect(rendered_template).not_to include("%root_path%") 57 | expect(rendered_template).to include("./rootStyle.css") 58 | end 59 | end 60 | 61 | context "using %date" do 62 | before do 63 | allow(Options).to receive(:arguments).and_return(Options::DEFAULTS) 64 | end 65 | 66 | it "replaces %date% with todays date" do 67 | allow(File).to receive(:open).with(options.template_filename,"r").and_return(StringIO.new(wiki_template)) 68 | rendered_template = Template.new(options).to_s 69 | expect(rendered_template).to include(Date.today.strftime("%e %b %Y")) 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/lib/vimwiki_markdown/vimwiki_link_spec.rb: -------------------------------------------------------------------------------- 1 | require "spec_helper" 2 | 3 | module VimwikiMarkdown 4 | describe VimwikiLink do 5 | let(:markdown_extension) { ".md" } 6 | let(:root_path) { "-" } 7 | 8 | context "external or fragment only" do 9 | let(:markdown_link) { "[title](http://www.google.com)" } 10 | let(:source_filepath) { "unimportant" } 11 | let(:output_dir) { "unused in this scenario" } 12 | 13 | it "should leave external links alone" do 14 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 15 | expect(link.to_s).to eq(markdown_link) 16 | end 17 | 18 | it "should not alter fragments which are part of a url" do 19 | markdown_link = "[test](http://foo#Bar)" 20 | 21 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 22 | expect(link.to_s).to eq("[test](http://foo#Bar)") 23 | end 24 | 25 | it "should not alter fragment-only links" do 26 | markdown_link = "[test](#GTD)" 27 | 28 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 29 | expect(link.to_s).to eq("[test](#GTD)") 30 | end 31 | end 32 | 33 | context "with an existing markdown file matching name" do 34 | let(:existing_file) { "test#{markdown_extension}" } 35 | let(:existing_file_no_extension) { existing_file.gsub(/#{markdown_extension}$/,"") } 36 | let(:temp_wiki_dir) { Pathname.new(Dir.mktmpdir("temp_wiki_")) } 37 | let(:markdown_link) { "[test](#{existing_file})" } 38 | let(:source_filepath) { temp_wiki_dir + "index.md" } 39 | let(:output_dir) { temp_wiki_dir + "temp_output_dir" } 40 | 41 | before(:each) do 42 | # here we create a stub test filename in the directory, 43 | FileUtils.mkdir_p((temp_wiki_dir + existing_file).dirname) 44 | FileUtils.mkdir_p(output_dir) 45 | FileUtils.touch(temp_wiki_dir + existing_file) 46 | end 47 | 48 | after(:each) do 49 | FileUtils.rm_r(temp_wiki_dir) 50 | end 51 | 52 | it "must convert same-directory markdown links correctly" do 53 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 54 | expect(link.to_s).to eq("[test](#{existing_file_no_extension}.html)") 55 | end 56 | 57 | it "must convert same-directory markdown links with no extension correctly" do 58 | markdown_link = "[test](#{existing_file_no_extension})" 59 | 60 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 61 | expect(link.to_s).to eq("[test](#{existing_file_no_extension}.html)") 62 | end 63 | 64 | it "must convert same-directory markdown links with url fragments correctly" do 65 | markdown_link = "[test](#{existing_file_no_extension}#Wiki Heading)" 66 | 67 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 68 | expect(link.to_s).to eq("[test](#{existing_file_no_extension}.html#wiki-heading)") 69 | end 70 | 71 | context "with chinese or unparamaterizable chars" do 72 | let(:existing_file) { "世界#{markdown_extension}" } 73 | 74 | it "must convert same-directory markdown links without paramaterization correctly" do 75 | markdown_link = "[test](#{existing_file_no_extension})" 76 | 77 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 78 | expect(link.to_s).to eq("[test](#{existing_file_no_extension}.html)") 79 | end 80 | end 81 | 82 | context "subdirectory linked files" do 83 | let(:existing_file) { "subdirectory/test.md" } 84 | 85 | it "must convert markdown links correctly" do 86 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 87 | expect(link.to_s).to eq("[test](#{existing_file_no_extension}.html)") 88 | end 89 | 90 | it "must convert directory links correctly" do 91 | markdown_link = "[subdirectory](subdirectory/)" 92 | link = VimwikiLink.new(markdown_link, source_filepath, markdown_extension, root_path, output_dir) 93 | expect(link.to_s).to eq("[subdirectory](subdirectory/)") 94 | end 95 | end 96 | 97 | context "../ style links" do 98 | let(:existing_file) { "test.md" } 99 | let(:source_filepath) { temp_wiki_dir + "subdirectory/index.md" } 100 | 101 | it "must convert sub-directory markdown links correctly" do 102 | link = VimwikiLink.new("[test](../test)", source_filepath, markdown_extension, root_path, output_dir) 103 | expect(link.to_s).to eq("[test](../test.html)") 104 | end 105 | end 106 | 107 | context "aboslutely linked files" do 108 | let(:existing_file) { "test.md" } 109 | let(:source_filepath) { temp_wiki_dir + "subdirectory/index.md" } 110 | let(:root_path) { "../"} 111 | 112 | it "must convert absolute paths correctly" do 113 | link = VimwikiLink.new("[test](/test.md)", source_filepath, markdown_extension, root_path, output_dir) 114 | expect(link.to_s).to eq("[test](/test.html)") 115 | end 116 | 117 | it "must convert absolute paths without extension correctly" do 118 | link = VimwikiLink.new("[test](/test)", source_filepath, markdown_extension, root_path, output_dir) 119 | expect(link.to_s).to eq("[test](/test.html)") 120 | end 121 | 122 | context "from the root directory" do 123 | let(:source_filepath) { temp_wiki_dir + "index.md" } 124 | 125 | it "must convert absolute paths correctly" do 126 | link = VimwikiLink.new("[test](/test)", source_filepath, markdown_extension, ".", output_dir) 127 | expect(link.to_s).to eq("[test](/test.html)") 128 | end 129 | end 130 | end 131 | 132 | context "links with local: files" do 133 | let(:sample_png) { "foo.png" } 134 | 135 | before do 136 | FileUtils.touch(temp_wiki_dir + sample_png) 137 | end 138 | 139 | it "must convert local paths correctly" do 140 | link = VimwikiLink.new("[test](local:#{sample_png})", source_filepath, markdown_extension, root_path, output_dir) 141 | expect(link.to_s).to eq("[test](../#{sample_png})") 142 | end 143 | end 144 | 145 | context "links with file: files" do 146 | let(:sample_png) { "foo.png" } 147 | 148 | before do 149 | FileUtils.touch(temp_wiki_dir + sample_png) 150 | end 151 | 152 | it "must convert local paths correctly" do 153 | link = VimwikiLink.new("[test](file:#{sample_png})", source_filepath, markdown_extension, root_path, output_dir) 154 | expect(link.to_s).to eq("[test](#{temp_wiki_dir + sample_png})") 155 | end 156 | end 157 | end 158 | end 159 | end 160 | -------------------------------------------------------------------------------- /spec/lib/vimwiki_markdown/wiki_body_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'vimwiki_markdown/options' 3 | require 'vimwiki_markdown/wiki_body' 4 | require 'rspec-html-matchers' 5 | 6 | module VimwikiMarkdown 7 | describe WikiBody do 8 | 9 | let(:wiki_body) { WikiBody.new(double(:options, input_file: 'blah', extension: 'md', root_path: '-', output_dir: ".")) } 10 | let(:markdown_file_content) { wiki_index_markdown } 11 | 12 | it "must convert wiki links" do 13 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return(markdown_file_content) 14 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 15 | expect(wiki_body.to_s).to match(/<a href="books.html">Books<\/a>/) 16 | expect(wiki_body.to_s).to match(/<a href="bash-tips.html">Bash Tips<\/a>/) 17 | end 18 | 19 | it "must convert wiki links with separate titles correctly" do 20 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("[[http://www.google.com|google]]") 21 | expect(wiki_body.to_s).to match(/<a href="http:\/\/www.google.com">google<\/a>/) 22 | end 23 | 24 | it "must not put a break tag in a blockquote" do 25 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return(markdown_file_content) 26 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 27 | expect(wiki_body.to_s).not_to match(/blockquote<br>/) 28 | end 29 | 30 | it "must leave normal content alone" do 31 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 32 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("hello") 33 | expect(wiki_body.to_s).to match(/hello/) 34 | end 35 | 36 | it "must convert html content correctly" do 37 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 38 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("<p>hello world</p>") 39 | expect(wiki_body.to_s).to include("<p>hello world</p>") 40 | end 41 | 42 | it "must convert unsafe html content correctly" do 43 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 44 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return('<iframe src="test"></iframe>') 45 | expect(wiki_body.to_s).to include('<iframe src="test"></iframe>') 46 | end 47 | 48 | it "must convert multiple links on the same line correctly" do 49 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("[here](here) [there](there)") 50 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 51 | expect(wiki_body.to_s).to match(/<a href="here.html">here<\/a>/) 52 | expect(wiki_body.to_s).to match(/<a href="there.html">there<\/a>/) 53 | end 54 | 55 | it "must enrich task list unchecked" do 56 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 57 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("- [ ] This is one line") 58 | expect(wiki_body.to_s).to match(/<li class="done0"> This is one line<\/li>/) 59 | end 60 | 61 | it "must enrich task list checked" do 62 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 63 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("- [X] This is a checked line") 64 | expect(wiki_body.to_s).to match(/<li class="done4"> This is a checked line<\/li>/) 65 | end 66 | 67 | it "must enrich task list parent 1" do 68 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 69 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("- [.] This is a parent 1 line") 70 | expect(wiki_body.to_s).to match(/<li class="done1"> This is a parent 1 line<\/li>/) 71 | end 72 | 73 | it "must enrich task list parent 2" do 74 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 75 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("- [o] This is a parent 2 line") 76 | expect(wiki_body.to_s).to match(/<li class="done2"> This is a parent 2 line<\/li>/) 77 | end 78 | 79 | it "must enrich task list parent 3" do 80 | allow_any_instance_of(VimwikiMarkdown::VimwikiLink).to receive(:vimwiki_markdown_file_exists?).and_return(true) 81 | allow(wiki_body).to receive(:get_wiki_markdown_contents).and_return("- [O] This is a parent 3 line") 82 | expect(wiki_body.to_s).to match(/<li class="done3"> This is a parent 3 line<\/li>/) 83 | end 84 | 85 | describe "syntax highlighting" do 86 | it "must give correct classes" do 87 | allow(wiki_body).to receive(:get_wiki_markdown_contents) 88 | .and_return("```bash\n find ./path -type f -exec sed -i 's/find_this/replace_this/g' {} \\;\n```\n") 89 | expect(wiki_body.to_s).to match(/highlight/) 90 | end 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'bundler/setup' 2 | require 'pry' 3 | require 'rspec/its' 4 | require 'vimwiki_markdown' 5 | 6 | RSpec.configure do |config| 7 | # rspec-expectations config goes here. You can use an alternate 8 | # assertion/expectation library such as wrong or the stdlib/minitest 9 | # assertions if you prefer. 10 | config.expect_with :rspec do |expectations| 11 | # This option will default to `true` in RSpec 4. It makes the `description` 12 | # and `failure_message` of custom matchers include text for helper methods 13 | # defined using `chain`, e.g.: 14 | # be_bigger_than(2).and_smaller_than(4).description 15 | # # => "be bigger than 2 and smaller than 4" 16 | # ...rather than: 17 | # # => "be bigger than 2" 18 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 19 | end 20 | 21 | # rspec-mocks config goes here. You can use an alternate test double 22 | # library (such as bogus or mocha) by changing the `mock_with` option here. 23 | config.mock_with :rspec do |mocks| 24 | # Prevents you from mocking or stubbing a method that does not exist on 25 | # a real object. This is generally recommended, and will default to 26 | # `true` in RSpec 4. 27 | mocks.verify_partial_doubles = true 28 | end 29 | 30 | # The settings below are suggested to provide a good initial experience 31 | # with RSpec, but feel free to customize to your heart's content. 32 | =begin 33 | # These two settings work together to allow you to limit a spec run 34 | # to individual examples or groups you care about by tagging them with 35 | # `:focus` metadata. When nothing is tagged with `:focus`, all examples 36 | # get run. 37 | config.filter_run :focus 38 | config.run_all_when_everything_filtered = true 39 | 40 | # Limits the available syntax to the non-monkey patched syntax that is recommended. 41 | # For more details, see: 42 | # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax 43 | # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ 44 | # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching 45 | config.disable_monkey_patching! 46 | 47 | # This setting enables warnings. It's recommended, but in some cases may 48 | # be too noisy due to issues in dependencies. 49 | config.warnings = true 50 | 51 | # Many RSpec users commonly either run the entire suite or an individual 52 | # file, and it's useful to allow more verbose output when running an 53 | # individual spec file. 54 | if config.files_to_run.one? 55 | # Use the documentation formatter for detailed output, 56 | # unless a formatter has already been configured 57 | # (e.g. via a command-line flag). 58 | config.default_formatter = 'doc' 59 | end 60 | 61 | # Print the 10 slowest examples and example groups at the 62 | # end of the spec run, to help surface which specs are running 63 | # particularly slow. 64 | config.profile_examples = 10 65 | 66 | # Run specs in random order to surface order dependencies. If you find an 67 | # order dependency and want to debug it, you can fix the order by providing 68 | # the seed, which is printed after each run. 69 | # --seed 1234 70 | config.order = :random 71 | 72 | # Seed global randomization in this process using the `--seed` CLI option. 73 | # Setting this allows you to use `--seed` to deterministically reproduce 74 | # test failures related to randomization by passing the same `--seed` value 75 | # as the one that triggered the failure. 76 | Kernel.srand config.seed 77 | =end 78 | end 79 | 80 | def wiki_index_markdown 81 | " 82 | ## Patrick Davey personal Wiki 83 | * [[Books]] -- to read 84 | * [[Vim Tips]]-- anything to do with vim. 85 | * [[Git Tips]]-- anything to do with git. 86 | * [[Bash Tips]]-- anything to do with bash. 87 | * [[Mysql Tips]]-- anything to do with mysql. 88 | * [[css - responsive - design Tips]]-- anything to do with css etc.. 89 | * [[Refinery]]-- useful Refinery Stuff 90 | * [[Backbone]]-- useful Backbone Stuff 91 | * [[Tmux]]-- useful Tmux Stuff 92 | * [[Rails]]-- useful Rails Stuff 93 | * [[Scratchpad]] temporary stuff. 94 | * [[Server Setup]] -- checklist to setup a server. 95 | * [[Todo]] -- things to do 96 | * [[Quotes]] -- Nothing to do with programming! 97 | * [[Movies to watch]] -- Movies to watch 98 | * [[lent items]] 99 | * [[bike stuff]] 100 | * [[raspberrypi]] 101 | 102 | 103 | ## Languages 104 | * [[Ruby]]-- useful Ruby Stuff 105 | * [[iOS]]-- useful iOS Stuff 106 | * [[JavaScript]]-- useful JS Stuff 107 | 108 | > this is a blockquote 109 | > without a linebreak 110 | 111 | ## Test for checks 112 | 113 | - [ ] This is one line 114 | - [X] This is a checked line 115 | - [ ] This is a parent line 1 116 | - [ ] This is a child line 1 117 | - [ ] This is a child line 2 118 | - [.] This is a parent line 2 119 | - [X] This is a child line 1 120 | - [ ] This is a child line 2 121 | - [ ] This is a child line 3 122 | - [o] This is a parent line 2 123 | - [X] This is a child line 1 124 | - [X] This is a child line 2 125 | - [ ] This is a child line 3 126 | - [O] This is a parent line 3 127 | - [X] This is a child line 1 128 | - [X] This is a child line 2 129 | - [X] This is a child line 3 130 | - [ ] This is a child line 4 131 | 132 | " 133 | end 134 | 135 | def wiki_template 136 | <<-WIKITEMPLATE 137 | <!DOCTYPE html> 138 | <html lang="en"> 139 | <head> 140 | <meta charset="utf-8"> 141 | <link type="text/css" rel="stylesheet" href="./style.css" /> 142 | <link type="text/css" rel="stylesheet" href="./styles/bootstrap.min.css" /> 143 | <link type="text/css" rel="stylesheet" href="./overrides.css" /> 144 | <link type="text/css" rel="stylesheet" href="./styles/shCore.css" /> 145 | <link type="text/css" rel="stylesheet" href="./styles/shThemeDefault.css" /> 146 | 147 | <!-- for testing %ROOT_PATH% substitutions --> 148 | <link type="text/css" rel="stylesheet" href="%root_path%rootStyle.css" /> 149 | 150 | <script type="text/javascript" src="./scripts/shCore.js"></script> 151 | <script type="text/javascript" src="./scripts/shBrushRuby.js"></script> 152 | <script type="text/javascript" src="./scripts/shObjectiveC.js"></script> 153 | <script type="text/javascript" src="./scripts/shBrushBash.js"></script> 154 | <script type="text/javascript" src="./scripts/shBrushJScript.js"></script> 155 | <script type="text/javascript"> 156 | SyntaxHighlighter.all(); 157 | </script> 158 | <title>%title% 159 | 160 | 161 | %pygments% 162 | 163 | 164 | 171 | 172 |
173 |
174 |
175 |

%title%

176 |

Page created on %date%

177 | %content% 178 |
179 |
180 |
181 | 182 | 183 | WIKITEMPLATE 184 | end 185 | 186 | def template_missing_pygments 187 | wiki_template.gsub!("%pygments%", "") 188 | end 189 | 190 | def dark_pygments 191 | wiki_template.gsub!("%pygments%", "%dark_pygments%") 192 | end 193 | -------------------------------------------------------------------------------- /vimwiki_markdown.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'vimwiki_markdown/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "vimwiki_markdown" 8 | spec.version = VimwikiMarkdown::VERSION 9 | spec.authors = ["Patrick Davey"] 10 | spec.email = ["patrick.davey@gmail.com"] 11 | spec.summary = %q{Converts a github flavoured markdown vimwiki file into html.} 12 | spec.description = %q{Converts a vimwiki markdown file to html. It parses [[links]] and has support for syntax highlighting.} 13 | spec.homepage = "https://github.com/patrickdavey/wimwiki_markdown" 14 | spec.license = "MIT" 15 | spec.required_ruby_version = ">= 2.7" 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_development_dependency "bundler" 22 | spec.add_development_dependency "guard-rspec", "~> 4.3" 23 | spec.add_development_dependency "pry", "~> 0.12" 24 | spec.add_development_dependency "rake", "~> 12.3" 25 | spec.add_development_dependency "rspec", "~> 3.0" 26 | spec.add_development_dependency "rspec-html-matchers", "~> 0.6.1" 27 | spec.add_development_dependency "rspec-its", "~> 1.1" 28 | spec.add_development_dependency "rubocop" 29 | spec.add_development_dependency "solargraph" 30 | 31 | spec.add_runtime_dependency "activesupport", "~> 6.1" 32 | spec.add_runtime_dependency "commonmarker", "~> 0.23.4" 33 | spec.add_runtime_dependency "escape_utils", "~> 1.2" 34 | spec.add_runtime_dependency "github-markup", "~> 3.0" 35 | spec.add_runtime_dependency "html-pipeline", "~> 2.0" 36 | spec.add_runtime_dependency "rouge", "~> 4.0" 37 | end 38 | --------------------------------------------------------------------------------