mirror of
https://github.com/JetBrains/intellij-sdk-code-samples.git
synced 2025-07-30 18:27:49 +08:00
Added Docs engine
This commit is contained in:
parent
e247d36399
commit
c3082ea173
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
_site
|
||||
_includes/page.html
|
||||
app
|
||||
HelpTOC.json
|
14
Rakefile
Normal file
14
Rakefile
Normal file
@ -0,0 +1,14 @@
|
||||
CONFIG = {
|
||||
:source_dir => __dir__,
|
||||
:tmp_dir => "#{__dir__}/_tmp",
|
||||
:build_destination => "_site",
|
||||
:preview_host => "0.0.0.0",
|
||||
:preview_port => 4000,
|
||||
:default_env => 'dev'
|
||||
}
|
||||
|
||||
Dir['_rake/*.rake'].each { |r| load r }
|
||||
|
||||
task :default do
|
||||
system('rake -T')
|
||||
end
|
10
_SUMMARY.md
Normal file
10
_SUMMARY.md
Normal file
@ -0,0 +1,10 @@
|
||||
<!--
|
||||
Similar to GitBook SUMMARY.md - https://github.com/GitbookIO/gitbook#summarymd,
|
||||
but list items without links will not br included in the table of contents.
|
||||
Also you can use HTML-comments.
|
||||
-->
|
||||
|
||||
## Getting started
|
||||
* [Getting started with SDK](index.html)
|
||||
* Some planned topic
|
||||
<!-- * [Another planned topic](topic.html) -->
|
22
_config.yml
Normal file
22
_config.yml
Normal file
@ -0,0 +1,22 @@
|
||||
product_name: IntelliJ SDK
|
||||
product_version:
|
||||
|
||||
markdown: kramdown
|
||||
markdown_ext: foo
|
||||
kramdown:
|
||||
input: GFM2
|
||||
hard_wrap: false
|
||||
auto_ids: false
|
||||
highlighter: pygments
|
||||
|
||||
exclude:
|
||||
- '*.scss'
|
||||
- README*
|
||||
- Rakefile
|
||||
- lib
|
||||
- webhelp-template
|
||||
- code_samples
|
||||
|
||||
defaults:
|
||||
- values:
|
||||
layout: 'webhelp'
|
5
_includes/head.html
Normal file
5
_includes/head.html
Normal file
@ -0,0 +1,5 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
|
||||
<link rel="stylesheet" href="styles/styles.css">
|
32
_layouts/webhelp.html
Normal file
32
_layouts/webhelp.html
Normal file
@ -0,0 +1,32 @@
|
||||
{% capture _t %}
|
||||
{% assign product_name = site.product_name %}
|
||||
{% assign product_version = site.product_version %}
|
||||
{% assign page_title = page.title %}
|
||||
{% assign page_title_with_h1 = '' %}
|
||||
{% assign page_id = page.name | replace:'.md','' %}
|
||||
{% assign page_content = content %}
|
||||
{% capture shortcut_switcher %}
|
||||
<div class="shortcuts-switcher"><label for="switch-shortcuts">Keymap:</label><select id="switch-shortcuts" class="select _shortcuts" height="1">
|
||||
<option data-group="primary" value="default" selected>Default</option>
|
||||
<option data-group="primary" value="default_for_gnome">GNOME</option>
|
||||
<option data-group="primary" value="default_for_kde">KDE</option>
|
||||
<option data-group="primary" value="default_for_xwin">XWindow</option>
|
||||
<option data-group="primary" value="emacs">Emacs</option>
|
||||
<option data-group="primary" value="jbuilder">JBuilder</option>
|
||||
<option data-group="primary" value="visual_studio">Visual Studio</option>
|
||||
<option data-group="primary" value="netbeans_6.5">NetBeans 6.5</option>
|
||||
<option data-group="primary" value="eclipse">Eclipse</option>
|
||||
<option data-group="secondary" value="mac_os_x_10.5_">OS X 10.5+</option>
|
||||
<option data-group="secondary" value="mac_os_x">OS X</option>
|
||||
<option data-group="secondary" value="eclipse_mac_os_x">OS X Eclipse</option></select>
|
||||
</div>
|
||||
{% endcapture %}
|
||||
{% assign is_show_shortcut_switcher = 'false' %}
|
||||
{% assign current_year = 'now' | date:'%Y' %}
|
||||
{% assign last_modified = '' %}
|
||||
{% assign disqus = '' %}
|
||||
{% assign baseurl = '.' %}
|
||||
|
||||
{% endcapture %}
|
||||
{% capture rendered_content %}{% include page.html %}{% endcapture %}
|
||||
{{ rendered_content | replace:'</head>','<link rel="stylesheet" href="styles/styles.css"></head>' }}
|
154
_plugins/markdown_converter.rb
Normal file
154
_plugins/markdown_converter.rb
Normal file
@ -0,0 +1,154 @@
|
||||
require 'kramdown'
|
||||
require 'pygments'
|
||||
|
||||
module Kramdown
|
||||
module Converter
|
||||
class Upsrc < Html
|
||||
|
||||
def convert_header(el, indent)
|
||||
attr = el.attr.dup
|
||||
el_id = generate_id(el.options[:raw_text])
|
||||
|
||||
if @options[:auto_ids] && !attr['id']
|
||||
attr['id'] = el_id
|
||||
end
|
||||
@toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el)
|
||||
level = output_header_level(el.options[:level])
|
||||
|
||||
if level <= 3
|
||||
anchor = Element.new(:a, nil, {'href' => '#' + el_id, 'class' => 'anchor-link'})
|
||||
el.children.push(anchor)
|
||||
end
|
||||
|
||||
anchor = format_as_block_html("a", {'name' => el_id, 'class' => 'elem-anchor'}, inner(Element.new(:a, nil), indent), indent)
|
||||
header = format_as_block_html("h#{level}", attr, inner(el, indent), indent)
|
||||
anchor + header
|
||||
end
|
||||
|
||||
def convert_codeblock(el, indent)
|
||||
attr = el.attr.dup
|
||||
lang = self.extract_code_language(attr) || 'text'
|
||||
highlight_lines = ''
|
||||
|
||||
if attr['class'] and attr['class'].scan(/\{[\d\-\,]+\}/).length > 0
|
||||
lang_parts = attr['class'].split('{')
|
||||
highlight_lines = "{#{lang_parts[1]}"
|
||||
end
|
||||
|
||||
code = pygmentize(el.value, lang, highlight_lines)
|
||||
code_attr = {}
|
||||
code_attr['class'] = "code-block__wrapper"
|
||||
code_attr['class'] += " code-block _highlighted lang_#{lang}" if lang
|
||||
|
||||
"<pre><code#{html_attributes(code_attr)}>#{code}</code></pre>\n"
|
||||
end
|
||||
|
||||
# Extract the code block/span language from the attributes.
|
||||
def extract_code_language(attr)
|
||||
if attr['class']
|
||||
class_attr = attr['class']
|
||||
|
||||
if class_attr.scan(/\{|\}/).length > 0
|
||||
class_attr = class_attr.split('{')[0]
|
||||
end
|
||||
|
||||
class_attr.scan(/\blanguage-(\w+)\b/).first.first
|
||||
end
|
||||
end
|
||||
|
||||
def convert_codespan(el, indent)
|
||||
attr = el.attr.dup
|
||||
lang = extract_code_language!(attr) || 'text'
|
||||
code = pygmentize(el.value, lang)
|
||||
attr['class'] = 'code'
|
||||
attr['class'] += " highlight language-#{lang}" if lang
|
||||
"<code#{html_attributes(attr)}>#{code}</code>"
|
||||
end
|
||||
|
||||
def convert_blockquote(el, indent)
|
||||
format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent)
|
||||
end
|
||||
|
||||
def convert_a(el, indent)
|
||||
res = inner(el, indent)
|
||||
attr = el.attr.dup
|
||||
attr['href'] = '' if attr['href'].nil?
|
||||
is_external = attr['href'].start_with?('http://', 'https://', 'ftp://', '//')
|
||||
attr['data-bypass'] = 'yes' if is_external
|
||||
if attr['href'].start_with?('mailto:')
|
||||
mail_addr = attr['href'][7..-1]
|
||||
attr['href'] = obfuscate('mailto') << ":" << obfuscate(mail_addr)
|
||||
res = obfuscate(res) if res == mail_addr
|
||||
end
|
||||
format_as_span_html(el.type, attr, "<span>#{res}</span>")
|
||||
end
|
||||
|
||||
def convert_img(el, indent)
|
||||
"<img#{html_attributes(el.attr)} />"
|
||||
end
|
||||
|
||||
def pygmentize(code, lang, highlight_lines = nil)
|
||||
hl_lines = ''
|
||||
|
||||
if highlight_lines
|
||||
hl_lines = highlight_lines.gsub(/[{}]/, '').split(',').map do |ln|
|
||||
if matches = /(\d+)-(\d+)/.match(ln)
|
||||
ln = Range.new(matches[1], matches[2]).to_a.join(' ')
|
||||
end
|
||||
ln
|
||||
end.join(' ')
|
||||
end
|
||||
|
||||
if lang
|
||||
Pygments.highlight(code,
|
||||
:lexer => lang,
|
||||
:options => {
|
||||
:encoding => 'utf-8',
|
||||
:nowrap => true,
|
||||
:hl_lines => hl_lines
|
||||
}
|
||||
)
|
||||
else
|
||||
escape_html(code)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Parser
|
||||
class GFM2 < GFM
|
||||
def parse
|
||||
super
|
||||
end
|
||||
|
||||
FENCED_CODEBLOCK_MATCH = /^(([~`]){3,})\s*?(\w+[\{\}\,\d\-]*?)?\s*?\n(.*?)^\1\2*\s*?\n/m
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Jekyll
|
||||
class KramdownPygments < Jekyll::Converter
|
||||
def matches(ext)
|
||||
ext =~ /^\.md$/i
|
||||
end
|
||||
|
||||
def output_ext(ext)
|
||||
".html"
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
html = Kramdown::Document.new(content, {
|
||||
:auto_ids => @config['kramdown']['auto_ids'],
|
||||
:footnote_nr => @config['kramdown']['footnote_nr'],
|
||||
:hard_wrap => @config['kramdown']['hard_wrap'],
|
||||
:entity_output => @config['kramdown']['entity_output'],
|
||||
:toc_levels => @config['kramdown']['toc_levels'],
|
||||
:smart_quotes => @config['kramdown']['smart_quotes'],
|
||||
:coderay_default_lang => @config['kramdown']['default_lang'],
|
||||
:input => @config['kramdown']['input']
|
||||
}).to_upsrc
|
||||
return html
|
||||
end
|
||||
end
|
||||
end
|
10
_rake/build.rake
Normal file
10
_rake/build.rake
Normal file
@ -0,0 +1,10 @@
|
||||
desc 'Build docs'
|
||||
task :build do
|
||||
dest = ENV['dest'] || CONFIG[:build_destination]
|
||||
|
||||
Rake::Task['build_toc'].invoke
|
||||
Rake::Task['prepare_assets'].invoke
|
||||
|
||||
command = "jekyll build --trace --destination=#{dest}"
|
||||
sh command
|
||||
end
|
13
_rake/build_toc.rake
Normal file
13
_rake/build_toc.rake
Normal file
@ -0,0 +1,13 @@
|
||||
desc 'Build docs table of contents index'
|
||||
task :build_toc do
|
||||
src_dir = CONFIG[:source_dir]
|
||||
toc_file = ENV['dest'] || "#{src_dir}/HelpTOC.json"
|
||||
|
||||
load "#{src_dir}/lib/toc_generator.rb"
|
||||
|
||||
kramdown_config = YAML::load_file("#{src_dir}/_config.yml")['kramdown']
|
||||
toc = Docs::TocGenerator.extract("#{src_dir}/_SUMMARY.md", kramdown_config)
|
||||
|
||||
res = File.write("#{toc_file}", toc.to_json)
|
||||
puts "TOC successfully created in #{toc_file}" if res
|
||||
end
|
22
_rake/prepare_assets.rake
Normal file
22
_rake/prepare_assets.rake
Normal file
@ -0,0 +1,22 @@
|
||||
desc 'Preparing assets'
|
||||
task :prepare_assets do
|
||||
dest = ENV["dest"] || CONFIG[:build_destination]
|
||||
appsrc = 'webhelp-template/app'
|
||||
appdest = 'app'
|
||||
|
||||
# webhelp template
|
||||
RakeFileUtils.cp 'webhelp-template/app/templates/page.html', '_includes'
|
||||
|
||||
# assets dir
|
||||
RakeFileUtils.mkdir_p %W(#{appdest}/css #{appdest}/fonts #{appdest}/img #{appdest}/js/vendor/requirejs)
|
||||
|
||||
# js
|
||||
RakeFileUtils.cp_r "#{appsrc}/js/main.build.js", "#{appdest}/js"
|
||||
RakeFileUtils.cp_r "#{appsrc}/js/vendor/requirejs/require.js", "#{appdest}/js/vendor/requirejs"
|
||||
|
||||
# css
|
||||
RakeFileUtils.cp_r "#{appsrc}/css/styles.min.css", "#{appdest}/css"
|
||||
|
||||
# images & fonts
|
||||
RakeFileUtils.cp_r %W(#{appsrc}/fonts #{appsrc}/img), appdest
|
||||
end
|
11
_rake/preview.rake
Normal file
11
_rake/preview.rake
Normal file
@ -0,0 +1,11 @@
|
||||
desc "Runs site on a local preview webserver"
|
||||
task :preview do
|
||||
host = ENV["host"] || CONFIG[:preview_host]
|
||||
port = ENV["port"] || CONFIG[:preview_port]
|
||||
|
||||
Rake::Task["build_toc"].invoke
|
||||
Rake::Task['prepare_assets'].invoke
|
||||
|
||||
command = "jekyll serve --trace --host=#{host} --port=#{port} --watch --force_polling"
|
||||
sh command
|
||||
end
|
8
index.md
Normal file
8
index.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Getting started
|
||||
---
|
||||
|
||||
# {{ page.title }}
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus doloremque enim explicabo fugiat modi, obcaecati
|
||||
officia sunt unde. A assumenda dolorum hic, in ipsam nisi officia porro praesentium provident sequi.
|
113
lib/toc_generator.rb
Normal file
113
lib/toc_generator.rb
Normal file
@ -0,0 +1,113 @@
|
||||
require 'yaml'
|
||||
require 'json'
|
||||
require 'kramdown'
|
||||
require 'rexml/document'
|
||||
require 'rexml/xpath'
|
||||
|
||||
module Docs
|
||||
class TocGenerator
|
||||
|
||||
ITEM_TYPE_HEADER = 'header'
|
||||
|
||||
# @param path {String} path to Markdown file
|
||||
# @param kramdown_config {Hash} Kramdown config
|
||||
# @return {Hash}
|
||||
def self.extract(path, kramdown_config = {})
|
||||
toc = []
|
||||
content = File.read(path)
|
||||
kramdown_config = kramdown_config.merge({:html_to_native => true})
|
||||
kramdown_doc = Kramdown::Document.new(content, kramdown_config)
|
||||
kramdown_doc_content = <<-XML
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<root>
|
||||
#{kramdown_doc.to_html}
|
||||
</root>
|
||||
XML
|
||||
|
||||
kramdown_doc_content = kramdown_doc_content.gsub(/<!--(.*?)-->/m, '')
|
||||
|
||||
xml = REXML::Document.new kramdown_doc_content
|
||||
xml.elements.each("/root/*") do |node|
|
||||
items = extract_from_node(node)
|
||||
toc.concat(items) if items != nil
|
||||
end
|
||||
|
||||
# Removing headers of empty sections
|
||||
delete_list = []
|
||||
(0).upto(toc.length-1) do |i|
|
||||
item = toc[i]
|
||||
prev = toc[i-1] != nil ? toc[i-1] : nil
|
||||
item_is_header = (item[:type] != nil and item[:type] == self::ITEM_TYPE_HEADER)
|
||||
prev_is_header = (prev != nil and prev[:type] != nil and prev[:type] == self::ITEM_TYPE_HEADER)
|
||||
|
||||
if item_is_header and prev_is_header
|
||||
delete_list.push(i-1)
|
||||
end
|
||||
end
|
||||
|
||||
delete_list.each do |del_index|
|
||||
toc.delete_at(del_index)
|
||||
end
|
||||
|
||||
return toc
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
# @param node {REXML::Node}
|
||||
# @return {Hash}
|
||||
def self.extract_from_node(node)
|
||||
items = []
|
||||
|
||||
case node.name
|
||||
when 'ul'
|
||||
REXML::XPath.each(node, './li') do |node|
|
||||
item = extract_items(node)
|
||||
items.push(item) if item != nil
|
||||
end
|
||||
|
||||
when 'h2'
|
||||
items.push(extract_header(node))
|
||||
end
|
||||
|
||||
return items.length > 0 ? items : nil
|
||||
end
|
||||
|
||||
# @param node {REXML::Node}
|
||||
# @return {Hash}
|
||||
def self.extract_header(header_node)
|
||||
return {
|
||||
:title => header_node.text(),
|
||||
:type => self::ITEM_TYPE_HEADER
|
||||
}
|
||||
end
|
||||
|
||||
# @param node {REXML::Node}
|
||||
# @return {Hash}
|
||||
def self.extract_items(li_node)
|
||||
item = nil
|
||||
|
||||
REXML::XPath.each(li_node, 'a') do |link|
|
||||
href = link.attribute('href').to_s
|
||||
id = File.basename(href, File.extname(href))
|
||||
is_external = href.start_with?('http://', 'https://', 'ftp://', '//')
|
||||
item = {
|
||||
:id => id,
|
||||
:title => link.text(),
|
||||
:url => href
|
||||
}
|
||||
item[:is_external] = true if is_external
|
||||
pages = []
|
||||
|
||||
REXML::XPath.each(li_node, 'ul/li') do |li|
|
||||
pages.push(extract_items(li))
|
||||
end
|
||||
|
||||
item['pages'] = pages unless pages.empty?
|
||||
end
|
||||
|
||||
return item
|
||||
end
|
||||
|
||||
end
|
||||
end
|
25
lib/util/erb.rb
Normal file
25
lib/util/erb.rb
Normal file
@ -0,0 +1,25 @@
|
||||
require 'ostruct'
|
||||
require 'erb'
|
||||
|
||||
module Docs
|
||||
module Util
|
||||
class Erb
|
||||
|
||||
def self.render(path, data = {})
|
||||
vars = ErbBinding.new(data)
|
||||
|
||||
erb_contents = File.read(path)
|
||||
erb = ERB.new(erb_contents)
|
||||
vars_binding = vars.send(:get_binding)
|
||||
|
||||
erb.result(vars_binding)
|
||||
end
|
||||
|
||||
class ErbBinding < OpenStruct
|
||||
def get_binding
|
||||
binding
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user