diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .sass-cache .user-doc-cache .vagrant +abc_md_docs # general .DS_Store diff --git a/Gemfile b/Gemfile --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,4 @@ gem "jekyll", "~> 4.1" gem 'jekyll-paginate' +gem 'jekyll-relative-links' diff --git a/Gemfile.lock b/Gemfile.lock --- a/Gemfile.lock +++ b/Gemfile.lock @@ -30,6 +30,8 @@ safe_yaml (~> 1.0) terminal-table (~> 1.8) jekyll-paginate (1.1.0) + jekyll-relative-links (0.6.1) + jekyll (>= 3.3, < 5.0) jekyll-sass-converter (2.1.0) sassc (> 2.0.1, < 3.0) jekyll-watch (2.2.1) @@ -64,6 +66,7 @@ DEPENDENCIES jekyll (~> 4.1) jekyll-paginate + jekyll-relative-links BUNDLED WITH 2.1.4 diff --git a/_config.yml b/_config.yml --- a/_config.yml +++ b/_config.yml @@ -182,6 +182,11 @@ plugins: - jekyll-paginate + - jekyll-relative-links + +relative_links: + enabled: true + collections: false # Beautiful Jekyll / Dean Attali # 2fc73a3a967e97599c9763d05e564189 diff --git a/_plugins/markdown-override-broken-links.rb b/_plugins/markdown-override-broken-links.rb new file mode 100644 --- /dev/null +++ b/_plugins/markdown-override-broken-links.rb @@ -0,0 +1,108 @@ +require 'jekyll' +require 'pathname' +require 'uri' + +module Jekyll + class MarkdownOverrideBrokenLinks < Generator + attr_accessor :site, :config + + safe true + priority :highest + + def generate(site) + @site = site + + documents = site.pages + + documents.each do |document| + next unless markdown_extension?(document.extname) + next if document.is_a?(StaticFile) + + fix_broken_links(document) + end + end + + def fix_broken_links(doc) + if doc.content.nil?() + return + end + + # Find all the links + links = doc.content.scan(/(\[([^\]]+)\]\(([^ ")]+)[^)]*\))/) + + links.each do |link| + original = link[0].strip() + text = link[1].strip() + url = link[2].strip() + + # The external links and local anchors will render valid + next if is_valid_link?(url) + + # Relative links to markdown files will be converted by the + # jekyll-relative-links plugin and are considered valid. + # The plugin won't match the links relative to project root (starting + # with a '/') if they are located in a subdirectory, so we need to fix + # the link in this case. + if is_markdown_link?(url) + # Relative links don't need to be fixed + next if !is_project_root_relative_link?(url) + + # Convert first both the link and the source markdown paths to absolute + absolute_link = Pathname.new(get_doc_root(doc)).join(url[1..]) + absolute_doc_path = Pathname.new(site.source).join(doc.relative_path) + + # Now we can compute the link relative to the source markdown path + relative_link = absolute_link.relative_path_from(absolute_doc_path.dirname()).to_s() + + doc.content.gsub!(original, "[#{text}](#{relative_link})") + next + end + + # Other links are broken, update them with "text (_url_)" + doc.content.gsub!(original, "#{text} (`#{url}`)") + end + + return + end + + def get_doc_root(doc) + doc_root = File.dirname(doc.relative_path) + doc_root.slice!(File.dirname(doc.url)) + return File.join(site.source, doc_root) + end + + def is_project_root_relative_link?(link_url) + return link_url.start_with?("/") + end + + def is_valid_link?(url) + return is_external_link?(url) || is_lone_anchor?(url) + end + + def is_external_link?(link_url) + uri = URI.parse(link_url) + return !uri.scheme.nil? + end + + def is_lone_anchor?(link_url) + uri = URI.parse(link_url) + return (uri.path.nil? || uri.path.empty?) && !uri.fragment.nil? + end + + def is_markdown_link?(link_url) + uri = URI.parse(link_url) + return uri.path.end_with?(".md") + end + + def markdown_extension?(extension) + markdown_converter.matches(extension) + end + + def markdown_converter + @markdown_converter ||= site.find_converter_instance(Converters::Markdown) + end + end +end + + + diff --git a/scripts/fetch_documentation.sh b/scripts/fetch_documentation.sh --- a/scripts/fetch_documentation.sh +++ b/scripts/fetch_documentation.sh @@ -166,3 +166,26 @@ done +# Pull all the markdown files from the ABC repository so they can be converted +# and rendered by jekyll. The tree directory structure is preserved in order to +# keep the links working. +pushd "${SRC_DIR}" +git checkout master + +ABC_MD_DOCS_BASE="${TOPLEVEL}/abc_md_docs" +mkdir -p "${ABC_MD_DOCS_BASE}" + +FILES=($(git ls-files "*.md")) + +for FILE in "${FILES[@]}" +do + FILE_DST="${ABC_MD_DOCS_BASE}/${FILE}" + mkdir -p "$(dirname ${FILE_DST})" + + NAME="${FILE}" \ + PERMALINK="/${FILE%.*}.html" \ + envsubst < "${TOPLEVEL}/scripts/md_docs_frontmatter.yml.in" > "${FILE_DST}" + cat "${FILE}" >> "${FILE_DST}" +done + +popd diff --git a/scripts/md_docs_frontmatter.yml.in b/scripts/md_docs_frontmatter.yml.in new file mode 100644 --- /dev/null +++ b/scripts/md_docs_frontmatter.yml.in @@ -0,0 +1,5 @@ +--- +category: doc +name: ${NAME} +permalink: ${PERMALINK} +---