Compare commits

..

115 Commits

Author SHA1 Message Date
Samy Pessé 3218ee7455 Fix tests to adapt to changes in parsers 2015-03-11 22:05:58 +01:00
Samy Pessé 0552007b8a Bump version to 2.0.0-beta.2 2015-03-11 22:03:54 +01:00
Samy Pessé 50bc89d9d9 Fix define of introduction from summary 2015-03-11 22:02:46 +01:00
Samy Pessé 743a88f53a Fix typo in bin message 2015-03-11 11:40:56 +01:00
Samy Pessé ee92c6dd99 Add changelog for 2.0.0-beta.1 2015-03-11 11:23:48 +01:00
Samy Pessé b6c54c17d1 Bump version to 2.0.0-beta.1 2015-03-11 11:17:56 +01:00
Samy Pessé 992ef1ab74 Use latest commit from nunjucks windows fix branch 2015-03-11 11:17:43 +01:00
Samy Pessé 960848ba34 Ensure inline svgs have xml header 2015-03-11 09:38:18 +01:00
Samy Pessé d9aca7a9df Fix #639: update nunjucks to support windows 2015-03-11 00:57:07 +01:00
Samy Pessé 05a0de2d86 Remove require of old dependency "shell-escape" 2015-03-11 00:50:48 +01:00
Samy Pessé 19e4f498cf Fix inline svg extraction on windows 2015-03-10 16:45:22 -07:00
Samy Pessé 3055139297 Fix run of svgexport on windows 2015-03-10 16:31:43 -07:00
Samy Pessé 3d6b099dea Fix links normalization on windows 2015-03-10 22:44:54 +01:00
Samy Pessé dd970e33b8 Remove --no-exit option from mocha tests runner 2015-03-10 21:31:43 +01:00
Samy Pessé 59ba479465 Test option --no-exit for mocha tests 2015-03-10 16:14:04 +01:00
Samy Pessé 54c9ecf3c2 Use mocha from node_modules/.bin 2015-03-10 15:44:39 +01:00
Samy Pessé 8308ae69a2 Remove command export from "npm test" 2015-03-10 15:01:51 +01:00
Samy Pessé bd6c3287ed Add badge for windows testing 2015-03-10 14:58:23 +01:00
Samy Pessé 24fc36deb1 Add appveyor.yml for windows testing
Related to #639
2015-03-10 14:52:09 +01:00
Samy Pessé 2f44b61cec Merge pull request #638 from wapmorgan/patch-1
Update README.md
2015-03-09 21:13:29 +01:00
wapmorgan 45ee503db1 Update README.md
Fix link
2015-03-10 00:12:53 +04:00
Samy Pessé dc826da99b Update README.md 2015-03-09 10:58:11 +01:00
Samy Pessé 3ea659d582 Improve readme presentation 2015-03-09 10:57:23 +01:00
Samy Pessé 34fc2831e0 Merge branch 'version/2.0' 2015-03-09 10:43:12 +01:00
Samy Pessé 1bf68a5aa0 Merge branch 'master' into version/2.0
Conflicts:
	README.md
