Compare commits

...

20 Commits

Author SHA1 Message Date
Samy Pessé eb6204aa42 Bump version to 0.0.4 2014-04-02 20:26:08 -07:00
Samy Pessé a70439f375 Update app.js build 2014-04-02 20:25:52 -07:00
Samy Pessé a3b562b4e8 Prevent default click action on sharing 2014-04-02 20:24:07 -07:00
Samy Pessé aa4e3abc33 Add sharing links in header 2014-04-02 20:17:46 -07:00
Samy Pessé f24a7fbb6e Fix selection of all buffer when clicking on "Solution" 2014-04-02 19:00:50 -07:00
Samy Pessé f3a49306b1 Use prefix for storage key 2014-04-02 18:57:36 -07:00
Samy Pessé f312472abd Add button to edit current chapter in sidebar 2014-04-02 18:53:58 -07:00
Aaron O'Mullan ecb07468f6 Resolve relative links to GitHub repo, fixes #6
Useful for linking to blobs and other files …
2014-04-02 18:40:53 -07:00
Aaron O'Mullan 8fc09e2e05 Add github link resolution test 2014-04-02 18:40:53 -07:00
Aaron O'Mullan ed7798237a Add GITHUB_LINKS.md fixture
For testing github link resolution
2014-04-02 18:40:52 -07:00
Samy Pessé faf63566df Hide articles in progress bar on mobile 2014-04-02 17:48:35 -07:00
Samy Pessé c88382aea0 Update favicon 2014-04-02 17:01:30 -07:00
Samy Pessé 9ee5f48aef Add meta tag generator 2014-04-02 16:53:28 -07:00
Samy Pessé e1dfe5c0f6 Improve meta tags 2014-04-02 16:48:12 -07:00
Aaron O'Mullan 3adcd77ae4 Merge sections together, fixes #7 2014-04-02 16:40:51 -07:00
Aaron O'Mullan 4bdcfd07a9 Add tests for section merging 2014-04-02 16:40:51 -07:00
Aaron O'Mullan a9967df6eb Add HR_PAGE.md fixture
This is for testing that non exercise sections are merged correctly
together and united with HRs
2014-04-02 16:40:51 -07:00
Samy Pessé 62a2e8f81c Fix #8: Improve page title 2014-04-02 16:38:24 -07:00
Aaron O'Mullan 6bcc2d8cf2 Expose titles in navigation of current nodes 2014-04-02 16:33:31 -07:00
Samy Pessé ad1867e4d8 Add preview on readme 2014-04-02 10:40:47 +02:00
22 changed files with 195 additions and 29 deletions
+2
View File
@@ -3,6 +3,8 @@ GitBook
GiBook is a command line tool (and Node.js library) for building beautiful programming books and exercises using GitHub/Git and Markdown. You can see an example: [Learn Javascript](http://gitbookio.github.io/javascript/).
![Image](https://raw.github.com/GitbookIO/gitbook/master/preview.png)
## How to use it:
GitBook can be installed from **NPM** using:
+10 -1
View File
@@ -1,15 +1,21 @@
require([
"jQuery",
"utils/storage",
"utils/analytic",
"utils/sharing",
"core/state",
"core/exercise",
"core/progress",
"core/sidebar"
], function($, analytic, _state, exercise, progress, sidebar){
], function($, storage, analytic, sharing, _state, exercise, progress, sidebar){
$(document).ready(function() {
var state = _state();
var $book = state.$book;
// Initialize storage
storage.setBaseKey(state.githubId);
// Tract page view
analytic.track("View");
@@ -26,6 +32,9 @@ require([
// Bind exercise
exercise.init();
// Bind sharing button
sharing.init();
// Show progress
progress.show();
});
+1
View File
@@ -32,6 +32,7 @@ define([
e.preventDefault();
editor.setValue(codeSolution);
editor.gotoLine(0);
});
};
+33
View File
@@ -0,0 +1,33 @@
define([
"jQuery"
], function($) {
var url = location.href;
var title = $("title").text();
var types = {
"twitter": function($el) {
window.open("http://twitter.com/home?status="+encodeURIComponent(title+" "+url))
},
"facebook": function($el) {
window.open("http://www.facebook.com/sharer/sharer.php?s=100&p[url]="+encodeURIComponent(url))
},
"google-plus": function($el) {
window.open("https://plus.google.com/share?url="+encodeURIComponent(url))
}
};
// Bind all sharing button
var init = function() {
$("a[data-sharing]").click(function(e) {
if (e) e.preventDefault();
var type = $(this).data("sharing");
types[type]($(this));
})
};
return {
init: init
};
});
+8
View File
@@ -1,12 +1,19 @@
define(function(){
var baseKey = "";
/*
* Simple module for storing data in the browser's local storage
*/
return {
setBaseKey: function(key) {
baseKey = key;
},
set: function(key, value) {
key = baseKey+":"+key;
localStorage[key] = JSON.stringify(value);
},
get: function(key, def) {
key = baseKey+":"+key;
try {
return JSON.parse(localStorage[key]) || def;
} catch(err) {
@@ -14,6 +21,7 @@ define(function(){
}
},
remove: function(key) {
key = baseKey+":"+key;
localStorage.removeItem(key);
}
};
+1 -1
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long
+8
View File
@@ -74,6 +74,14 @@
background: @brand-success;
box-shadow: none;
}
@media (max-width: 800px) {
display: none;
&.new-chapter {
display: block;
}
}
}
}
}
+4 -2
View File
@@ -38,7 +38,10 @@ var initTemplate = function(options) {
// Parse sections
.then(function(markdown) {
return parse.page(markdown);
return parse.page(markdown, {
repo: options.locals.githubId,
dir: path.dirname(_input) || '/'
});
})
//Calcul template
@@ -49,7 +52,6 @@ var initTemplate = function(options) {
content: sections,
basePath: basePath,
staticBase: path.join(basePath, "gitbook"),
navigation: options.locals.allNavigation[_output],
progress: parse.progress(options.locals.allNavigation, _output)
})
);
+3
View File
@@ -45,6 +45,7 @@ function navigation(summary, files) {
// Add chapter mapping
mapping[chapter.path] = {
title: chapter.title,
prev: clean(prev),
next: clean(next),
level: (idx+1).toString(),
@@ -59,6 +60,7 @@ function navigation(summary, files) {
var next = (_idx+1 >= articles.length) ? nextChapter : clean(articles[_idx+1]);
mapping[article.path] = {
title: article.title,
prev: clean(prev),
next: clean(next),
level: [idx+1, _idx+1].join('.'),
@@ -68,6 +70,7 @@ function navigation(summary, files) {
// Hack for README.html
mapping['README.html'] = {
title: README_NAV.title,
prev: null,
next: clean(summary.chapters[0]),
level: '0',
+20 -4
View File
@@ -46,19 +46,22 @@ function sectionType(nodes, idx) {
}
// Render a section using our custom renderer
function render(section) {
function render(section, _options) {
// marked's Render expects this, we don't use it yet
section.links = {};
// Build options using defaults and our custom renderer
var options = _.extend({}, marked.defaults, {
renderer: renderer()
renderer: renderer(null, _options)
});
return marked.parser(section, options);
}
function parsePage(src) {
function parsePage(src, options) {
options = options || {};
// Lex file
var nodes = marked.lexer(src);
return _.chain(splitSections(nodes))
@@ -70,6 +73,19 @@ function parsePage(src) {
.filter(function(section) {
return !_.isEmpty(section);
})
.reduce(function(sections, section) {
var last = _.last(sections);
// Merge normal sections together
if(last && last.type === section.type && last.type === 'normal') {
last.push.apply(last, [{'type': 'hr'}].concat(section));
} else {
// Add to list of sections
sections.push(section);
}
return sections;
}, [])
.map(function(section) {
// Generate a uniqueId to identify this section in our code
var id = _.uniqueId('gitbook_');
@@ -100,7 +116,7 @@ function parsePage(src) {
return {
id: id,
type: section.type,
content: render(section)
content: render(section, options)
};
})
.value();
+11 -3
View File
@@ -2,7 +2,7 @@ var _ = require("lodash");
var calculProgress = function(navigation, current) {
var n = _.size(navigation);
var percent = 0, prevPercent = 0;
var percent = 0, prevPercent = 0, currentChapter = null;
var done = true;
var chapters = _.chain(navigation)
@@ -20,6 +20,7 @@ var calculProgress = function(navigation, current) {
// Is it done
nav.done = done;
if (nav.path == current) {
currentChapter = nav;
percent = nav.percent;
done = false;
} else if (done) {
@@ -30,11 +31,18 @@ var calculProgress = function(navigation, current) {
})
.value();
return {
// Previous percent
prevPercent: prevPercent,
// Current percent
percent: percent,
chapters: chapters
// List of chapter with progress
chapters: chapters,
// Current chapter
current: currentChapter
};
}
+16 -2
View File
@@ -1,14 +1,18 @@
var url = require('url');
var inherits = require('util').inherits;
var path = require('path');
var marked = require('marked');
function GitBookRenderer(options) {
function GitBookRenderer(options, extra_options) {
if(!(this instanceof GitBookRenderer)) {
return new GitBookRenderer(options);
return new GitBookRenderer(options, extra_options);
}
GitBookRenderer.super_.call(this, options);
this._extra_options = extra_options;
}
inherits(GitBookRenderer, marked.Renderer);
@@ -39,6 +43,16 @@ GitBookRenderer.prototype.link = function(href, title, text) {
// Parsed version of the url
var parsed = url.parse(href);
var o = this._extra_options;
// Relative link, rewrite it to point to github repo
if(parsed.path[0] != '/' && o && o.repo && o.dir) {
href = 'https://github.com/' + o.repo + '/blob' + path.normalize(path.join(
'/',
o.dir,
href
));
parsed = url.parse(href);
}
// Generate HTML for link
var out = '<a href="' + href + '"';
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.0.3",
"version": "0.0.4",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
"dependencies": {
+5 -1
View File
@@ -1,9 +1,13 @@
<div class="book-header">
<!-- Actions Left -->
<a href="https://github.com/{{ githubId }}" target="_blank" class="btn pull-left"><i class="fa fa-github-alt"></i></a>
<a href="#" class="btn pull-left toggle-summary"><i class="fa fa-align-justify"></i> Summary</a>
<a href="#" class="btn pull-left toggle-summary"><i class="fa fa-align-justify"></i></a>
<!-- Actions Right -->
<a href="#" target="_blank" class="btn pull-right" data-sharing="google-plus"><i class="fa fa-google-plus"></i></a>
<a href="#" target="_blank" class="btn pull-right" data-sharing="facebook"><i class="fa fa-facebook"></i></a>
<a href="#" target="_blank" class="btn pull-right" data-sharing="twitter"><i class="fa fa-twitter"></i></a>
<a href="https://github.com/{{ githubId }}/stargazers" target="_blank" class="btn pull-right count-star"><i class="fa fa-star-o"></i> Star (<span>-</span>)</a>
<a href="https://github.com/{{ githubId }}/watchers" target="_blank" class="btn pull-right count-watch"><i class="fa fa-eye"></i> Watch (<span>-</span>)</a>
+3
View File
@@ -6,6 +6,9 @@
<li>
<a href="https://github.com/{{ githubId }}/issues" target="blank">Questions and Issues</a>
</li>
<li>
<a href="https://github.com/{{ githubId }}/edit/master/{{ _input }}" target="blank">Edit and Contribute</a>
</li>
<li class="divider"></li>
<li data-level="0">
<a href="{{ basePath }}/README.html"><i class="fa fa-check"></i> Introduction</a>
+19 -5
View File
@@ -1,18 +1,32 @@
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<head prefix="og: http://ogp.me/ns# book: http://ogp.me/ns/book#">
{% block head %}
<meta charset="UTF-8">
<title>{% block title %} | GitBook{% endblock %}</title>
<meta name="robots" content="{% block robots %}noindex, nofollow{% endblock %}">
<link rel="shortcut icon" href="{{ staticBase }}/images/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="{{ staticBase }}/style.css">
<title>{% block title %} | {{ title }}{% endblock %}</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="robots" content="index, follow">
<meta name="author" content="{{ githubAuthor }}">
<meta name="description" content="{{ description }}">
<meta name="keywords" content="gitbook,github" >
<meta name="generator" content="www.gitbook.io">
<meta property="og:title" content="{% block title %} | {{ title }}{% endblock %}">
<meta property="og:site_name" content="{{ title }}">
<meta property="og:type" content="book">
<meta property="og:locale" content="en_US">
<meta property="book:author" content="https://github.com/{{ githubAuthor }}">
<meta property="book:tag" content="GitBook">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="shortcut icon" href="{{ staticBase }}/images/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="{{ staticBase }}/style.css">
<script type="text/javascript">
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
+6 -8
View File
@@ -1,10 +1,8 @@
{% extends "layout.html" %}
{% block title %}{{ _input }} {{ title }}{% parent %}{% endblock %}
{% block description %}{% endblock %}
{% block robots %}index, follow{% endblock %}
{% block title %}{{ progress.current.title }}{% parent %}{% endblock %}
{% block content %}
<div class="book {% if _input == "README.md" %}with-summary{% endif %}" data-github="{{ githubId }}" data-level="{{ navigation.level }}">
<div class="book {% if _input == "README.md" %}with-summary{% endif %}" data-github="{{ githubId }}" data-level="{{ progress.current.level }}">
{% include "includes/book/header.html" %}
{% include "includes/book/summary.html" %}
<div class="book-body">
@@ -34,11 +32,11 @@
<div class="page-footer">
{% if _input == "README.md" %}
<a href="{{ basePath }}/{{ navigation.next.path }}" class="navigation-link">Start</a>
<a href="{{ basePath }}/{{ progress.current.next.path }}" class="navigation-link">Start</a>
{% else %}
{% if navigation.next %}
{% if navigation.next.path %}
<a href="{{ basePath }}/{{ navigation.next.path }}" class="navigation-link next">Next</a>
{% if progress.current.next %}
{% if progress.current.next.path %}
<a href="{{ basePath }}/{{ progress.current.next.path }}" class="navigation-link next">Next</a>
{% else %}
<div class="navigation-link coming-soon">Coming soon</div>
{% endif %}
+3
View File
@@ -0,0 +1,3 @@
# Nice course
Check out this source file [in C++](../src/something.cpp)
+11
View File
@@ -0,0 +1,11 @@
## Wow such book
Some nice content here
---
A beautiful separator, but non an exercise !
---
Some more beautiful text, because `this` book is awesome ...
+29
View File
@@ -8,6 +8,12 @@ var page = require('../').parse.page;
var CONTENT = fs.readFileSync(path.join(__dirname, './fixtures/PAGE.md'), 'utf8');
var LEXED = page(CONTENT);
var HR_CONTENT = fs.readFileSync(path.join(__dirname, './fixtures/HR_PAGE.md'), 'utf8');
var HR_LEXED = page(HR_CONTENT);
var LINKS_CONTENT = fs.readFileSync(path.join(__dirname, './fixtures/GITHUB_LINKS.md'), 'utf8');
describe('Page parsing', function() {
it('should detection sections', function() {
assert.equal(LEXED.length, 3);
@@ -31,4 +37,27 @@ describe('Page parsing', function() {
assert(LEXED[1].code.solution);
assert(LEXED[1].code.validation);
});
it('should merge sections correctly', function() {
// One big section
assert.equal(HR_LEXED.length, 1);
// HRs inserted correctly
assert.equal(HR_LEXED[0].content.match(/<hr>/g).length, 2);
});
});
describe('Relative links', function() {
it('should be resolved to their GitHub counterparts', function() {
var LEXED = page(LINKS_CONTENT, {
// GitHub repo ID
repo: 'GitBookIO/javascript',
// Imaginary folder of markdown file
dir: 'course',
});
assert(LEXED[0].content.indexOf('https://github.com/GitBookIO/javascript/blob/src/something.cpp') !== -1);
});
});