Compare commits

...

15 Commits

Author SHA1 Message Date
Samy Pessé 2cee253be4 Bump version to 0.0.2 2014-04-01 19:32:55 -07:00
Samy Pessé 25162ceaa2 Fix #5: Add favicon 2014-04-01 19:20:38 -07:00
Samy Pessé 840113a48f Improve design of page content (sections and exercises) 2014-04-01 19:10:15 -07:00
Samy Pessé ddffd02b2e Add border radius to sections and footer navigation button 2014-04-01 18:59:59 -07:00
Samy Pessé 520ea847da Make chapter in progress bar clickable 2014-04-01 18:57:48 -07:00
Samy Pessé e77e3b724e Improve footer navigation 2014-04-01 18:49:20 -07:00
Samy Pessé d313589736 Mark chapter as read after the page is viewed 2014-04-01 18:42:43 -07:00
Samy Pessé 466ceb581c Fix execution when contains && 2014-04-01 18:21:01 -07:00
Samy Pessé 835953d8dd Improve lisibility of text in page 2014-04-01 17:57:20 -07:00
Samy Pessé a69e8ec328 Add highlight.js dependency 2014-04-01 17:39:22 -07:00
Samy Pessé 970107c656 Fix #3: Add syntax highlighting 2014-04-01 17:01:44 -07:00
Samy Pessé 7121b7efe3 Fix #4: Add option for defining description 2014-04-01 16:42:15 -07:00
Samy Pessé d02581a21c Add base analytic using mixpanel 2014-04-01 15:39:28 -07:00
Samy Pessé fd5c2f6706 Fix transition on header 2014-04-01 14:42:04 -07:00
Samy Pessé b93f67c84a Save sidebar state 2014-04-01 13:26:06 -07:00
25 changed files with 247 additions and 48 deletions
+8 -6
View File
@@ -1,18 +1,20 @@
require([
"jQuery",
"utils/analytic",
"core/state",
"core/exercise",
"core/progress",
], function($, _state, exercise, progress){
"core/sidebar"
], function($, analytic, _state, exercise, progress, sidebar){
$(document).ready(function() {
var state = _state();
var $book = state.$book;
// Toggle summary
$book.find(".book-header .toggle-summary").click(function(e) {
e.preventDefault();
$book.toggleClass("with-summary");
});
// Tract page view
analytic.track("View");
// Init sidebar
sidebar.init();
// Star and watch count
$.getJSON("https://api.github.com/repos/"+state.githubId)
+7 -3
View File
@@ -1,21 +1,25 @@
define([
"jQuery",
"utils/execute",
"utils/analytic",
"core/state"
], function($, execute, state){
], function($, execute, analytic, state){
// Bind an exercise
var prepareExercise = function($exercise) {
var codeSolution = $exercise.find(".code-solution").html();
var codeValidation = $exercise.find(".code-validation").html();
var codeSolution = $exercise.find(".code-solution").text();
var codeValidation = $exercise.find(".code-validation").text();
var editor = ace.edit($exercise.find(".editor").get(0));
editor.setTheme("ace/theme/tomorrow");
editor.getSession().setUseWorker(false);
editor.getSession().setMode("ace/mode/javascript");
// Submit: test code
$exercise.find(".action-submit").click(function(e) {
e.preventDefault();
analytic.track("exercise.submit");
execute(editor.getValue(), codeValidation, function(err, result) {
$exercise.toggleClass("return-error", err != null);
$exercise.toggleClass("return-success", err == null);
+4 -4
View File
@@ -43,10 +43,7 @@ define([
};
// Show progress
var showProgress = function() {
// Mark current progress
markProgress(getCurrentLevel(), true);
var showProgress = function() {
// Update progress
var progress = getProgress();
var $summary = $(".book-summary");
@@ -54,6 +51,9 @@ define([
_.each(progress, function(value, level) {
$summary.find("li[data-level='"+level+"']").toggleClass("done", value > 0);
});
// Mark current progress
markProgress(getCurrentLevel(), true);
};
return {
+41
View File
@@ -0,0 +1,41 @@
define([
"utils/storage",
"utils/platform",
"core/state"
], function(storage, platform, state) {
// Toggle sidebar with or withour animation
var toggleSidebar = function(_state, animation) {
if (animation == null) animation = true;
var $book = state().$book;
$book.toggleClass("without-animation", !animation);
$book.toggleClass("with-summary", _state);
storage.set("sidebar", isOpen());
};
// Return true if sidebar is open
var isOpen = function() {
return state().$book.hasClass("with-summary");
};
// Prepare sidebar: state and toggle button
var init = function() {
var $book = state().$book;
// Toggle summary
$book.find(".book-header .toggle-summary").click(function(e) {
e.preventDefault();
toggleSidebar();
});
// Init last state if not mobile and not homepage
if (!isOpen()) toggleSidebar(platform.isMobile ? false : storage.get("sidebar", false), false);
};
return {
init: init,
toggle: toggleSidebar
}
});
+15
View File
@@ -0,0 +1,15 @@
define([], function() {
var isAvailable = function() {
return (typeof mixpanel === "undefined");
};
var track = function(event, data) {
if (!isAvailable()) return;
mixpanel.track(event, data);
};
return {
isAvailable: isAvailable,
track: track
};
});
+3 -8
View File
@@ -65,17 +65,12 @@ define(function(){
};
var ass = "function assert(condition, message) { \nif (!condition) { \n throw message || \"Assertion failed\"; \n } \n }\n";
var code = {
"base": "var firstName = \"John\";\nvar middleName = \"James\";\nvar lastName = \"Smith\";\n\nvar fullName =",
"solution": "var firstName = \"John\";\nvar middleName = \"James\";\nvar lastName = \"Smith\";\n\nvar fullName = firstName + \" \" + middleName + \" \" + lastName;",
"validation": "console.log(fullName); assert(fullName == 'John James Smith');"
};
var ass = "function assert(condition, message) { \nif (!condition) { \n throw message || \"Assertion failed\"; \n } \n }\n";
var execute = function(solution, validation, callback) {
// Validate with validation code
evalJS([solution, ass, validation].join(";\n"), function(err, res) {
var code = [solution, ass, validation].join(";\n");
evalJS(code, function(err, res) {
if(err) return callback(err);
if (res.type == "error") callback(new Error(res.value));
+5
View File
@@ -0,0 +1,5 @@
define([], function() {
return {
isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
};
});
+1 -1
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long
+9 -1
View File
@@ -24,7 +24,9 @@
margin: 0px 0px;
padding: 5px 15px;
background: #fff;
border-radius: 0px;
border-radius: 2px;
font-size: 15px;
line-height: 1.7;
}
.btn-group {
@@ -46,4 +48,10 @@
}
}
}
&.without-animation {
.book-body {
.transition(none) !important;
}
}
}
+2 -1
View File
@@ -2,7 +2,7 @@
section.exercise {
padding: 0px;
margin: 20px 0px;
border: 2px solid #2f8cde;
border: 3px solid #2f8cde;
.header {
padding: 5px 15px;
@@ -21,6 +21,7 @@
.editor {
min-height: 50px;
font-size: 14px;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
+4 -7
View File
@@ -6,6 +6,8 @@
width: 100%;
height: 80px;
padding: 10px;
overflow: hidden;
color: #fff;
@@ -16,7 +18,8 @@
width: 100%;
height: 100%;
font-size: 24px;
line-height: 80px;
line-height: 60px;
border-radius: 2px;
background: @brand-success;
color: inherit;
@@ -34,12 +37,6 @@
&.finished, &.finished:hover {
background: darken(@btn-success-bg, 5%);
}
@media (max-width: 600px) {
span {
display: none;
}
}
}
}
}
+5
View File
@@ -58,4 +58,9 @@
margin-left: 250px;
}
}
&.without-animation {
.book-header h1 {
.transition(none) !important;
}
}
}
+9 -5
View File
@@ -1,9 +1,6 @@
.book .book-body .page-wrapper .page-inner section.normal {
font-size: 14px;
line-height: 1.6;
padding: 30px;
padding-top: 10px;
padding-bottom: 10px;
padding: 25px;
padding-top: 15px;
background-color: white;
@@ -113,6 +110,13 @@
ul :last-child, ol :last-child {
margin-bottom: 0; }
ul p {
margin: 0px;
}
ul ul {
margin: 0px;
}
dl {
padding: 0; }
+5
View File
@@ -14,6 +14,7 @@
.book .book-body {
@chapter-size: 16px;
@bar-background: #eee;
.book-progress {
@@ -65,6 +66,10 @@
background: @bar-background;
box-shadow: 0px 0px 1px #bbb;
&.new-chapter {
}
&.done {
background: @brand-success;
box-shadow: none;
+6
View File
@@ -90,4 +90,10 @@
left: 0px;
}
}
&.without-animation {
.book-summary {
.transition(none) !important;
}
}
}
+90
View File
@@ -0,0 +1,90 @@
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Tomorrow Comment */
.hljs-comment,
.hljs-title {
color: #8e908c;
}
/* Tomorrow Red */
.hljs-variable,
.hljs-attribute,
.hljs-tag,
.hljs-regexp,
.ruby .hljs-constant,
.xml .hljs-tag .hljs-title,
.xml .hljs-pi,
.xml .hljs-doctype,
.html .hljs-doctype,
.css .hljs-id,
.css .hljs-class,
.css .hljs-pseudo {
color: #c82829;
}
/* Tomorrow Orange */
.hljs-number,
.hljs-preprocessor,
.hljs-pragma,
.hljs-built_in,
.hljs-literal,
.hljs-params,
.hljs-constant {
color: #f5871f;
}
/* Tomorrow Yellow */
.ruby .hljs-class .hljs-title,
.css .hljs-rules .hljs-attribute {
color: #eab700;
}
/* Tomorrow Green */
.hljs-string,
.hljs-value,
.hljs-inheritance,
.hljs-header,
.ruby .hljs-symbol,
.xml .hljs-cdata {
color: #718c00;
}
/* Tomorrow Aqua */
.css .hljs-hexcolor {
color: #3e999f;
}
/* Tomorrow Blue */
.hljs-function,
.python .hljs-decorator,
.python .hljs-title,
.ruby .hljs-function .hljs-title,
.ruby .hljs-title .hljs-keyword,
.perl .hljs-sub,
.javascript .hljs-title,
.coffeescript .hljs-title {
color: #4271ae;
}
/* Tomorrow Purple */
.hljs-keyword,
.javascript .hljs-function {
color: #8959a8;
}
.hljs {
display: block;
background: white;
color: #4d4d4c;
padding: 0.5em;
}
.coffeescript .javascript,
.javascript .xml,
.tex .hljs-formula,
.xml .javascript,
.xml .vbscript,
.xml .css,
.xml .hljs-cdata {
opacity: 0.5;
}
+2
View File
@@ -5,6 +5,8 @@
@import "variables.less";
@import "fonts.less";
@import "highlight.less";
@import "book/header.less";
@import "book/summary.less";
@import "book/body.less";
+3 -1
View File
@@ -26,11 +26,12 @@ prog
.description('Build a gitbook from a directory')
.option('-o, --output <directory>', 'Path to output directory, defaults to ./_book')
.option('-t, --title <name>', 'Name of the book to generate, defaults to repo name')
.option('-i, --intro <intro>', 'Description of the book to generate')
.option('-g, --github <repo_path>', 'ID of github repo like : username/repo')
.action(buildFunc = function(dir, options) {
dir = dir || process.cwd();
outputDir = options.output || path.join(dir, '_book');
console.log('Starting build ...');
// Get repo's URL
return utils.gitURL(dir)
@@ -47,6 +48,7 @@ prog
outputDir,
{
title: options.title || utils.titleCase(repo),
description: options.intro,
github: options.github || repoID
}
);
+6 -2
View File
@@ -11,8 +11,9 @@ var generate = function(root, output, options) {
var files, summary, navigation, tpl;
options = _.defaults(options || {}, {
// Book title
// Book title, keyword, description
title: null,
description: "Book generated using GitBook",
// Origin github repository id
github: null
@@ -59,9 +60,12 @@ var generate = function(root, output, options) {
root: root,
output: output,
locals: {
title: options.title,
description: options.description,
githubAuthor: options.github.split("/")[0],
githubId: options.github,
title: options.title,
summary: summary,
allNavigation: navigation
}
+7
View File
@@ -3,6 +3,13 @@ var marked = require('marked');
var renderer = require('./renderer');
// Synchronous highlighting with highlight.js
marked.setOptions({
highlight: function (code) {
return require('highlight.js').highlightAuto(code).value;
}
});
// Split a page up into sections (lesson, exercises, ...)
function splitSections(nodes) {
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "gitbook",
"version": "0.0.1",
"version": "0.0.2",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
"dependencies": {
@@ -11,7 +11,8 @@
"send": "0.2.0",
"fstream-ignore": "0.0.7",
"commander": "2.2.0",
"fs-extra": "0.8.1"
"fs-extra": "0.8.1",
"highlight.js": "8.0.0"
},
"devDependencies": {
"mocha": "1.18.2",
+8 -3
View File
@@ -5,14 +5,19 @@
<meta charset="UTF-8">
<title>{% block title %} | GitBook{% endblock %}</title>
<meta name="robots" content="{% block robots %}noindex, nofollow{% endblock %}">
<link rel="icon" href="{{ staticBase }}/images/icons/32.png">
<link rel="shortcut icon" href="{{ staticBase }}/images/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="{{ staticBase }}/style.css">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="{% block description %}{% endblock %}">
<meta name="keywords" content="{% block keywords %}{% endblock %}" >
<meta name="description" content="{{ description }}">
<meta name="keywords" content="gitbook,github" >
<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">
<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.async=!0;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||[]);
mixpanel.init("01eb2b950ae09a5fdb15a98dcc5ff20e");
</script>
{% endblock %}
</head>
<body>
+3 -3
View File
@@ -15,7 +15,7 @@
</div>
<div class="chapters">
{% for p in progress.chapters %}
<div class="chapter {% if p.done %}done{% endif %}" data-progress="{{ p.level }}" style="left: {{ p.percent }}%;"></div>
<a href="{{ basePath }}/{{ p.path }}" title="{{ p.title }}" class="chapter {% if p.done %}done{% endif %} {% if p.level.length == 1 %}new-chapter{% endif %}" data-progress="{{ p.level }}" style="left: {{ p.percent }}%;"></a>
{% endfor %}
</div>
</div>
@@ -34,11 +34,11 @@
<div class="page-footer">
{% if _input == "README.md" %}
<a href="{{ basePath }}/{{ navigation.next.path }}" class="navigation-link">Start this book</a>
<a href="{{ basePath }}/{{ navigation.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<span>: {{ navigation.next.title }}</span></a>
<a href="{{ basePath }}/{{ navigation.next.path }}" class="navigation-link next">Next</a>
{% else %}
<div class="navigation-link coming-soon">Coming soon</div>
{% endif %}