2015-03-09 10:42:42 +01:00
Samy Pessé d72c397f23 Update gitbook-parsers@0.5.2 2015-03-08 23:09:50 +01:00
Samy Pessé 2c69525148 Add GitBook as book producer in ebook-convert 2015-03-08 22:53:18 +01:00
Samy Pessé ee3a0ba801 Fix #633: update markdown parser to fix codeblocks
Sort glossary and fix #634
2015-03-08 22:53:18 +01:00
Samy Pessé 7a4179a2a2 Merge pull request #631 from MHM5000/version/2.0
[i18n] - fa: Persian/Farsi
2015-03-07 18:48:05 +01:00
Mohammad Hossein Mojtahedi 1d0083c5f4 added @mhm5000 in translators 2015-03-07 18:22:40 +03:30
Mohammad Hossein Mojtahedi 33a6111a30 [i18n] - fa: Persian/Farsi 2015-03-07 16:48:44 +03:30
Samy Pessé a5d7a87e31 Enable rtl in ebooks 2015-03-06 22:45:53 +01:00
Samy Pessé c7f7c5b5ab Base translation for Arabic (with rtl support) 2015-03-06 22:32:45 +01:00
Samy Pessé 55a7b99b4d Fix #227: Add base rtl support for website 2015-03-06 22:32:25 +01:00
Samy Pessé 8bfba604b3 Update gitbook-parsers@0.5.0 and include page.prepare
Fix #625: escape code blocks in markdown
2015-03-06 16:54:46 +01:00
Samy Pessé 2a5fa1c5fb Fix #629: add generator name in template context 2015-03-06 14:34:55 +01:00
Samy Pessé a3e95feb26 Add instructions to use version from git 2015-03-06 13:58:23 +01:00
Samy Pessé 145b00f590 Fix #628: preserve pure anchor links and hash in relative links 2015-03-06 10:25:06 +01:00
Samy Pessé 5f2785f0a8 Escape svgexport args
Fixes shakiba/svgexport#5 and #624
2015-03-05 10:06:45 +01:00
Samy Pessé 412529c548 Merge pull request #621 from nasirkhan/version/2.0
Bengali (bn) added in theme/i18n
2015-02-27 17:48:07 +01:00
nasirkhan 547ec6ade8 bn language added 2015-02-27 22:29:10 +06:00
nasirkhan eac513cfa3 Merge remote-tracking branch 'upstream/version/2.0' into version/2.0 2015-02-27 22:16:11 +06:00
Aaron O'Mullan 5ec8a1f18c Add en.json
Fixes #620
2015-02-27 16:02:31 +01:00
Samy Pessé c923a7e01a Fix transformation of README.md links in index.html 2015-02-26 01:14:27 +01:00
Samy Pessé 366e6ed105 Bump version to 2.0.0-alpha.9 2015-02-24 13:57:20 +01:00
Samy Pessé 52078eb666 Use latest nunjucks from mozilla/nunjucks 2015-02-24 13:54:08 +01:00
Samy Pessé d9ddbff443 Fix links in sidebar 2015-02-24 13:51:10 +01:00
Samy Pessé 01b160f9a1 Fix normalization of html link (README to index) 2015-02-21 13:40:38 +01:00
Samy Pessé 23fcb817a4 Fix html snippets escaping 2015-02-20 20:52:07 +01:00
Samy Pessé f531a3f984 Update nunjucks-autoescape 2015-02-20 12:24:33 +01:00
Samy Pessé c777023e9f Add introduction to changelog 2015-02-17 14:18:49 +01:00
Samy Pessé 62c99759c1 Bump version to 2.0.0-alpha.8 2015-02-14 16:43:19 +01:00
Samy Pessé 6951c21d19 Update gitbook-parsers@0.4.1 2015-02-14 16:26:16 +01:00
Samy Pessé 3a8289483e Improve language detection from book.json 2015-02-14 15:34:19 +01:00
Samy Pessé 4079de9587 Fix #608: fix chapter name for glossary 2015-02-14 15:29:41 +01:00
Samy Pessé b86d171082 Escape description in title attr of glossary link
Related to #609
2015-02-14 11:53:30 +01:00
Samy Pessé 959b272e65 Fix #609: don't escape html in glossary 2015-02-14 11:52:33 +01:00
Samy Pessé 684440e2d1 Fix generation of multilingual book as ebook 2015-02-14 11:49:42 +01:00
Samy Pessé 4740cd3b06 Merge pull request #605 from GitbookIO/update/lodash
Update lodash to 3.x.x
2015-02-13 08:18:45 +01:00
Samy Pessé b3131d99d2 Update lodash@3.2.0 2015-02-13 08:16:28 +01:00
Samy Pessé b0fd2a67ea Fix test with post in blocks 2015-02-13 08:09:28 +01:00
Samy Pessé 7c83869869 Limit concurrent blocks processed 2015-02-13 00:04:27 +01:00
Samy Pessé 57d5c23eaf Accept post function from block to post process content 2015-02-12 23:36:22 +01:00
Samy Pessé 8d92b74e61 Fix page normalization with empty links or images 2015-02-12 18:43:06 +01:00
Samy Pessé 4e2cda99cc Complete changelog for 2.0.0-alpha.7 2015-02-12 16:40:50 +01:00
Samy Pessé dd250e0339 Bump version to 2.0.0-alpha.7 2015-02-12 16:30:55 +01:00
Samy Pessé 741b158631 Fix #596: fix display of glossary in ebook format 2015-02-12 16:27:52 +01:00
Samy Pessé 843889303e Improve pdf by adding default header and footer 2015-02-12 12:47:08 +01:00
Samy Pessé 4ad2b040b4 Always generate README.json with langs index
remove method langsIndex form generators (moved to finish)
2015-02-12 12:18:52 +01:00
Samy Pessé f5916b5c59 Remove log from test 2015-02-12 11:44:44 +01:00
Samy Pessé d9da4e9a08 Fix GitbookIO/plugin-youtube#2: hash remote image for local path 2015-02-12 11:40:17 +01:00
Samy Pessé 1d0f6370ad Fix default language to english 2015-02-12 08:19:38 +01:00
Samy Pessé 12a7a4c4cf Fix test for lodash 3.1.0 (from git) 2015-02-11 17:53:46 +01:00
Samy Pessé e4127d961e Update to gitbook-parsers@0.4.0 2015-02-09 18:10:46 +01:00
Samy Pessé 8e97655040 Complete zh translations 2015-02-09 11:38:12 +01:00
Samy Pessé 9b61b87873 Add Serif and Sans to all translations 2015-02-09 11:14:47 +01:00
Samy Pessé 4a99e37b2f Fix spaces in zh-tw translation 2015-02-09 11:12:07 +01:00
Samy Pessé 752b5e9b7c Merge pull request #602 from howiehu/version/2.0
add zh-tw (Traditional Chinese) i18n file
2015-02-09 11:09:04 +01:00
Samy Pessé b318f2fe94 Improve i18n to support locale normalization 2015-02-09 11:08:46 +01:00
Hao Hu 01c46030b6 Add @howiehu to authors and normalize zh-tw translation 2015-02-09 17:59:54 +08:00
Hao Hu 9803b05d8a add zh-tw (Traditional Chinese) i18n file 2015-02-09 17:56:25 +08:00
Samy Pessé 1337858fe6 Add @howiehu to authors and normalize zh translation 2015-02-09 10:16:37 +01:00
Aaron O'Mullan 925b9e88ad Merge pull request #601 from howiehu/version/2.0
Add Simplifiled Chinese (zh-cn) i18n file.
2015-02-09 09:58:36 +01:00
Hao Hu 7305011a8b add zh-cn (Simplifiled Chinese) i18n file 2015-02-09 16:53:30 +08:00
Samy Pessé 489f23f74e Fix #595: calcul link to glossary as an absolute path 2015-02-07 20:39:15 +01:00
Samy Pessé 370799ac55 Add test for #595: glossary links in subpages 2015-02-07 20:35:24 +01:00
Samy Pessé 4a9adb9440 Bump version to 2.0.0-alpha.6 2015-02-06 19:42:55 +01:00
Samy Pessé d8898b7a1f Add changelog for version 2.0.0-alpha.* 2015-02-06 15:54:40 +01:00
Samy Pessé bb7e081a37 Fix #588: Fix replacement of glossary terms by links 2015-02-06 15:28:53 +01:00
Samy Pessé c3ffa5e0ef Add test for glossary replacement #588 2015-02-06 15:07:01 +01:00
Samy Pessé 724bc2b59c Add capital to german translation of share links 2015-02-06 15:00:13 +01:00
Samy Pessé 178d2e2a48 Add @RyanOM as spanish translator 2015-02-06 14:35:23 +01:00
Samy Pessé 4d710c129c Merge pull request #590 from RyanOM/patch-2
Created es.json
2015-02-06 14:34:25 +01:00
RyanOM e4dbf62c0f Create es.json 2015-02-06 11:33:26 -02:00
Samy Pessé b0cd23fd34 Add @RyanOM as a translator 2015-02-06 14:32:20 +01:00
Samy Pessé af5764bc3b Merge pull request #589 from RyanOM/patch-1
Create pt.json
2015-02-06 14:29:31 +01:00
RyanOM 6309da1214 Create pt.json 2015-02-06 11:21:22 -02:00
Samy Pessé 38c9bfa357 Fix dom-serializer dependency 2015-02-05 21:10:17 +01:00
Samy Pessé f194cb513c Merge pull request #586 from ludovicofischer/version/2.0
Use tiny-lr instead of old unmaintained fork.
2015-02-05 20:50:02 +01:00
Ludovico Fischer 03ff892727 Use tiny-lr instead of old unmaintained fork. 2015-02-05 19:43:29 +01:00
Samy Pessé 8cc0f64f54 Handle SVG correctly in page normalization
Related to mathjax/MathJax-node#65
2015-02-05 17:36:44 +01:00
Samy Pessé 532e8b0388 Bump version to 2.0.0-alpha.5 2015-02-05 13:56:52 +01:00
Samy Pessé 35b3d50012 Add "finish:before" to the list of valid hooks 2015-02-05 13:56:43 +01:00
Samy Pessé 72ff9996ce Update fs-extra to fix fs.copy issue 2015-02-05 13:51:53 +01:00
Samy Pessé 0759c4dd78 Bump version to 2.0.0-alpha.4 2015-02-04 20:49:09 +01:00
Samy Pessé 82a1a151e4 Correctly copy cover for sub books 2015-02-04 20:29:49 +01:00
Samy Pessé ff6e8387fb Bump version to 2.0.0-alpha.3 2015-02-04 18:31:26 +01:00
Samy Pessé f71601e8d3 Fix generation of multilingual books as ebook 2015-02-04 18:31:07 +01:00
Samy Pessé 234a37726f Improve logs for images and ebook copy 2015-02-04 16:54:02 +01:00
Samy Pessé 65a7979874 Load plugins from the book in priority 2015-02-04 15:25:40 +01:00
Samy Pessé 6a00bf0fc0 Remove plugin list 2015-02-04 11:54:52 +01:00
Samy Pessé 853f3d6482 Add translators on AUTHORS.md
@gbonanome, @kmelve, @AndreyAkinshin, @winniehell
2015-02-04 11:52:00 +01:00
Samy Pessé 27de7cd914 Merge pull request #582 from kmelve/version/2.0
Added Norwegian translation
2015-02-04 11:42:46 +01:00
Knut Melvær 2318cae1e6 Added Norwegian translation 2015-02-04 11:39:40 +01:00
Samy Pessé e1594cde2c Remove doc about custom styles 2015-01-19 13:14:52 +01:00
50 changed files with 887 additions and 295 deletions
+28 -4
View File
@@ -7,12 +7,36 @@ Names below are ordered by first contribution.
Author
------
- Samy Pessé <samypesse@gmail.com>
- Aaron O'Mullan <aaron.omullan@gmail.com>
- Samy Pessé <samypesse@gmail.com> (@SamyPesse)
- Aaron O'Mullan <aaron.omullan@gmail.com> (@AaronO)
Contributors
------------
- Nijiko Yonskai
- Herman Starikov
- Nijiko Yonskai (@Nijikokun)
- Herman Starikov (@Hermanya)
Translators
------------
- German
- Winnie (@winniehell)
- Italian
- Giulio Bonanome (@gbonanome)
- Russian
- Andrey Akinshin (@AndreyAkinshin)
- Norwegian
- Knut Melvær (@kmelve)
- Persian (Farsi)
- Mohammad Hossein Mojtahedi (@mhm5000)
- Portuguese
- Ryan O'Mullan (@RyanOM)
- Spanish
- Ryan O'Mullan (@RyanOM)
- Simplifiled Chinese
- Hu Hao (@howiehu)
- Traditional Chinese
- Hu Hao (@howiehu)
- French
- Samy Pessé (@SamyPesse)
+67
View File
@@ -1,4 +1,71 @@
# Release notes
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 2.0.0-beta.2
- Fix definition of entry point title using SUMMARY.md
## 2.0.0-beta.1
- Fix windows incompatibility
- Add support for rtl (enabled by default for `ar` and `fa`)
- Escape code blocks in markdown parser
- Add Persian/Farsi translation (`fa`)
- Add Arabic translation (`ar`)
- Add Bengali translation (`bn`)
- Provide generator name in template context
## 2.0.0-alpha.9
- Fix links in sidebar
- Fix normalization of html link (README to index)
- Fix html snippets escaping
## 2.0.0-alpha.8
- Improve locale detection for i18n
- Fix chapter name for Glossary in pdf
- Don't escape html in glossary items
- Fix generation of multilingual book as ebook
- Add "post" block attribute to post-process
## 2.0.0-alpha.7
- Fix display of glossary in ebook formats
- Add default footer and header to pdf
- Fix generation of json format compatible with 1.x.x
- Add Simplifiled Chinese and Traditional Chinese translations
## 2.0.0-alpha.6
- Add es and pt translations
- Fix replacement of glossary terms
## 2.0.0-alpha.5
- Fix copy of files/covers
- Add back `finish:before` hook
## 2.0.0-alpha.4
- Fix copy of cover for multilingal books
## 2.0.0-alpha.3
- Norwegian translation
- Load plugins from book in priority
## 2.0.0-alpha.3
- Fix init command
- Update parsers to fix spaces in summary (`gitbook-parsers@0.3.1`)
## 2.0.0-alpha.1
- Externalize parsing into `gitbook-parsers` module
- Supports AsciiDoc and reStructuredText
- Hooks for page (`page:*`) are now deprecated, plugins should extend filters and blocks instead
- Hooks `summary` and `glossary` (after and before) have been removed
- Exercises and Quizzes are no longer parsed in the markdown parser
- Support for more markdown extensions: `.markdown`, `.mdown`
- Templates are rendered with nunjucks instead of swig, syntax is almost compatible, there is some changes with contexts and filters. `{{ super() }}` should be use instead of `{% parent %}`
- Clean output folder on build without removing `.git` and `.svn`
- MathJAX is no longer a default plugin
- SVG images are converted to PNG during generation of ebooks
- i18n in website and ebook (ru, it, de, fr)
- New templating syntax
- Content references (both internal and external)
- Glossary terms are handled during generation (also in ebook format)
## 1.5.0
- Fix `serve` command, broken by `1.4.2`
+31 -41
View File
@@ -1,12 +1,17 @@
GitBook
=======
:warning: This branch contains the version 2.0.
[![Build Status](https://travis-ci.org/GitbookIO/gitbook.png?branch=master)](https://travis-ci.org/GitbookIO/gitbook)
[![NPM version](https://badge.fury.io/js/gitbook.svg)](http://badge.fury.io/js/gitbook)
[![Build Status](https://travis-ci.org/GitbookIO/gitbook.png?branch=master)](https://travis-ci.org/GitbookIO/gitbook)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/GitbookIO/gitbook?branch=master&svg=true)](https://ci.appveyor.com/project/SamyPesse/gitbook)
GitBook is a command line tool (and Node.js library) for building beautiful books using GitHub/Git and Markdown (or AsciiDoc). Here is an example: [Learn Javascript](https://www.gitbook.com/book/GitBookIO/javascript). You can publish and host book easily online using [gitbook.com](https://www.gitbook.com), a web-editor is [also available](https://www.gitbook.com/editor). You can follow [@GitBookIO](https://twitter.com/GitBookIO) on Twitter. Complete documentation is available at [help.gitbook.io](http://help.gitbook.io/).
GitBook is a command line tool (and Node.js library) for building beautiful books using GitHub/Git and Markdown (or AsciiDoc). Here is an example: [Learn Javascript](https://www.gitbook.com/book/GitBookIO/javascript).
You can publish and host book easily online using [gitbook.com](https://www.gitbook.com), a web-editor is [also available](https://www.gitbook.com/editor).
Stay updated by following [@GitBookIO](https://twitter.com/GitBookIO) on Twitter or [GitBook](https://www.facebook.com/gitbookcom) on Facebook.
Complete documentation is available at [help.gitbook.com](http://help.gitbook.com/).
![Image](https://raw.github.com/GitbookIO/gitbook/master/preview.png)
@@ -38,14 +43,14 @@ $ gitbook build ./repository ./outputFolder
## Features
* [Output as a website or ebook (pdf, epub, mobi)](#output-formats)
* [Multi-Languages](#multi-languages)
* [Glossary](#glossary)
* [Cover](#cover)
* [AsciiDoc Support](#asciidoc)
* [Variables and Templating](#variables-and-templating)
* [Content References](#content-references)
* [Plugins](#plugins)
* [Output as a website or ebook (pdf, epub, mobi)](http://help.gitbook.com/format/output.html)
* [Multi-Languages](http://help.gitbook.com/format/languages.html)
* [Glossary](http://help.gitbook.com/format/glossary.html)
* [Cover](http://help.gitbook.com/format/cover.html)
* [AsciiDoc Support](http://help.gitbook.com/format/asciidoc.html)
* [Variables and Templating](http://help.gitbook.com/format/templating.html)
* [Content References](http://help.gitbook.com/format/conrefs.html)
* [Plugins](http://help.gitbook.com/plugins/index.html)
* Interractive reader website:
* Search
* Font Settings (Serif, Sans Serif)
@@ -199,36 +204,8 @@ The platform [GitBook.com](https://www.gitbook.com/) is like an "Heroku for book
Plugins can be used to extend your book's functionality. Read [GitbookIO/plugin](https://github.com/GitbookIO/plugin) for more information about how to build a plugin for GitBook.
Plugins needed to build a book can be installed using: `gitbook install ./`.
Plugins needed to build a book can be installed using: `gitbook install ./`. You can find plugins at [plugins.gitbook.com](http://plugins.gitbook.com).
##### Official plugins:
| Name | Description |
| ----- | ---- |
| [exercises](https://github.com/GitbookIO/plugin-exercises) | Add interactive exercises to your book. |
| [quizzes](https://github.com/GitbookIO/plugin-quizzes) | Add interactive quizzes to your book. |
| [mathjax](https://github.com/GitbookIO/plugin-mathjax) | Displays mathematical notation in the book. |
| [mixpanel](https://github.com/GitbookIO/plugin-mixpanel) | Mixpanel tracking for your book |
| [infinitescroll](https://github.com/GitbookIO/gitbook-plugin-infinitescroll) | Infinite Scrolling |
##### Other plugins:
| Name | Description |
| ----- | ---- |
| [Google Analytics](https://github.com/GitbookIO/plugin-ga) | Google Analytics tracking for your book |
| [Disqus](https://github.com/GitbookIO/plugin-disqus) | Disqus comments integration in your book |
| [Autocover](https://github.com/GitbookIO/plugin-autocover) | Generate a cover for your book |
| [Transform annoted quotes to notes](https://github.com/erixtekila/gitbook-plugin-richquotes) | Allow extra markdown markup to render blockquotes as nice notes |
| [Send code to console](https://github.com/erixtekila/gitbook-plugin-toconsole) | Evaluate javascript block in the browser inspector's console |
| [Revealable sections](https://github.com/mrpotes/gitbook-plugin-reveal) | Reveal sections of the page using buttons made from the first title in each section |
| [Markdown within HTML](https://github.com/mrpotes/gitbook-plugin-nestedmd) | Process markdown within HTML blocks - allows custom layout options for individual pages |
| [Bootstrap JavaScript plugins](https://github.com/mrpotes/gitbook-plugin-bootstrapjs) | Use the [Bootstrap JavaScript plugins](http://getbootstrap.com/javascript) in your online GitBook |
| [Piwik Open Analytics](https://github.com/emmanuel-keller/gitbook-plugin-piwik) | Piwik Open Analytics tracking for your book |
| [Heading Anchors](https://github.com/rlmv/gitbook-plugin-anchors) | Add linkable Github-style anchors to headings |
| [JSBin](https://github.com/jcouyang/gitbook-plugin-jsbin) | Embedded jsbin frame into your book |
| [GrVis](https://github.com/romanlytkin/gitbook-grvis) | Gitbook GrViz plugin is used to select from markdown dot and converting it into a picture format svg |
| [PlantUml](https://github.com/romanlytkin/gitbook-plantuml) | Gitbook PlantUml plugin is used to select from markdown uml and converting it into a picture format svg |
| [Mermaid](https://github.com/JozoVilcek/gitbook-plugin-mermaid) | Adds diagrams and flowcharts rendered by [mermaid](https://github.com/knsv/mermaid) |
## Debugging
@@ -237,3 +214,16 @@ You can use the options `--log=debug` and `--debug` to get better error messages
```
$ gitbook build ./ -- log=debug --debug
```
#### How to use the latest commit from GitBook in gitbook-cli
To use the latest commit from `GitBook/gitbook` with `gitbook-cli`:
```
$ git clone https://github.com/GitbookIO/gitbook.git ./gitbook
$ gitbook versions:link 2.0.0 ./gitbook
```
Now the version tag `2.0.0` wil be associated with the `./gitbook` folder.
You can uninstall it using: `gitbook versions:uninstall 2.0.0`.
+29
View File
@@ -0,0 +1,29 @@
# Fix line endings in Windows. (runs before repo cloning)
init:
- git config --global core.autocrlf input
# Test against these versions of Node.js.
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.11"
# Install scripts. (runs after repo cloning)
install:
# Get the latest stable version of Node.js or io.js
- ps: Install-Product node $env:nodejs_version
# install svgexport
- npm install svgexport -g
# install modules
- npm install
# Post-install test scripts.
test_script:
# Output useful info for debugging.
- node --version
- npm --version
# run tests
- npm test
# Don't actually build.
build: off
+1 -1
View File
@@ -3,5 +3,5 @@
var color = require('bash-color');
console.log(color.red("You need to install 'gitbook-cli' to have access to the gitbook command anywhere on your system."));
console.log(color.red("If you've installe this package globally, you need to uninstall it."));
console.log(color.red("If you've installed this package globally, you need to uninstall it."));
console.log(color.red(">> Run 'npm uninstall -g gitbook' then 'npm install -g gitbook-cli'"));
+48 -23
View File
@@ -10,6 +10,7 @@ var fs = require("./utils/fs");
var parseNavigation = require("./utils/navigation");
var parseProgress = require("./utils/progress");
var pageUtil = require("./utils/page");
var batch = require("./utils/batch");
var links = require("./utils/links");
var logger = require("./utils/logger");
@@ -117,7 +118,7 @@ Book.prototype.parse = function() {
path.join(that.root, lang.path),
_.merge({}, that.context, {
config: _.extend({}, that.options, {
'output': path.join(that.options.output, lang.path),
'output': path.join(that.options.output, lang.lang),
'language': lang.lang
})
}),
@@ -185,8 +186,6 @@ Book.prototype.generate = function(generator) {
return generator.prepare();
})
// Generate content
.then(function() {
if (that.isMultilingual()) {
@@ -226,9 +225,11 @@ Book.prototype.generate = function(generator) {
// Finally let's generate content
.then(function() {
return _.reduce(ops["content"] || [], function(prev, file) {
var nFiles = (ops["content"] || []).length;
return _.reduce(ops["content"] || [], function(prev, file, i) {
return prev.then(function() {
that.log.debug.ln("converting", file);
var p = ((i*100)/nFiles).toFixed(0)+"%";
that.log.info.ln("processing", file, p);
return Q(generator.convertFile(file));
});
}, Q());
@@ -263,9 +264,6 @@ Book.prototype.generateMultiLingual = function(generator) {
return book.generate(that.options.generator);
});
}, Q());
})
.then(function() {
return generator.langsIndex(that.langs);
});
};
@@ -280,9 +278,7 @@ Book.prototype.generateFile = function(output, options) {
return fs.tmp.dir()
.then(function(tmpDir) {
book.config.extend({
output: tmpDir
});
book.setOutput(tmpDir);
return book.generate(options.ebookFormat)
.then(function(_options) {
@@ -295,14 +291,11 @@ Book.prototype.generateFile = function(output, options) {
_tmpDir = path.join(_tmpDir, lang);
}
book.log.info("copy ebook to", output, "...");
book.log.debug.ln("copy ebook to", _outputFile);
return fs.copy(
path.join(_tmpDir, "index."+options.ebookFormat),
_outputFile
)
.then(function() {
book.log.info.ok();
});
);
};
// Multi-langs book
@@ -313,12 +306,15 @@ Book.prototype.generateFile = function(output, options) {
_.map(book.langs, function(lang) {
return copyFile(lang.lang);
})
);
)
.thenResolve(book.langs.length);
} else {
return copyFile();
return copyFile().thenResolve(1);
}
})
.then(function() {
.then(function(n) {
book.log.info.ok(n+" file(s) generated");
return fs.remove(tmpDir);
});
});
@@ -424,6 +420,7 @@ Book.prototype.parseSummary = function() {
.then(function(content) {
return summary.parser.summary(content, {
entryPoint: that.readmeFile,
entryPointTitle: "",
files: that.files
});
});
@@ -511,17 +508,25 @@ Book.prototype.parsePage = function(filename, options) {
return interpolate(options.interpolateTemplate);
})
// Prepare page markup
.then(function() {
return filetype.page.prepare(page.content)
.then(function(content) {
page.content = content;
});
})
// Generate template
.then(function() {
return that.template.renderPage(page);
})
// Parse markup
// Prepare and Parse markup
.then(function(content) {
page.content = content;
that.log.debug.ln("use file parser", filetype.name, "for", filename);
return filetype.parser.page(page.content);
return filetype.page(page.content);
})
// Post process sections
@@ -577,7 +582,7 @@ Book.prototype.findFile = function(filename) {
.then(function(exists) {
if (!exists) return null;
return {
parser: parsers.get(ext).parser,
parser: parsers.get(ext),
path: filepath
};
})
@@ -650,6 +655,16 @@ Book.prototype.parentRoot = function() {
return this.root;
};
// Return true if it's a sub-book
Book.prototype.isSubBook = function() {
return !!this.parent;
};
// Test if the file is the entry point
Book.prototype.isEntryPoint = function(fp) {
return fp == this.readmeFile;
};
// Resolve a path in book
Book.prototype.resolve = function(p) {
return path.resolve(this.root, p);
@@ -658,7 +673,7 @@ Book.prototype.resolve = function(p) {
// Normalize a link to .html and convert README -> index
Book.prototype.contentLink = function(link) {
if (
path.basename(link) == "README"
path.basename(link, path.extname(link)) == "README"
|| link == this.readmeFile
) {
link = path.join(path.dirname(link), "index"+path.extname(link));
@@ -692,6 +707,16 @@ Book.prototype._defaultsStructure = function(filename) {
that.langsFile = that.langsFile || that.config.getStructure("langs")+extension;
}
// Change output path
Book.prototype.setOutput = function(p) {
var that = this;
this.options.output = path.resolve(p);
_.each(this.books, function(book) {
book.setOutput(path.join(that.options.output, book.options.language));
});
};
// Init and return a book
Book.init = function(root) {
+19 -9
View File
@@ -5,6 +5,7 @@ var semver = require('semver');
var pkg = require('../package.json');
var fs = require("./utils/fs");
var i18n = require("./utils/i18n");
// Default plugins added to each books
var defaultsPlugins = [];
@@ -95,18 +96,26 @@ Configuration.prototype.load = function() {
}
})
.then(function() {
that.options.output = path.resolve(that.options.output || path.join(that.book.root, "_book"));
that.options.plugins = normalizePluginsList(that.options.plugins);
that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || "");
that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins);
that.options.plugins = _.uniq(that.options.plugins, "name");
if (!semver.satisfies(pkg.version, that.options.gitbook)) {
throw "GitBook version doesn't satisfy version required by the book: "+that.options.gitbook;
}
if (that.options.gitbook == "*") {
that.book.log.warn.ln("you should specify a gitbook version to use in your book.json, for example: "+(_.first(pkg.version.split("."))+".x.x"));
}
that.options.output = path.resolve(that.options.output || path.join(that.book.root, "_book"));
that.options.plugins = normalizePluginsList(that.options.plugins);
that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || "");
that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins);
that.options.plugins = _.uniq(that.options.plugins, "name");
// Default value for text direction (from language)
if (!that.options.direction) {
var lang = i18n.getByLanguage(that.options.language);
if (lang) that.options.direction = lang.direction;
}
that.options.gitbook = pkg.version;
});
};
@@ -122,7 +131,7 @@ Configuration.prototype.getStructure = function(name) {
// Return normalized language
Configuration.prototype.normalizeLanguage = function() {
return _.first(this.options.language.split("-")).toLowerCase();
return i18n.normalizeLanguage(this.options.language);
};
@@ -138,6 +147,7 @@ Configuration.DEFAULT = {
"description": null,
"isbn": null,
"language": "en",
"direction": null,
// version of gitbook to use
"gitbook": "*",
@@ -217,8 +227,8 @@ Configuration.DEFAULT = {
"margin": {
"right": 62,
"left": 62,
"top": 36,
"bottom": 36
"top": 56,
"bottom": 56
},
//Header HTML template. Available variables: _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_.
+1 -6
View File
@@ -58,7 +58,7 @@ BaseGenerator.prototype.copyCover = function() {
])
.fail(function() {
// If orignaly from multi-lang, try copy from parent
if (!that.isMultilingual()) return;
if (!that.book.isSubBook()) return;
return Q.all([
fs.copy(path.join(that.book.parentRoot(), "cover.jpg"), path.join(that.options.output, "cover.jpg")),
@@ -70,11 +70,6 @@ BaseGenerator.prototype.copyCover = function() {
});
};
// Generate the langs index
BaseGenerator.prototype.langsIndex = function(langs) {
return Q.reject(new Error("Langs index is not supported in this generator"));
};
// At teh end of the generation
BaseGenerator.prototype.finish = function() {
return Q.reject(new Error("Could not finish generation"));
+13 -11
View File
@@ -41,18 +41,14 @@ Generator.prototype.writeSummary = function() {
return this._writeTemplate(this.templates["summary"], {}, path.join(this.options.output, "SUMMARY.html"));
};
Generator.prototype.langsIndex = function(langs) {
return Q();
};
Generator.prototype.finish = function() {
var that = this;
return BaseGenerator.prototype.finish.apply(this)
.then(function() {
return that.writeSummary();
})
return Q()
.then(this.copyAssets)
.then(this.copyCover)
.then(this.writeGlossary)
.then(this.writeSummary)
.then(function() {
if (!that.ebookFormat) return Q();
@@ -68,6 +64,8 @@ Generator.prototype.finish = function() {
"--comments": that.options.description,
"--isbn": that.options.isbn,
"--authors": that.options.author,
"--language": that.options.language,
"--book-producer": "GitBook",
"--publisher": "GitBook",
"--chapter": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter ')]",
"--chapter-mark": "pagebreak",
@@ -92,8 +90,12 @@ Generator.prototype.finish = function() {
"--pdf-mono-font-size": String(pdfOptions.fontSize),
"--paper-size": String(pdfOptions.paperSize),
"--pdf-page-numbers": Boolean(pdfOptions.pageNumbers),
"--pdf-header-template": String(pdfOptions.headerTemplate),
"--pdf-footer-template": String(pdfOptions.footerTemplate)
"--pdf-header-template": String(pdfOptions.headerTemplate) || "<p class='header'><span>"+that.options.title+"</span></p>",
"--pdf-footer-template": String(pdfOptions.footerTemplate) || "<p class='footer'><span>_SECTION_</span> <span style='float:right;'>_PAGENUM_</span></p>"
});
} else if (that.ebookFormat == "epub") {
_.extend(_options, {
"--dont-split-on-page-breaks": true
});
}
+14 -10
View File
@@ -14,7 +14,6 @@ util.inherits(Generator, BaseGenerator);
// Ignore some methods
Generator.prototype.transferFile = function(input) { };
Generator.prototype.finish = function() { };
// Convert an input file
Generator.prototype.convertFile = function(input) {
@@ -37,21 +36,26 @@ Generator.prototype.convertFile = function(input) {
});
};
// Generate languages index
// Contains the first languages readme and langs infos
Generator.prototype.langsIndex = function(langs) {
// Finish generation
Generator.prototype.finish = function() {
return this.writeReadme();
};
// Write README.json
Generator.prototype.writeReadme = function() {
var that = this;
if (langs.length == 0) return Q.reject("Need at least one language");
var mainLang = _.first(langs).lang;
var readme = links.changeExtension(that.book.readmeFile, ".json");
var mainlang, langs;
return Q()
.then(function() {
langs = that.book.langs;
mainLang = langs.length > 0? _.first(langs).lang : null;
readme = links.changeExtension(that.book.readmeFile, ".json");
// Read readme from main language
return fs.readFile(
path.join(that.options.output, mainLang, readme)
mainLang? path.join(that.options.output, mainLang, readme) : path.join(that.options.output, readme)
);
})
.then(function(content) {
+12 -18
View File
@@ -12,6 +12,7 @@ var fs = require("../utils/fs");
var BaseGenerator = require("../generator");
var links = require("../utils/links");
var pageUtil = require("../utils/page");
var i18n = require("../utils/i18n");
var pkg = require("../../package.json");
@@ -74,20 +75,12 @@ Generator.prototype.prepareTemplates = function() {
Generator.prototype.prepareTemplateEngine = function() {
var that = this;
return fs.readdir(path.resolve(__dirname, "../../theme/i18n"))
.then(function(locales) {
return Q()
.then(function() {
var language = that.book.config.normalizeLanguage();
locales = _.chain(locales)
.map(function(local) {
local = path.basename(local, ".json");
return [local, require("../../theme/i18n/"+local)];
})
.object()
.value();
if (!_.contains(_.keys(locales), language) && language != "en") {
that.book.log.warn.ln("Language '"+language+"' is not available as a layout locales (en, "+_.keys(locales).join(", ")+")");
if (!i18n.getByLanguage(language) && language != "en") {
that.book.log.warn.ln("Language '"+language+"' is not available as a layout locales (en, "+i18n.getLanguages().join(", ")+")");
}
var folders = _.chain(that.templates)
@@ -114,7 +107,7 @@ Generator.prototype.prepareTemplateEngine = function() {
that.env.addExtension('FilterExtension', new FilterExtension(that.env));
that.env.addExtension('I18nExtension', new I18nExtension({
env: that.env,
translations: locales,
translations: i18n.getLocales(),
locale: "language"
}));
});
@@ -125,7 +118,8 @@ Generator.prototype.finish = function() {
return this.copyAssets()
.then(this.copyCover)
.then(this.writeGlossary)
.then(this.writeSearchIndex);
.then(this.writeSearchIndex)
.then(this.writeLangsIndex)
};
// Convert an input file
@@ -148,7 +142,7 @@ Generator.prototype.convertFile = function(input) {
var basePath = path.relative(path.dirname(output), that.options.output) || ".";
if (process.platform === 'win32') basePath = basePath.replace(/\\/g, '/');
that.book.log.info.ln("write parsed file", page.path, "to", relativeOutput);
that.book.log.debug.ln("write parsed file", page.path, "to", relativeOutput);
return that._writeTemplate(that.templates["page"], {
progress: page.progress,
@@ -163,11 +157,11 @@ Generator.prototype.convertFile = function(input) {
};
// Write the index for langs
Generator.prototype.langsIndex = function(langs) {
Generator.prototype.writeLangsIndex = function() {
var that = this;
if (!this.book.langs.length) return Q();
return this._writeTemplate(this.templates["langs"], {
langs: langs
langs: this.book.langs
}, path.join(this.options.output, "index.html"));
};
+1 -1
View File
@@ -1,7 +1,7 @@
var Q = require("q");
var _ = require("lodash");
var path = require("path");
var tinylr = require('tiny-lr-fork');
var tinylr = require('tiny-lr');
var color = require('bash-color');
var Book = require("./book");
+5 -2
View File
@@ -22,15 +22,18 @@ var Plugin = function(book, name) {
"gitbook-"+name,
name,
], function(_name) {
if (this.load(_name, __dirname)) return false;
// Load from the book
if (this.load(_name, book.root)) return false;
// Load from default plugins
if (this.load(_name, __dirname)) return false;
}, this);
};
// Type of plugins resources
Plugin.RESOURCES = ["js", "css"];
Plugin.HOOKS = [
"init", "finish"
"init", "finish", "finish:before"
]
// Load from a name
+44 -20
View File
@@ -6,6 +6,7 @@ var nunjucks = require("nunjucks");
var git = require("./utils/git");
var stringUtils = require("./utils/string");
var fs = require("./utils/fs");
var batch = require("./utils/batch");
var pkg = require("../package.json");
@@ -87,18 +88,21 @@ TemplateEngine.prototype.processBlock = function(blk) {
if (_.isString(blk)) blk = { body: blk };
blk = _.defaults(blk, {
parse: false
parse: false,
post: undefined
});
blk.id = _.uniqueId("blk");
var toAdd = (!blk.parse) || (blk.post != undefined);
// Add to global map
if (toAdd) this.blocks[blk.id] = blk;
//Parsable block, just return it
if (blk.parse) {
return blk.body;
}
// Add to global map
this.blocks[blk.id] = blk;
// Return it as a macro
return "%+%"+blk.id+"%+%";
};
@@ -114,9 +118,6 @@ TemplateEngine.prototype.replaceBlocks = function(content) {
var body = blk.body;
// Remove it from map
delete that.blocks[key];
return body;
});
};
@@ -239,21 +240,25 @@ TemplateEngine.prototype.addBlock = function(name, block) {
var args = Array.prototype.slice.call(arguments, 1);
var callback = args.pop();
// Extract blocks body
var _blocks = _.chain(block.blocks)
.reverse()
.map(function(blockName){
return {
name: blockName,
body: args.pop()()
};
})
.reverse()
.value();
// Extract blocks
var blocks = args
.concat([])
.slice(-block.blocks.length);
// Eliminate blocks from list
if (block.blocks.length > 0) args = args.slice(0, -block.blocks.length);
// Extract main body and kwargs
var body = args.pop();
var kwargs = args.pop() || {};
// Extract blocks body
var _blocks = _.map(block.blocks, function(blockName, i){
return {
name: blockName,
body: blocks[i]()
};
});
var func = that.bindContext(block.process);
@@ -313,7 +318,8 @@ TemplateEngine.prototype.renderString = function(content, context, options) {
// infos about gitbook
gitbook: {
version: pkg.version
version: pkg.version,
generator: this.book.options.generator
}
});
options = _.defaults(options || {}, {
@@ -363,8 +369,26 @@ TemplateEngine.prototype.renderPage = function(page) {
// Post process content
TemplateEngine.prototype.postProcess = function(content) {
var that = this;
return Q(content)
.then(this.replaceBlocks);
.then(that.replaceBlocks)
.then(function(_content) {
return batch.execEach(that.blocks, {
max: 20,
fn: function(blk, blkId) {
return Q()
.then(function() {
if (!blk.post) return Q();
return blk.post();
})
.then(function() {
delete that.blocks[blkId];
});
}
})
.thenResolve(_content);
});
};
module.exports = TemplateEngine;
+52
View File
@@ -0,0 +1,52 @@
var Q = require("q");
var _ = require("lodash");
// Execute a method for all element
function execEach(items, options) {
if (_.size(items) == 0) return Q();
var concurrents = 0, d = Q.defer(), pending = [];
options = _.defaults(options || {}, {
max: 100,
fn: function(item) {}
});
function startItem(item, i) {
if (concurrents >= options.max) {
pending.push([item, i]);
return;
}
concurrents++;
Q()
.then(function() {
return options.fn(item, i);
})
.then(function() {
concurrents--;
// Next pending
var next = pending.shift();
if (concurrents == 0 && !next) {
d.resolve();
} else if (next) {
startItem.apply(null, next);
}
})
.fail(function(err) {
pending = [];
d.reject(err);
})
}
_.each(items, startItem);
return d.promise;
}
module.exports = {
execEach: execEach
};
+72
View File
@@ -0,0 +1,72 @@
var _ = require("lodash");
var path = require("path");
var fs = require("fs");
var I18N_PATH = path.resolve(__dirname, "../../theme/i18n/")
var getLocales = _.memoize(function() {
var locales = fs.readdirSync(I18N_PATH);
return _.chain(locales)
.map(function(local) {
local = path.basename(local, ".json");
return [local, _.extend({
direction: "ltr"
}, require(path.join(I18N_PATH, local)), {
id: local
})];
})
.object()
.value();
});
var getLanguages = function() {
return _.keys(getLocales());
};
var getByLanguage = function(lang) {
lang = normalizeLanguage(lang);
var locales = getLocales();
return locales[lang];
};
var compareLocales = function(lang, locale) {
var langMain = _.first(lang.split("-"));
var langSecond = _.last(lang.split("-"));
var localeMain = _.first(locale.split("-"));
var localeSecond = _.last(locale.split("-"));
if (locale == lang) return 100;
if (localeMain == langMain) return 50;
if (localeSecond == langSecond) return 20;
return 0;
};
var normalizeLanguage = _.memoize(function(lang) {
var locales = getLocales();
var language = _.chain(locales)
.values()
.map(function(locale) {
locale = locale.id;
return {
locale: locale,
score: compareLocales(lang, locale)
}
})
.filter(function(lang) {
return lang.score > 0;
})
.sortBy("score")
.pluck("locale")
.last()
.value();
return language || lang;
});
module.exports = {
getLocales: getLocales,
getLanguages: getLanguages,
getByLanguage: getByLanguage,
normalizeLanguage: normalizeLanguage
};
+13 -8
View File
@@ -1,28 +1,33 @@
var _ = require("lodash");
var Q = require("q");
var fs = require("./fs");
var exec = require('child_process').exec;
var spawn = require('spawn-cmd').spawn;
var links = require("./links");
// Convert a svg file
var convertSVG = function(source, dest, options) {
if (!fs.existsSync(source)) return Q.reject(new Error("File doesn't exist: "+source));
var d = Q.defer();
options = _.defaults(options || {}, {
});
var command = "svgexport "+source+" "+dest;
//var command = shellescape(['svgexport', source, dest]);
var child = spawn('svgexport', [source, dest]);
var child = exec(command, function (error, stdout, stderr) {
if (error) {
if (error.code == 127) error = new Error("Need to install 'svgexport' using 'npm install svgexport -g'");
return d.reject(error);
child.on("error", function(error) {
if (error.code == "ENOENT") error = new Error("Need to install 'svgexport' using 'npm install svgexport -g'");
return d.reject(error);
});
child.on("close", function(code) {
if (code == 0 && fs.existsSync(dest)) {
d.resolve();
} else {
d.reject(new Error("Error converting "+source+" into "+dest));
}
d.resolve();
});
return d.promise;
+21 -8
View File
@@ -15,12 +15,27 @@ var isRelative = function(href) {
try {
var parsed = url.parse(href);
return !!(!parsed.protocol && parsed.path);// && parsed.path[0] != '/';
return !!(!parsed.protocol && parsed.path);
} catch(err) {}
return true;
};
// Return true if the link is an achor
var isAnchor = function(href) {
try {
var parsed = url.parse(href);
return !!(!parsed.protocol && !parsed.path && parsed.hash);
} catch(err) {}
return false;
};
// Normalize a path to be a link
var normalizeLink = function(s) {
return s.replace(/\\/g, '/');
};
// Relative to absolute path
// dir: directory parent of the file currently in rendering process
// outdir: directory parent from the html output
@@ -36,7 +51,7 @@ var toAbsolute = function(_href, dir, outdir) {
_href = path.relative(outdir, hrefInRoot);
// Normalize windows paths
_href = _href.replace(/\\/g, '/');
_href = normalizeLink(_href);
return _href;
};
@@ -45,11 +60,7 @@ var toAbsolute = function(_href, dir, outdir) {
var join = function() {
var _href = path.join.apply(path, arguments);
if (process.platform === 'win32') {
_href = _href.replace(/\\/g, '/');
}
return _href;
return normalizeLink(_href);
};
// Change extension
@@ -61,9 +72,11 @@ var changeExtension = function(filename, newext) {
};
module.exports = {
isAnchor: isAnchor,
isRelative: isRelative,
isExternal: isExternal,
toAbsolute: toAbsolute,
join: join,
changeExtension: changeExtension
changeExtension: changeExtension,
normalize: normalizeLink
};
+61 -36
View File
@@ -1,13 +1,16 @@
var Q = require('q');
var _ = require('lodash');
var url = require('url');
var path = require('path');
var cheerio = require('cheerio');
var domSerializer = require('dom-serializer');
var request = require('request');
var crc = require("crc");
var links = require('./links');
var imgUtils = require('./images');
var fs = require('./fs');
var batch = require('./batch');
// Render a cheerio dom as html
var renderDom = function($, dom, options) {
@@ -78,7 +81,14 @@ function pregQuote( str ) {
// Adapt an html snippet to be relative to a base folder
function normalizeHtml(src, options) {
var $ = cheerio.load(src, { xmlMode: false});
var $ = cheerio.load(src, {
// We should parse html without trying to normalize too much
xmlMode: false,
// SVG need some attributes to use uppercases
lowerCaseAttributeNames: false,
lowerCaseTags: false
});
var toConvert = [];
var svgContent = {};
var outputRoot = options.book.options.output;
@@ -95,7 +105,7 @@ function normalizeHtml(src, options) {
// Generate filename
dest = "/"+fs.getUniqueFilename(outputRoot, dest);
svgContent[dest] = content;
svgContent[dest] = '<?xml version="1.0" encoding="UTF-8"?>'+content;
$(this).replaceWith($("<img>").attr("src", dest));
});
}
@@ -104,6 +114,7 @@ function normalizeHtml(src, options) {
$("img").each(function() {
var origin = undefined;
var src = $(this).attr("src");
if (!src) return;
var isExternal = links.isExternal(src);
// Transform as relative to the bases
@@ -116,13 +127,13 @@ function normalizeHtml(src, options) {
// If image is external and ebook, then downlaod the images
if (isExternal) {
origin = src;
src = "/"+fs.getUniqueFilename(outputRoot, path.basename(src));
src = "/"+crc.crc32(origin).toString(16)+path.extname(origin);
src = links.toAbsolute(src, options.base, options.output);
isExternal = false;
}
var ext = path.extname(src);
var srcAbs = path.join("/", options.base, src);
var srcAbs = links.join("/", options.base, src);
// Test image extension
if (_.contains(imgUtils.INVALID, ext)) {
@@ -134,7 +145,7 @@ function normalizeHtml(src, options) {
var dest = "";
// Replace extension
dest = path.join(path.dirname(srcAbs), path.basename(srcAbs, ext)+".png");
dest = links.join(path.dirname(srcAbs), path.basename(srcAbs, ext)+".png");
dest = dest[0] == "/"? dest.slice(1) : dest;
// Get a name that doesn't exists
@@ -153,7 +164,7 @@ function normalizeHtml(src, options) {
dest: path.join("./", dest)
});
src = path.join("/", dest);
src = links.join("/", dest);
}
// Reset as relative to output
@@ -174,16 +185,24 @@ function normalizeHtml(src, options) {
$("a").each(function() {
var href = $(this).attr("href");
if (!href) return;
if (links.isRelative(href)) {
var absolutePath = path.join(options.base, href);
if (links.isAnchor(href)) {
// Keep it as it is
} else if (links.isRelative(href)) {
var parts = url.parse(path.join(options.base, href));
var absolutePath = parts.pathname;
var anchor = parts.hash;
// If is in navigation relative: change extsnio nto be .html
if (options.navigation[absolutePath]) href = links.changeExtension(href, ".html");
// If is in navigation relative: transform as content
if (options.navigation[absolutePath]) {
href = options.book.contentLink(href);
}
// Transform as absolute
href = links.toAbsolute(href, options.base, options.output);
href = links.toAbsolute(href, options.base, options.output)+anchor;
} else {
// External links
$(this).attr("target", "_blank");
}
@@ -198,12 +217,13 @@ function normalizeHtml(src, options) {
$("*").each(function() {
replaceText($, this, r, function(match) {
// Add to files index in glossary
if (!includedInFiles) {
includedInFiles = true;
term.files = term.files || [];
term.files.push(options.navigation[options.input]);
}
return "<a href='"+links.toAbsolute("GLOSSARY.html", options.base, options.output)+"#"+term.id+"' class='glossary-term' title='"+term.description+"'>"+match+"</span>";
return "<a href='"+links.toAbsolute("/GLOSSARY.html", options.base, options.output)+"#"+term.id+"' class='glossary-term' title='"+_.escape(term.description)+"'>"+match+"</a>";
});
});
});
@@ -218,36 +238,41 @@ function normalizeHtml(src, options) {
function convertImages(images, options) {
if (!options.convertImages) return Q();
options.book.log.info.ln("convert ", images.length, "images to png");
var downloaded = [];
options.book.log.debug.ln("convert ", images.length, "images to png");
return _.reduce(images, function(prev, image) {
var imgin = path.resolve(options.book.options.output, image.source);
return batch.execEach(images, {
max: 100,
fn: function(image) {
var imgin = path.resolve(options.book.options.output, image.source);
return prev
return Q()
// Write image if need to be download
.then(function() {
if (!image.origin) return;
options.book.log.info("download image", image.origin);
return options.book.log.info.promise(fs.writeStream(imgin, request(image.origin)));
})
// Write image if need to be download
.then(function() {
if (!image.origin && !_.contains(downloaded, image.origin)) return;
options.book.log.debug("download image", image.origin, "...");
downloaded.push(image.origin);
return options.book.log.debug.promise(fs.writeStream(imgin, request(image.origin)));
})
// Write svg if content
.then(function() {
if (!image.content) return;
return fs.writeFile(imgin, image.content);
})
// Write svg if content
.then(function() {
if (!image.content) return;
return fs.writeFile(imgin, image.content);
})
// Convert
.then(function(){
if (!image.dest) return;
var imgout = path.resolve(options.book.options.output, image.dest);
options.book.log.debug("convert image", image.source, "to", image.dest, "...");
return options.book.log.debug.promise(imgUtils.convertSVG(imgin, imgout));
});
}, Q())
// Convert
.then(function() {
if (!image.dest) return;
var imgout = path.resolve(options.book.options.output, image.dest);
options.book.log.debug("convert image", image.source, "to", image.dest, "...");
return options.book.log.debug.promise(imgUtils.convertSVG(imgin, imgout));
});
}
})
.then(function() {
options.book.log.info.ok(images.length+" images converted with success");
options.book.log.debug.ok(images.length+" images converted with success");
});
};
+11 -10
View File
@@ -1,20 +1,20 @@
{
"name": "gitbook",
"version": "2.0.0-alpha.2",
"version": "2.0.0-beta.2",
"homepage": "https://www.gitbook.com",
"description": "Library and cmd utility to generate GitBooks",
"main": "lib/index.js",
"dependencies": {
"q": "1.0.1",
"lunr": "0.5.7",
"lodash": "2.4.1",
"lodash": "3.2.0",
"graceful-fs": "3.0.5",
"resolve": "0.6.3",
"fs-extra": "0.14.0",
"fs-extra": "0.16.5",
"fstream-ignore": "1.0.2",
"gitbook-parsers": "0.3.1",
"nunjucks": "git+https://github.com/SamyPesse/nunjucks.git#4019d1b7379372336b86ce1b0bf84352a2029747",
"nunjucks-autoescape": "0.1.0",
"gitbook-parsers": "0.5.3",
"nunjucks": "git+https://github.com/mozilla/nunjucks.git#0f8b21b8df7e8e852b2e1889388653b7075f0d09",
"nunjucks-autoescape": "0.1.1",
"nunjucks-filter": "0.1.0",
"nunjucks-i18n": "1.0.0",
"semver": "2.2.1",
@@ -23,17 +23,18 @@
"gitbook-plugin-livereload": "0.0.1",
"gaze": "~0.5.1",
"send": "0.2.0",
"tiny-lr-fork": "0.0.5",
"tiny-lr": "0.1.5",
"tmp": "0.0.24",
"crc": "3.2.1",
"bash-color": "0.0.3",
"URIjs": "1.14.1",
"request": "2.51.0",
"npm": "2.4.1",
"dom-serializer": "git+https://github.com/SamyPesse/dom-serializer.git#58d8ea24b9b7b4137ee5f30a41abce4d7c4a922a"
"dom-serializer": "0.1.0",
"spawn-cmd": "0.0.2"
},
"devDependencies": {
"mocha": "1.18.2",
"mocha": "2.2.1",
"grunt": "~0.4.2",
"grunt-cli": "0.1.11",
"grunt-contrib-copy": "0.5.0",
@@ -42,7 +43,7 @@
"grunt-bower-install-simple": "0.9.2"
},
"scripts": {
"test": "export TESTING=true; mocha --reporter list --timeout 15000"
"test": "node_modules/.bin/mocha --reporter list --timeout 15000"
},
"repository": {
"type": "git",
+15 -19
View File
@@ -1,6 +1,7 @@
var path = require('path');
var _ = require('lodash');
var assert = require('assert');
var cheerio = require('cheerio');
var fs = require("fs");
var fsUtil = require("../lib/utils/fs");
@@ -15,26 +16,21 @@ describe('eBook Generator', function () {
it('should correctly convert svg images to png', function(done) {
testGeneration(books[4], "ebook", function(output) {
var readmeContent = fs.readFileSync(path.join(output, "index.html"), {encoding: "utf8"});
var pageContent = fs.readFileSync(path.join(output, "sub/PAGE.html"), {encoding: "utf8"});
// Check that all images exists
_.each([
"index.html",
"sub/PAGE.html"
], function(pageName) {
var pageFile = path.join(output, pageName);
var pageFolder = path.dirname(pageFile);
var pageContent = fs.readFileSync(pageFile, {encoding: "utf8"});
var $ = cheerio.load(pageContent);
// Remote image
assert(pageContent.indexOf('src="../Tux.png"') >= 0);
assert(fs.existsSync(path.join(output, "Tux.png")));
assert(fs.existsSync(path.join(output, "test.png")));
assert(fs.existsSync(path.join(output, "NewTux.png")));
assert(!fs.existsSync(path.join(output, "test_0.png")));
assert(!fs.existsSync(path.join(output, "sub/test.png")));
assert(!fs.existsSync(path.join(output, "sub/NewTux.png")));
assert(pageContent.indexOf('src="../test.png"') >= 0);
assert(pageContent.indexOf('src="../NewTux.png"') >= 0);
assert(pageContent.indexOf('<svg') < 0);
assert(readmeContent.indexOf('src="test.png"') >= 0);
assert(readmeContent.indexOf('src="NewTux.png"') >= 0);
$("img").each(function() {
var src = $(this).attr("src");
assert(fs.existsSync(path.resolve(pageFolder, src)), src+" not found for page "+pageName);
})
});
}, done);
});
});
+1 -1
View File
@@ -1,3 +1,3 @@
# Other Title
A description
This is a description, it's simple, no ?
+2
View File
@@ -4,3 +4,5 @@ This is a relative link [test](../intro.md).
![image](../image.png)
This is a glossary link.
+4
View File
@@ -5,3 +5,7 @@ A description
![test image to be converted](./test.svg)
![test url](http://upload.wikimedia.org/wikipedia/commons/b/b0/NewTux.svg)
![test image to be converted, second use](./test.svg)
# Test with youtube videos that have the same filename:
![youtube1](http://img.youtube.com/vi/9bZkp7q19f0/0.jpg)
![youtube2](http://img.youtube.com/vi/IkV2HQLAKHY/0.jpg)
+2 -2
View File
@@ -8,8 +8,8 @@
## Inline svg
{% html %}
<svg width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)">
<svg xmlns="http://www.w3.org/2000/svg">
<path d="M97.008198003228,6.103238498249268A97.2,97.2 0 0,1 87.9491894996971,41.385747140125076L54.289623147961166,25.546757493904366A60,60 0 0,0 59.88160370569629,3.7674311717588074Z"></path>
</svg>
{% endhtml %}
+35
View File
@@ -0,0 +1,35 @@
var path = require('path');
var _ = require('lodash');
var assert = require('assert');
var cheerio = require('cheerio');
var fs = require("fs");
var fsUtil = require("../lib/utils/fs");
describe('Glossary Generation', function () {
it('should correctly replace glossary terms', function(done) {
testGeneration(books[0], "website", function(output) {
var content = fs.readFileSync(path.join(output, "index.html"), { encoding: "utf8" });
var $ = cheerio.load(content);
var $body = $(".page-inner");
var $a = $("a[href='GLOSSARY.html#description']");
assert($a.length == 1);
assert($a.text() == "description");
}, done);
});
it('should correctly replace glossary terms in sub pages', function(done) {
testGeneration(books[1], "website", function(output) {
var content = fs.readFileSync(path.join(output, "sub/test1.html"), { encoding: "utf8" });
var $ = cheerio.load(content);
var $body = $(".page-inner");
var $a = $("a[href='../GLOSSARY.html#test']");
assert($a.length == 1);
assert($a.text() == "test");
assert($a.attr("title") == "a test text");
}, done);
});
});
+1 -1
View File
@@ -16,7 +16,7 @@ describe('JSON generator', function () {
it('should correctly generate a book to json with sub folders', function(done) {
testGeneration(books[1], "json", function(output) {
assert(!fs.existsSync(path.join(output, "README.json")));
assert(fs.existsSync(path.join(output, "README.json")));
assert(fs.existsSync(path.join(output, "intro.json")));
assert(fs.existsSync(path.join(output, "sub/test1.json")));
+7
View File
@@ -13,6 +13,13 @@ describe('Links', function () {
assert(!links.isExternal("/folder/test.md"));
});
it('should correctly test anchor links', function() {
assert(links.isAnchor("#test"));
assert(links.isAnchor(" #test"));
assert(!links.isAnchor("https://google.fr#test"));
assert(!links.isAnchor("test.md#test"));
});
describe('toAbsolute', function() {
it('should correctly transform as absolute', function() {
assert.equal(links.toAbsolute("http://google.fr"), "http://google.fr");
+2 -2
View File
@@ -71,12 +71,12 @@ describe('Book parsing', function () {
assert.equal(_.size(NAVIGATION), 2);
assert(NAVIGATION["intro.md"])
assert.equal(NAVIGATION["intro.md"].title, "Introduction");
assert.equal(NAVIGATION["intro.md"].title, "");
assert.equal(NAVIGATION["intro.md"].prev, null);
assert.equal(NAVIGATION["intro.md"].next.title, "Article 1");
assert.equal(NAVIGATION["sub/test1.md"].title, "Article 1");
assert.equal(NAVIGATION["sub/test1.md"].prev.title, "Introduction");
assert.equal(NAVIGATION["sub/test1.md"].prev.title, "");
assert.equal(NAVIGATION["sub/test1.md"].next, null);
});
});
+37
View File
@@ -0,0 +1,37 @@
var path = require('path');
var _ = require('lodash');
var assert = require('assert');
var fs = require("fs");
var pkg = require("../package.json");
describe('Templating', function () {
before(function(done) {
testGeneration(books[0], "website", function(output) {}, done);
});
var testTpl = function(str, args, options) {
return books[0].template.renderString(str, args, options)
.then(books[0].template.postProcess)
};
it('should correctly have access to generator', function(done) {
qdone(
testTpl('{{ gitbook.generator }}')
.then(function(content) {
assert.equal(content, "website");
}),
done
);
});
it('should correctly have access to gitbook version', function(done) {
qdone(
testTpl('{{ gitbook.version }}')
.then(function(content) {
assert.equal(content, pkg.version.toString());
}),
done
);
});
});
File diff suppressed because one or more lines are too long
+21
View File
@@ -0,0 +1,21 @@
{
"direction": "rtl",
"LANGS_CHOOSE": "اختيار اللغة",
"GLOSSARY": "قاموس مصطلحات",
"GLOSSARY_INDEX": "مؤشر المصطلحات",
"GLOSSARY_OPEN": "قاموس مصطلحات",
"GITBOOK_LINK": "نشرت مع GitBook",
"SUMMARY": "جدول المحتويات",
"SUMMARY_INTRODUCTION": "مقدمة",
"SUMMARY_TOGGLE": "جدول المحتويات",
"SEARCH_TOGGLE": "بحث",
"SEARCH_PLACEHOLDER": "اكتب للبحث",
"FONTSETTINGS_TOGGLE": "إعدادات الخط",
"SHARE_TOGGLE": "حصة",
"SHARE_ON": "على __platform__ حصة",
"FONTSETTINGS_WHITE": "أبيض",
"FONTSETTINGS_SEPIA": "بني داكن",
"FONTSETTINGS_NIGHT": "ليل",
"FONTSETTINGS_SANS": "بلا",
"FONTSETTINGS_SERIF": "الرقيق"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "ভাষা নির্বাচন করুন",
"GLOSSARY": "গ্লোসারি",
"GLOSSARY_INDEX": "ইন্ডেক্স",
"GLOSSARY_OPEN": "গ্লোসারি",
"GITBOOK_LINK": "গিটবুকের মাধ্যমে প্রকাশিত",
"SUMMARY": "সূচিপত্র",
"SUMMARY_INTRODUCTION": "সূচনা",
"SUMMARY_TOGGLE": "সূচিপত্র",
"SEARCH_TOGGLE": "অনুসন্ধান",
"SEARCH_PLACEHOLDER": "অনুসন্ধান",
"FONTSETTINGS_TOGGLE": "ফন্ট সেটিংস",
"SHARE_TOGGLE": "শেয়ার",
"SHARE_ON": "__platform__-এ শেয়ার",
"FONTSETTINGS_WHITE": "সাদা",
"FONTSETTINGS_SEPIA": "সেপিয়া",
"FONTSETTINGS_NIGHT": "রাত",
"FONTSETTINGS_SANS": "স্যান্স",
"FONTSETTINGS_SERIF": "শেরিফ"
}
+4 -2
View File
@@ -11,8 +11,10 @@
"SEARCH_PLACEHOLDER": "Suchbegriff eingeben",
"FONTSETTINGS_TOGGLE": "Schrifteinstellungen",
"SHARE_TOGGLE": "Teilen",
"SHARE_ON": "auf __platform__ teilen",
"SHARE_ON": "Auf __platform__ teilen",
"FONTSETTINGS_WHITE": "Hell",
"FONTSETTINGS_SEPIA": "Sepia",
"FONTSETTINGS_NIGHT": "Nacht"
"FONTSETTINGS_NIGHT": "Nacht",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "Choose a language",
"GLOSSARY": "Glossary",
"GLOSSARY_INDEX": "Index",
"GLOSSARY_OPEN": "Glossary",
"GITBOOK_LINK": "Published with GitBook",
"SUMMARY": "Table of Contents",
"SUMMARY_INTRODUCTION": "Introduction",
"SUMMARY_TOGGLE": "Table of Contents",
"SEARCH_TOGGLE": "Search",
"SEARCH_PLACEHOLDER": "Type to search",
"FONTSETTINGS_TOGGLE": "Font Settings",
"SHARE_TOGGLE": "Share",
"SHARE_ON": "Share on __platform__",
"FONTSETTINGS_WHITE": "White",
"FONTSETTINGS_SEPIA": "Sepia",
"FONTSETTINGS_NIGHT": "Night",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "Seleccione un idioma",
"GLOSSARY": "Glosario",
"GLOSSARY_INDEX": "Índice",
"GLOSSARY_OPEN": "Glosario",
"GITBOOK_LINK": "Publicado con GitBook",
"SUMMARY": "Tabla de contenido",
"SUMMARY_INTRODUCTION": "Introducción",
"SUMMARY_TOGGLE": "Tabla de contenido",
"SEARCH_TOGGLE": "Busca",
"SEARCH_PLACEHOLDER": "Escribe para buscar",
"FONTSETTINGS_TOGGLE": "Configuración de fuente",
"SHARE_TOGGLE": "Comparte",
"SHARE_ON": "Comparte en __platform__",
"FONTSETTINGS_WHITE": "Claro",
"FONTSETTINGS_SEPIA": "Sépia",
"FONTSETTINGS_NIGHT": "Noche",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+21
View File
@@ -0,0 +1,21 @@
{
"direction": "rtl",
"LANGS_CHOOSE": "انتخاب زبان",
"GLOSSARY": "واژه‌نامه",
"GLOSSARY_INDEX": "فهرست واژه‌ها",
"GLOSSARY_OPEN": "واژه‌نامه",
"GITBOOK_LINK": "انتشار یافته توسط GitBook",
"SUMMARY": "فهرست مطالب",
"SUMMARY_INTRODUCTION": "مقدمه",
"SUMMARY_TOGGLE": "فهرست مطالب",
"SEARCH_TOGGLE": "جستجو",
"SEARCH_PLACEHOLDER": "چیزی برای جستجو بنویسید",
"FONTSETTINGS_TOGGLE": "تنظیمات فونت",
"SHARE_TOGGLE": "اشتراک",
"SHARE_ON": "در __platform__ به اشتراک بگذارید",
"FONTSETTINGS_WHITE": "سفید",
"FONTSETTINGS_SEPIA": "سپیا",
"FONTSETTINGS_NIGHT": "شب",
"FONTSETTINGS_SANS": "سنس",
"FONTSETTINGS_SERIF": "سریف"
}
+3 -1
View File
@@ -14,5 +14,7 @@
"SHARE_ON": "Partager sur __platform__",
"FONTSETTINGS_WHITE": "Clair",
"FONTSETTINGS_SEPIA": "Sépia",
"FONTSETTINGS_NIGHT": "Nuit"
"FONTSETTINGS_NIGHT": "Nuit",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+3 -1
View File
@@ -14,5 +14,7 @@
"SHARE_ON": "Condividi su __platform__",
"FONTSETTINGS_WHITE": "Bianco",
"FONTSETTINGS_SEPIA": "Seppia",
"FONTSETTINGS_NIGHT": "Notte"
"FONTSETTINGS_NIGHT": "Notte",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "Velg språk",
"GLOSSARY": "Register",
"GLOSSARY_INDEX": "Indeks",
"GLOSSARY_OPEN": "Register",
"GITBOOK_LINK": "Publisert med GitBook",
"SUMMARY": "Innholdsfortegnelse",
"SUMMARY_INTRODUCTION": "Innledning",
"SUMMARY_TOGGLE": "Innholdsfortegnelse",
"SEARCH_TOGGLE": "Søk",
"SEARCH_PLACEHOLDER": "Skriv inn søkeord",
"FONTSETTINGS_TOGGLE": "Tekstinnstillinger",
"SHARE_TOGGLE": "Del",
"SHARE_ON": "Del på __platform__",
"FONTSETTINGS_WHITE": "Lys",
"FONTSETTINGS_SEPIA": "Sepia",
"FONTSETTINGS_NIGHT": "Mørk",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "Escolher sua língua",
"GLOSSARY": "Glossário",
"GLOSSARY_INDEX": "Índice",
"GLOSSARY_OPEN": "Glossário",
"GITBOOK_LINK": "Publicado com GitBook",
"SUMMARY": "Tabela de conteúdos",
"SUMMARY_INTRODUCTION": "Introdução",
"SUMMARY_TOGGLE": "Tabela de conteúdos",
"SEARCH_TOGGLE": "Pesquise",
"SEARCH_PLACEHOLDER": "Escreva para pesquisar",
"FONTSETTINGS_TOGGLE": "Configurações de fonte",
"SHARE_TOGGLE": "Compartilhar",
"SHARE_ON": "Compartilhar no __platform__",
"FONTSETTINGS_WHITE": "Claro",
"FONTSETTINGS_SEPIA": "Sépia",
"FONTSETTINGS_NIGHT": "Noite",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+3 -1
View File
@@ -14,5 +14,7 @@
"SHARE_ON": "Поделиться в __platform__",
"FONTSETTINGS_WHITE": "Светлый",
"FONTSETTINGS_SEPIA": "Сепия",
"FONTSETTINGS_NIGHT": "Тёмный"
"FONTSETTINGS_NIGHT": "Тёмный",
"FONTSETTINGS_SANS": "Sans",
"FONTSETTINGS_SERIF": "Serif"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "选择一种语言",
"GLOSSARY": "术语表",
"GLOSSARY_INDEX": "索引",
"GLOSSARY_OPEN": "术语表",
"GITBOOK_LINK": "本书使用 GitBook 发布",
"SUMMARY": "目录",
"SUMMARY_INTRODUCTION": "介绍",
"SUMMARY_TOGGLE": "目录",
"SEARCH_TOGGLE": "搜索",
"SEARCH_PLACEHOLDER": "输入并搜索",
"FONTSETTINGS_TOGGLE": "字体设置",
"SHARE_TOGGLE": "分享",
"SHARE_ON": "分享到 __platform__",
"FONTSETTINGS_WHITE": "白色",
"FONTSETTINGS_SEPIA": "棕褐色",
"FONTSETTINGS_NIGHT": "夜间",
"FONTSETTINGS_SANS": "无衬线体",
"FONTSETTINGS_SERIF": "衬线体"
}
+20
View File
@@ -0,0 +1,20 @@
{
"LANGS_CHOOSE": "選擇一種語言",
"GLOSSARY": "術語表",
"GLOSSARY_INDEX": "索引",
"GLOSSARY_OPEN": "術語表",
"GITBOOK_LINK": "本書使用 GitBook 釋出",
"SUMMARY": "目錄",
"SUMMARY_INTRODUCTION": "介紹",
"SUMMARY_TOGGLE": "目錄",
"SEARCH_TOGGLE": "搜尋",
"SEARCH_PLACEHOLDER": "輸入並搜尋",
"FONTSETTINGS_TOGGLE": "字型設定",
"SHARE_TOGGLE": "分享",
"SHARE_ON": "分享到 __platform__",
"FONTSETTINGS_WHITE": "白色",
"FONTSETTINGS_SEPIA": "棕褐色",
"FONTSETTINGS_NIGHT": "夜間",
"FONTSETTINGS_SANS": "無襯線體",
"FONTSETTINGS_SERIF": "襯線體"
}
+21 -40
View File
@@ -5,52 +5,33 @@
.page {
&.page-toc {
ol {
margin: 0px;
.glossary {
margin-bottom: 40px;
h2 {
a, a:hover {
color: inherit;
text-decoration: none;
}
}
.glossary-index {
list-style: none;
margin: 0px;
padding: 0px;
li {
display: inline;
margin: 0px 8px;
white-space: nowrap;
}
}
}
}
.book-chapter {
display: none;
}
.exercise, .quiz {
margin: 1cm 0cm;
border: 2px solid #ddd;
.exercise-header {
padding: 0.1cm 0.3cm;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
font-weight: bold;
page-break-inside: avoid;
}
.exercise-inner {
padding: 0.15cm 0.3cm;
p:last-child {
margin: 0px;
}
}
hr {
height: 2px;
}
.question {
margin-top: 0.1cm;
border-top: 1px solid #ddd;
.question-base {
}
.question-solution {
}
}
}
}
+13 -7
View File
@@ -4,12 +4,18 @@
{% block content %}
<div class="page page-toc">
<h1>Glossary</h1>
{% for item in glossaryIndex %}
<section class="normal glossary" id="{{ item.id }}">
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
<p>{{ item.description }}</p>
</section>
{% endfor %}
<h1 class="book-chapter book-chapter-1">{% i18n "GLOSSARY" %}Glossary{% endi18n %}</h1>
<h1>{% i18n "GLOSSARY" %}Glossary{% endi18n %}</h1>
{% for item in glossary %}
<section class="normal glossary" id="{{ item.id }}">
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
<p>{{ item.description|safe }}</p>
<ul class="glossary-index">
{% for file in item.files %}
<li><a href="{{ basePath }}/{{ file.path|contentLink }}"><span class="level">{{ file.level }}.</span> {{ file.title }}</a></li>
{% endfor %}
</ul>
</section>
{% endfor %}
</div>
{% endblock %}
+2 -2
View File
@@ -1,5 +1,5 @@
<!DOCTYPE HTML>
<html lang="{{ language }}" {% block htmlTag %}{% endblock %}>
<html lang="{{ language }}" {% block htmlTag %}{% endblock %} {% if options.direction == "rtl" %}dir="rtl"{% endif %}>
{{ htmlSnippet("html:start")|default("")|safe }}
<head>
{{ htmlSnippet("head:start")|default("")|safe }}
@@ -9,7 +9,7 @@
<meta name="description" content="{% block description %}{% endblock %}">
<meta name="generator" content="GitBook {{ gitbook.version }}">
{% block head %}{% endblock %}
{{ htmlSnippet("head:end")|default("") }}
{{ htmlSnippet("head:end")|default("")|safe }}
</head>
<body>
{{ htmlSnippet("body:start")|default("")|safe }}
+1 -2
View File
@@ -6,8 +6,7 @@
{% for item in glossary %}
<section class="normal glossary" id="{{ item.id }}">
<h2><a href="#{{ item.id }}">{{ item.name }}</a></h2>
<p>{{ item.description }}</p>
<h4>{% i18n "GLOSSARY_INDEX" %}Index{% endi18n %}</h4>
<p>{{ item.description|safe }}</p>
<ul class="glossary-index">
{% for file in item.files %}
<li><a href="{{ basePath }}/{{ file.path|contentLink }}"><span class="level">{{ file.level }}.</span> {{ file.title }}</a></li>
@@ -8,7 +8,7 @@
{% if item.level != "0" %}
<b>{{ item.level }}.</b>
{% endif %}
{% if item.introduction %}{% i18n "SUMMARY_INTRODUCTION" %}Introduction{% endi18n %}{% else %}{{ item.title }}{% endif %}
{% if item.introduction and not item.title %}{% i18n "SUMMARY_INTRODUCTION" %}Introduction{% endi18n %}{% else %}{{ item.title }}{% endif %}
</a>
{% else %}
<a target="_blank" href="{{ item.path }}">
@@ -38,10 +38,10 @@
<ul class="summary">
{% set _divider = false %}
{% if options.links.sidebar %}
{% for link in options.links.sidebar %}
{% for linkTitle, link in options.links.sidebar %}
{% set _divider = true %}
<li>
<a href="{{ options.links.sidebar[loop.key] }}" target="blank" class="custom-link">{{ loop.key }}</a>
<a href="{{ link }}" target="blank" class="custom-link">{{ linkTitle }}</a>
</li>
{% endfor %}
{% endif %}
+2 -2
View File
@@ -1,8 +1,8 @@
<!DOCTYPE HTML>
<html lang="{{ language }}">
<html lang="{{ language }}" {% if options.direction == "rtl" %}dir="rtl"{% endif %}>
{{ htmlSnippet("html:start")|default("")|safe }}
<head>
{{ htmlSnippet("head:start")|default("") }}
{{ htmlSnippet("head:start")|default("")|safe }}
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=11; IE=10; IE=9; IE=8; IE=7; IE=EDGE" />
<title>{% block title %}{% endblock %}</title>