Skip to content

Commit

Permalink
Implements brackets tags and log messages. Version bump to 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
claudioc committed Feb 16, 2013
1 parent cc527d0 commit 9775706
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 42 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Features
- Show differences between document revisions
- Search through the content and the page names
- Layout accepts custom sidebar and footer
- Can use custom css and JavaScript scripts
- Can use custom CSS and JavaScript scripts
- White list for authorization on page reading and writing
- Detects unwritten pages (will appear in red)
- Automatically push to a remote
Expand Down Expand Up @@ -72,3 +72,24 @@ You can customize jingo in four different ways:
All those files are cached (thus, not re-read for every page load, but kept in memory). This means that for every modification in _style.css and _script.js you need to restart the server (sorry, working on that). This is not true for the footer and the sidebar but ONLY IF you edit those pages from jingo (which in that case will clear the cache by itself).

jingo uses twitter Bootstrap and jQuery as its front-end components.

Editing
-------

To link to another Jingo wiki page, use the Jingo Page Link Tag.

[[Jingo Works]]

The above tag will create a link to the corresponding page file named
`jingo-works.md`. The conversion is as follows:

1. Replace any spaces (U+0020) with dashes (U+002D)
2. Replace any slashes (U+002F) with dashes (U+002D)

If you'd like the link text to be something that doesn't map directly to the
page name, you can specify the actual page name after a pipe:

[[How Jingo works|Jingo Works]]

The above tag will link to `jingo-works.md` using "How Jingo Works" as the link text.

2 changes: 1 addition & 1 deletion jingo
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var express = require('express')
, yaml = require("yaml")
, program = require('commander');

