From: Jean Privat Date: Thu, 11 Jun 2015 20:24:10 +0000 (-0400) Subject: Merge: Nitiwiki next X-Git-Tag: v0.7.6~50 X-Git-Url: http://nitlanguage.org?hp=de34fbb9ce4f9dd1cc8f6ba20f0902107f905227 Merge: Nitiwiki next Some fixes for nitiwiki in prevision for the nitlanguage.org site migration and the resolution of #824. Do not consider b481cea since it belongs to #1368 (and break the loader) Feature summary: * ini accept array notation * customizable sidebar content * customizable sidebar position * wikilinks support external links * better search by title * better search by path * make breadcrumbs and summaries optionnal * add link to github for last_changes and edit mode Pull-Request: #1444 Reviewed-by: Lucas Bajolet Reviewed-by: Jean Privat --- diff --git a/contrib/nitiwiki/src/wiki_base.nit b/contrib/nitiwiki/src/wiki_base.nit index b250071..09b499b 100644 --- a/contrib/nitiwiki/src/wiki_base.nit +++ b/contrib/nitiwiki/src/wiki_base.nit @@ -209,6 +209,26 @@ class Nitiwiki return tpl end + # Does a sideblock named `name` exists for this wiki? + fun has_sideblock(name: String): Bool do + name = "{name}.{config.md_ext}" + return expand_path(config.root_dir, config.sidebar_dir, name).file_exists + end + + # Load a markdown block with `name` from `WikiConfig::sidebar_dir`. + private fun load_sideblock(name: String): nullable String do + if not has_sideblock(name) then + message("Error: can't load sideblock `{name}`", 0) + return null + end + name = "{name}.{config.md_ext}" + var path = expand_path(config.root_dir, config.sidebar_dir, name) + var file = new FileReader.open(path) + var res = file.read_all + file.close + return res + end + # Join `parts` as a path and simplify it fun expand_path(parts: String...): String do var path = "" @@ -324,6 +344,9 @@ abstract class WikiEntry return path.reversed end + # Sidebar relative to this wiki entry. + var sidebar = new WikiSidebar(self) + # Relative path from `wiki.config.root_dir` to source if any. fun src_path: nullable String is abstract @@ -560,6 +583,28 @@ class WikiArticle redef fun to_s do return "{name} ({parent or else "null"})" end +# The sidebar is displayed in front of the main panel of a `WikiEntry`. +class WikiSidebar + + # Wiki used to parse sidebar blocks. + var wiki: Nitiwiki is lazy do return entry.wiki + + # WikiEntry this panel is related to. + var entry: WikiEntry + + # Blocks are ieces of markdown that will be rendered in the sidebar. + var blocks: Array[Text] is lazy do + var res = new Array[Text] + # TODO get blocks from the entry for more customization + for name in entry.wiki.config.sidebar_blocks do + var block = wiki.load_sideblock(name) + if block == null then continue + res.add block + end + return res + end +end + # Wiki configuration class. # # This class provides services that ensure static typing when accessing the `config.ini` file. @@ -702,6 +747,59 @@ class WikiConfig return value_or_default("wiki.footer", "footer.html") end + # Automatically add a summary. + # + # * key: `wiki.auto_summary` + # * default: `true` + var auto_summary: Bool is lazy do + return value_or_default("wiki.auto_summary", "true") == "true" + end + + # Automatically add breadcrumbs. + # + # * key: `wiki.auto_breadcrumbs` + # * default: `true` + var auto_breadcrumbs: Bool is lazy do + return value_or_default("wiki.auto_breadcrumbs", "true") == "true" + end + + # Sidebar position. + # + # Position of the sidebar between `left`, `right` and `none`. Any other value + # will be considered as `none`. + # + # * key: `wiki.sidebar` + # * default: `left` + var sidebar: String is lazy do + return value_or_default("wiki.sidebar", "left") + end + + # Sidebar markdown block to include. + # + # Blocks are specified by their filename without the extension. + # + # * key: `wiki.sidebar.blocks` + # * default: `[]` + var sidebar_blocks: Array[String] is lazy do + var res = new Array[String] + if not has_key("wiki.sidebar.blocks") then return res + for val in at("wiki.sidebar.blocks").values do + res.add val + end + return res + end + + # Sidebar files directory. + # + # Directory where sidebar blocks are stored. + # **This path MUST be relative to `root_dir`.** + # + # * key: `wiki.sidebar_dir` + # * default: `sidebar/` + var sidebar_dir: String is lazy do + return value_or_default("wiki.sidebar_dir", "sidebar/").simplify_path + end + # Directory used by rsync to upload wiki files. # # This information is used to update your distant wiki files (like the webserver). @@ -721,6 +819,18 @@ class WikiConfig # * key: `wiki.git_branch` # * default: `master` var git_branch: String is lazy do return value_or_default("wiki.git_branch", "master") + + # URL to source versionning used to display last changes + # + # * key: `wiki.last_changes` + # * default: `` + var last_changes: String is lazy do return value_or_default("wiki.last_changes", "") + + # URL to source edition. + # + # * key: `wiki.edit` + # * default: `` + var edit: String is lazy do return value_or_default("wiki.edit", "") end # WikiSection custom configuration. diff --git a/contrib/nitiwiki/src/wiki_html.nit b/contrib/nitiwiki/src/wiki_html.nit index 46518aa..d5ccc7a 100644 --- a/contrib/nitiwiki/src/wiki_html.nit +++ b/contrib/nitiwiki/src/wiki_html.nit @@ -211,14 +211,23 @@ redef class WikiArticle fun tpl_article: TplArticle do var article = new TplArticle article.body = content - article.breadcrumbs = new TplBreadcrumbs(self) - tpl_sidebar.blocks.add tpl_summary + if wiki.config.auto_breadcrumbs then + article.breadcrumbs = new TplBreadcrumbs(self) + end article.sidebar = tpl_sidebar + article.sidebar_pos = wiki.config.sidebar return article end # Sidebar for this page. - var tpl_sidebar = new TplSidebar + var tpl_sidebar: TplSidebar is lazy do + var res = new TplSidebar + if wiki.config.auto_summary then + res.blocks.add tpl_summary + end + res.blocks.add_all sidebar.blocks + return res + end # Generate the HTML summary for this article. # @@ -284,6 +293,14 @@ redef class WikiArticle if tpl.has_macro("GEN_TIME") then tpl.replace("GEN_TIME", time.to_s) end + if tpl.has_macro("LAST_CHANGES") then + var url = "{wiki.config.last_changes}{src_path or else ""}" + tpl.replace("LAST_CHANGES", url) + end + if tpl.has_macro("EDIT") then + var url = "{wiki.config.edit}{src_path or else ""}" + tpl.replace("EDIT", url) + end return tpl end end @@ -327,6 +344,11 @@ class TplArticle # Sidebar of this article (if any). var sidebar: nullable TplSidebar = null + # Position of the sidebar. + # + # See `WikiConfig::sidebar`. + var sidebar_pos: String = "left" + # Breadcrumbs from wiki root to this article. var breadcrumbs: nullable TplBreadcrumbs = null @@ -336,13 +358,11 @@ class TplArticle end redef fun rendering do - if sidebar != null then - add "
" - add sidebar.as(not null) - add "
" - add "
" - else + if sidebar_pos == "left" then render_sidebar + if sidebar == null then add "
" + else + add "
" end if body != null then add "
" @@ -358,6 +378,14 @@ class TplArticle add "
" end add "
" + if sidebar_pos == "right" then render_sidebar + end + + private fun render_sidebar do + if sidebar == null then return + add "
" + add sidebar.as(not null) + add "
" end end @@ -370,9 +398,9 @@ class TplSidebar redef fun rendering do for block in blocks do - add "
" + add "
" + add "" end end end diff --git a/contrib/nitiwiki/src/wiki_links.nit b/contrib/nitiwiki/src/wiki_links.nit index bfdeb86..43f354d 100644 --- a/contrib/nitiwiki/src/wiki_links.nit +++ b/contrib/nitiwiki/src/wiki_links.nit @@ -29,7 +29,7 @@ redef class Nitiwiki # # Returns `null` if no article can be found. fun lookup_entry_by_name(context: WikiEntry, name: String): nullable WikiEntry do - var section = context.parent + var section: nullable WikiEntry = context.parent or else context var res = section.lookup_entry_by_name(name) if res != null then return res while section != null do @@ -50,13 +50,13 @@ redef class Nitiwiki # # Returns `null` if no article can be found. fun lookup_entry_by_title(context: WikiEntry, title: String): nullable WikiEntry do - var section = context.parent + var section: nullable WikiEntry = context.parent or else context var res = section.lookup_entry_by_title(title) if res != null then return res while section != null do - if section.title == title then return section + if section.title.to_lower == title.to_lower then return section for child in section.children.values do - if child.title == title then return child + if child.title.to_lower == title.to_lower then return child end section = section.parent end @@ -70,7 +70,7 @@ redef class Nitiwiki # # Returns `null` if no article can be found. fun lookup_entry_by_path(context: WikiEntry, path: String): nullable WikiEntry do - var entry = context.parent + var entry = context.parent or else context var parts = path.split_with("/") if path.has_prefix("/") then entry = root_section @@ -80,6 +80,7 @@ redef class Nitiwiki while not parts.is_empty do var name = parts.shift if name.is_empty then continue + if entry.name == name then continue if not entry.children.has_key(name) then return null entry = entry.children[name] end @@ -95,6 +96,7 @@ redef class WikiEntry redef fun render do super if not is_dirty and not wiki.force_render then return + render_sidebar_wikilinks end # Search in `self` then `self.children` if an entry has the name `name`. @@ -110,7 +112,7 @@ redef class WikiEntry # Search in `self` then `self.children` if an entry has the title `title`. fun lookup_entry_by_title(title: String): nullable WikiEntry do for child in children.values do - if child.title == title then return child + if child.title.to_lower == title.to_lower then return child end for child in children.values do var res = child.lookup_entry_by_title(title) @@ -118,6 +120,19 @@ redef class WikiEntry end return null end + + private var md_proc: NitiwikiMdProcessor is lazy do + return new NitiwikiMdProcessor(wiki, self) + end + + # Process wikilinks from sidebar. + private fun render_sidebar_wikilinks do + var blocks = sidebar.blocks + for i in [0..blocks.length[ do + blocks[i] = md_proc.process(blocks[i].to_s).write_to_string + md_proc.emitter.decorator.headlines.clear + end + end end redef class WikiSection @@ -155,7 +170,6 @@ redef class WikiArticle redef fun render do super if not is_dirty and not wiki.force_render or not has_source then return - var md_proc = new NitiwikiMdProcessor(wiki, self) content = md_proc.process(md.as(not null)) headlines.recover_with(md_proc.emitter.decorator.headlines) end @@ -183,7 +197,7 @@ class NitiwikiMdProcessor # Article parsed by `self`. # # Used to contextualize links. - var context: WikiArticle + var context: WikiEntry init do emitter = new MarkdownEmitter(self) @@ -198,32 +212,35 @@ private class NitiwikiDecorator var wiki: Nitiwiki # Article used to contextualize links. - var context: WikiArticle + var context: WikiEntry redef fun add_wikilink(v, link, name, comment) do - var wiki = v.processor.as(NitiwikiMdProcessor).wiki - var target: nullable WikiEntry = null var anchor: nullable String = null - if link.has("#") then - var parts = link.split_with("#") - link = parts.first - anchor = parts.subarray(1, parts.length - 1).join("#") - end - if link.has("/") then - target = wiki.lookup_entry_by_path(context, link.to_s) - else - target = wiki.lookup_entry_by_name(context, link.to_s) - if target == null then - target = wiki.lookup_entry_by_title(context, link.to_s) - end - end v.add " 1 else + print "Error: malformed ini at line {line_number}" + end var key = parts[0].trim var val = parts[1].trim - if path == null then - set_node(key, val) + if path != null then key = "{path}.{key}" + if key.has_suffix("[]") then + set_array(key, val) else - set_node("{path}.{key}", val) + set_node(key,val) end end end @@ -218,6 +239,16 @@ class ConfigTree private var roots = new Array[ConfigNode] + # Append `value` to array at `key` + private fun set_array(key: String, value: nullable String) do + key = key.substring(0, key.length - 2) + var len = 0 + if has_key(key) then + len = get_node(key).children.length + end + set_node("{key}.{len.to_s}", value) + end + private fun set_node(key: String, value: nullable String) do var parts = key.split(".").reversed var k = parts.pop diff --git a/lib/markdown/wikilinks.nit b/lib/markdown/wikilinks.nit index 22b67c0..28fd1e0 100644 --- a/lib/markdown/wikilinks.nit +++ b/lib/markdown/wikilinks.nit @@ -88,7 +88,6 @@ class TokenWikiLink pos += 1 pos = md.skip_spaces(pos) if pos < start then return -1 - pos += 1 return pos end end