program.version('0.1.5')
program.version('0.2.0')
.option('-c, --config <path>', 'Specify the config file')
.option('-s, --sample-config', 'Dumps a config file template and exits')
.parse(process.argv);
Expand Down
2 changes: 1 addition & 1 deletion lib/gitmech.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ module.exports = Gitmech = (function() {

gitExec(["log", "-" + howMany, "--reverse", "--no-notes", "--pretty=format:%h%n%H%n%an%n%ae%n%aD%n%ar%n%at%n%s", version, "--", path], function(err, data) {

var logdata = data.toString().split("\n")
var logdata = data ? data.toString().split("\n") : []
, group
, metadata = [];

Expand Down
1 change: 1 addition & 0 deletions lib/namer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var normalize = function(str) {
str = iconv.convert(str)
.toString()
.replace(/\s/g, '-')
.replace(/\//g, '-')
.replace(/[^a-zA-Z0-9\- _]/g, "")
.toLowerCase();

Expand Down
72 changes: 52 additions & 20 deletions lib/renderer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

var Marked = require("marked");
var Crypto = require('crypto');
var Namer = require("../lib/namer");

Marked.setOptions({
gfm: true,
Expand All @@ -10,37 +12,67 @@ Marked.setOptions({
}
});

var tagmap = {};

var Renderer = {

tagmap: {},
// Yields the content with the rendered [[bracket tags]]
// The rules are the same for Gollum https://github.com/github/gollum
function extractTags(text) {

render: function(content) {

var text = Marked(content);

return Marked(content);
},

// Yields the content with the rendered [[bracket tags]]
// The rules are the same for Gollum https://github.com/github/gollum
compileMarkup: function(content) {

var text = content.match(/(.?)\[\[(.+?)\]\]([^\[]?)/g);
console.log(text);
return text;
tagmap = {};

var matches = text.match(/(.?)\[\[(.+?)\]\]([^\[]?)/g)
, tag
, id;

},
// TODO text the ' at the beginning
if (matches) {
matches.forEach(function(match) {
tag = /\[\[(.+?)\]\]/.exec(match)[1];
id = Crypto.createHash('sha1').update(tag).digest("hex")
tagmap[id] = tag;
text = text.replace(tag, id);
});

extractTags: function(content) {
}
return text;
}

function evalTags(text) {
var parts
, name
, pageName
, re;

for (var k in tagmap) {
parts = tagmap[k].split("|");
name = pageName = parts[0];
if (parts[1]) {
pageName = parts[1];
}
pageName = Namer.normalize(pageName);

tagmap[k] = "<a class=\"internal\" href=\"/wiki/" + pageName + "\">" + name + "</a>";
}

return
for (k in tagmap) {
re = new RegExp("\\[\\[" + k + "\\]\\]", "g");
text = text.replace(re, tagmap[k]);
}
return text.replace(/\n/g, "");
}

var Renderer = {

render: function(content) {

var text = Marked(content);

text = extractTags(text);

text = evalTags(text);

return text;
}

};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jingo",
"version": "0.1.5",
"version": "0.2.0",
"description": "A nodejs based wiki engine",
"author": "Claudio Cicali <claudio.cicali@gmail.com>",
"main": "jingo",
Expand Down
15 changes: 15 additions & 0 deletions public/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,18 @@ input#pageTitle {
a.absent {
color: red;
}

form.edit {
border-radius: 4px;
background-color: #eee;
padding: 2%;
padding-bottom: 1%;
width: 96%;
}

form.edit input[type=text] {
width: 98%;
}
form.edit textarea {
width: 103%;
}
22 changes: 15 additions & 7 deletions public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,30 @@
return false;
});

if (window.location.pathname.match(/^\/wiki\//)) {
var pages = $.map($("#content a[href]").filter(function(i, a) {
var href = $(a).attr("href");
return !(href[0] == '/' || href.match(/^(f|ht)tps?:/));
}), function(a) {
return a.getAttribute("href").split("#")[0];
if (/^\/wiki\//.test(window.location.pathname)) {
var pages = []
, match
, href;

$("#content a.internal").each(function(i, a) {
href = $(a).attr("href");
if (match = /\/wiki\/(.+)/.exec(href)) {
pages.push(match[1]);
}
});

$.getJSON("/misc/existence", {data: pages}, function(result) {
$.each(result.data, function(href, a) {
$("#content a[href=" + a + "]").addClass("absent");
$("#content a[href=\\/wiki\\/" + a + "]").addClass("absent");
});
});
}

function toggleCompareCheckboxes() {
if ($hCol1.find(":checkbox").length == 1) {
$hCol1.find(":checkbox").hide();
return;
}
if ($hCol1.find(":checked").length == 2) {
$hCol1.find(":not(:checked)")
.hide();
Expand Down
3 changes: 3 additions & 0 deletions public/vendor/jquery-migrate-1.1.0.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ exports.pageUpdate = function(req, res) {
var pageName = res.locals.pageName = Namer.normalize(req.params.page)
, errors
, pageFile
, message
, content;

req.check('pageTitle', 'Page title cannot be empty').notEmpty();
Expand All @@ -255,12 +256,15 @@ exports.pageUpdate = function(req, res) {

req.sanitize('pageTitle').trim();
req.sanitize('content').trim();
req.sanitize('message').trim();

content = "#" + req.body.pageTitle + "\n" + req.body.content;
pageFile = app.locals.repo + "/" + pageName + ".md";

message = (req.body.message == "") ? "Content updated (" + pageName + ")" : req.body.message;

Fs.writeFile(pageFile, content, function() {
app.locals.Git.add(pageName + ".md", "Content updated (" + pageName + ")", req.user.asGitAuthor, function(err) {
app.locals.Git.add(pageName + ".md", message, req.user.asGitAuthor, function(err) {
Locker.unlock(pageName);
if (pageName == '_footer') {
app.locals._footer = null;
Expand Down Expand Up @@ -418,7 +422,7 @@ exports.miscSyntaxReference = function(req, res) {
res.render('syntax');
}

// Filters out pages that does not exist in the index
// Filters out pages that do not exist in the index
exports.miscExistence = function(req, res) {

if (!req.query.data) {
Expand Down
2 changes: 1 addition & 1 deletion test/spec/namerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe ("Namer", function() {
expect(Namer.normalize("CoffeE")).to.equal("coffee");
expect(Namer.normalize("Caffé")).to.equal("caffe");
expect(Namer.normalize("Caffé corretto!")).to.equal("caffe-corretto");
expect(Namer.normalize("Caff<p>e</p> senza schiuma")).to.equal("caffpep-senza-schiuma");
expect(Namer.normalize("Caff<p>e</p> senza schiuma")).to.equal("caffpe-p-senza-schiuma");
expect(Namer.normalize("Per favore: nessun, dico; E un punto...")).to.equal("per-favore-nessun-dico-e-un-punto");
});

Expand Down
32 changes: 30 additions & 2 deletions test/spec/rendererSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,39 @@ var Renderer = require("../../lib/renderer");

describe ("Renderer", function() {

it ("should render bracket tags", function() {
it ("should render bracket tags1", function() {
var text = "a [[Foo]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foo\">Foo</a> b</p>");
});

it ("should render bracket tags2", function() {
var text = "a [[Foo]][[Foo]][[Foo]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foo\">Foo</a><a class=\"internal\" href=\"/wiki/foo\">Foo</a><a class=\"internal\" href=\"/wiki/foo\">Foo</a> b</p>");
});

it ("should render bracket tags3", function() {
var text = "a [[Foo Bar]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foo-bar\">Foo Bar</a> b</p>");
});

it ("should render bracket tags4", function() {
var text = "a [[Foo]][[Bar]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foo\">Foo</a><a class=\"internal\" href=\"/wiki/bar\">Bar</a> b</p>");
});

it ("should render bracket tags5", function() {
var text = "a [[Foo]] [[Bar]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foo\">Foo</a> <a class=\"internal\" href=\"/wiki/bar\">Bar</a> b</p>");
});

it ("should render bracket tags6", function() {
var text = "a [[Il marito di Foo|Foobar]] [[Bar]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foobar\">Il marito di Foo</a> <a class=\"internal\" href=\"/wiki/bar\">Bar</a> b</p>");
});

expect(Renderer.compileMarkup(text)).to.be.a("<p>a <a class=\"internal\" href=\"/Foo\">Foo</a><a class=\"internal\" href=\"/Bar\">Bar</a> b</p>");
it ("should render bracket tags7", function() {
var text = "a [[Foo / Bar]] b";
expect(Renderer.render(text)).to.be.equal("<p>a <a class=\"internal\" href=\"/wiki/foo---bar\">Foo / Bar</a> b</p>");
});


Expand Down
6 changes: 3 additions & 3 deletions views/create.jade
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ block content

mixin errors()

form(action='/pages', method='post')
form(action='/pages', method='post', class='edit')

input(type="hidden", name="pageName", value="#{coalesce(pageName, '')}")

div
label Page title
input(type='text', name='pageTitle', value="#{coalesce(formData.pageTitle, '')}")#pageTitle.span8
input(type='text', name='pageTitle', value="#{coalesce(formData.pageTitle, '')}")#pageTitle

div
textarea(name="content", rows=25)#editor.span8 #{coalesce(formData.content, '')}
textarea(name="content", rows=25)#editor #{coalesce(formData.content, '')}

mixin saveAndCancel()

Expand Down
9 changes: 6 additions & 3 deletions views/edit.jade
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@ block content
mixin errors()
mixin warning()

form(action='/pages/#{pageName}', method='post')
form(action='/pages/#{pageName}', method='post', class='edit')

div
label Page title
input(type='text', name='pageTitle', value="#{coalesce(formData.pageTitle, '')}")#pageTitle.span8
input(type='text', name='pageTitle', value="#{coalesce(formData.pageTitle, '')}")#pageTitle
input(type="hidden", name="_method", value="put")

div
textarea(name="content", rows=25)#editor.span8 #{coalesce(formData.content, '')}
textarea(name="content", rows=25)#editor #{coalesce(formData.content, '')}

div
input(type='text', name='message', placeholder='Write a small message here explaining this change (optional)')#message.span8

mixin saveAndCancel()

Expand Down
1 change: 1 addition & 0 deletions views/mixins/form.jade
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mixin markitupStylesheets()
link(rel="stylesheet", type="text/css", href="/vendor/markitup/sets/markdown/style.css")

mixin markitupJavaScripts()
script(src="/vendor/jquery-migrate-1.1.0.min.js")
script(src="/vendor/markitup/jquery.markitup.js")
script(src="/vendor/markitup/sets/markdown/set.js")
script
Expand Down

0 comments on commit 9775706

Please sign in to comment.