Skip to content

Commit 82241a3

Browse files
authored
Merge pull request #38 from gdolle/plugin-ace-support
Plugin ace support
2 parents 337f46f + 9b17db3 commit 82241a3

File tree

33 files changed

+324
-39
lines changed

33 files changed

+324
-39
lines changed

README.md

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,66 @@ gitbook install
2222

2323
## Options
2424

25-
You can put your template into `book.js`(`book.json`) by `template` option.
25+
Several options can be set in `book.json` to customize the plugin.
26+
27+
| option | value | Description |
28+
| --- | --- | --- |
29+
| `template` | `{default,full,ace,...}` or custom path | reindent code if marker or slice is used |
30+
| `unindent` | `{true,false}` | reindent code if marker or slice is used |
31+
| `edit` | `{true,false}` | [allow edit code](https://github.com/ymcatar/gitbook-plugin-ace/blob/master/README.md) (**ace template required**) |
32+
| `check` | `{true,false}` | [syntax validation](https://github.com/ymcatar/gitbook-plugin-ace/blob/master/README.md) (**ace template required**) |
33+
| `theme` | `{monokai,coffee,...}` | [check syntax](https://github.com/ymcatar/gitbook-plugin-ace/blob/master/README.md) (**ace template required**) |
34+
| `fixlang` | {true,false} | fix some errors with code lang (e.g C++, ...) |
35+
36+
Just add the desired optin under `pluginConfig` in the `book.json` file
2637

2738
```js
28-
const fs = require("fs");
29-
module.exports = {
39+
{
3040
"gitbook": "3.x.x",
31-
"title": "gitbook-plugin-include-codeblock example",
32-
"plugins": [
33-
"include-codeblock"
34-
],
3541
"pluginsConfig": {
3642
"include-codeblock": {
37-
"template": fs.readFileSync(__dirname + "/user-template.hbs", "utf-8")
43+
"template": "ace",
44+
"unindent": "true",
45+
"theme": "monokai"
3846
}
3947
}
40-
};
48+
}
4149
```
4250

43-
See [template/](template/) and [example/](example/) for details.
51+
### Templates
4452

45-
You can also unindent the included text by specifying the `unindent` option:
53+
Templates let customize the rendered code. Several default templates are available
4654

55+
| template | description |
56+
| --- | --- |
57+
| `default` | default template, standard markdown code style |
58+
| `full` | enable title, labeling, id, ... |
59+
| `ace` | enable ace code rendering |
60+
| `acefull` | enable ace code rendering with title, label, id, ... |
61+
62+
For more template, consult the list in [template/](templates/).
63+
64+
Custom templates can be created to render the code by specifying a custom path
65+
to the template file.
4766
```js
48-
"pluginsConfig": {
49-
"include-codeblock": {
50-
"unindent": true
67+
{
68+
"gitbook": "3.x.x",
69+
"pluginsConfig": {
70+
"include-codeblock": {
71+
"template": __dirname + "/" + "path/to/custom.hbs",
72+
}
5173
}
5274
}
5375
```
76+
See [template/](templates/) and [example/](example/) for details.
77+
78+
Any contribution is welcome. Propose your new templates via pull-requests.
5479

55-
Alternatively, unindent can be specified on a per-tag basis (see below)
80+
### Ace plugin
81+
82+
It is possible to use the gitbook ace plugin to have code numbering or custom themes
83+
(See [gitbook-ace-plugin](https://github.com/ymcatar/gitbook-plugin-ace) for more details).
84+
To use ace within include-codeblock, an "ace" template is required.
5685

5786
## Usage
5887

@@ -74,9 +103,27 @@ or
74103
```
75104
Result
76105

77-
``` js
78-
console.log("test");
79-
```
106+
``` js
107+
console.log("test");
108+
```
109+
110+
### Local options
111+
112+
Option can be passed locally and may depend on the template your are using.
113+
114+
| option | value | Description |
115+
| --- | --- | --- |
116+
| `unindent` | `{"true","false"}` | reindent code if marker or slice is used |
117+
| `title`| `"<your title>"` | Title for the code **full template required**|
118+
| `filename` | `"<your_filename>"` | name of the included file **full template required** |
119+
| `originalPath` | `"</path/to/file/>"` | name of the included file **full template required** |
120+
| `id` | `"<your_id>"` | hmlt class for custom style **full template required** |
121+
| `label` | `"<your_ref_label>"` | reference label (latex like) **full template required** |
122+
| `edit` | `{"true","false"}` | allow edit code (**ace template required**) |
123+
| `check` | `{"true","false"}` | check syntax (**ace template required**) |
124+
| `theme` | `{"monokai","coffee",...}` | check syntax (**ace template required**) |
125+
126+
For more details see sections below.
80127

81128
<!--
82129
### Title(from v)
@@ -127,6 +174,7 @@ e.g.) typescript's aceMode value is `typescript`.
127174

128175
- https://github.com/blakeembrey/language-map/blob/b72edb8c2cb1b05d098782aa85dd2f573ed96ba3/languages.json#L4140
129176

177+
130178
### Sliced Code
131179

132180
If you want to slice imported code and show.

example/book.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module.exports = {
77
],
88
"pluginsConfig": {
99
"include-codeblock": {
10-
"template": fs.readFileSync(__dirname + "/user-template.hbs", "utf-8")
10+
"template": __dirname + "/user-template.hbs"
1111
}
1212
}
13-
};
13+
};

package.json

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"main": "lib/include-codeblock.js",
1717
"files": [
1818
"lib",
19-
"template",
19+
"templates",
2020
"src"
2121
],
2222
"directories": {
@@ -43,12 +43,38 @@
4343
"type": "string",
4444
"description": "Template string",
4545
"required": false
46+
},
47+
"unindent": {
48+
"type": "string",
49+
"description": "undindent inner snippets",
50+
"required": false
51+
},
52+
"edit": {
53+
"type": "string",
54+
"description": "ace code edition (ace* template required)",
55+
"required": false
56+
},
57+
"check": {
58+
"type": "string",
59+
"description": "ace syntax validation (ace* template required)",
60+
"required": false
61+
},
62+
"theme": {
63+
"type": "string",
64+
"description": "ace code editor theme (ace* template required)",
65+
"required": false
66+
},
67+
"fixlang": {
68+
"type": "Fix lang label (c++,...)",
69+
"description": "",
70+
"required": false
4671
}
4772
}
4873
},
4974
"dependencies": {
5075
"language-map": "^1.1.1",
51-
"handlebars": "^4.0.5"
76+
"handlebars": "^4.0.5",
77+
"ace": "^0.3.2"
5278
},
5379
"devDependencies": {
5480
"babel-cli": "^6.7.7",

src/language-detection.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function languageAceModeFix(resultAceMode) {
1313
return resultAceMode;
1414
}
1515

16-
export function lookupLanguageByAceMode(commands) {
16+
export function lookupLanguageByAceMode(commands, fixlang=false) {
1717
let resultAceMode;
1818
commands.forEach(command => {
1919
const matchAceModes = /lang\-(.+)/g.exec(command);
@@ -34,12 +34,14 @@ export function lookupLanguageByAceMode(commands) {
3434
if (resultAceMode === undefined) {
3535
resultAceMode = matchLang;
3636
}
37-
resultAceMode = languageAceModeFix(resultAceMode);
3837
});
38+
if(fixlang) {
39+
resultAceMode = languageAceModeFix(resultAceMode);
40+
}
3941
return resultAceMode;
4042
}
4143

42-
export function lookupLanguageByExtension(ext) {
44+
export function lookupLanguageByExtension(ext, fixlang=false) {
4345
let aceMode;
4446
Object.keys(language_map).some(langKey => {
4547
const extensions = language_map[langKey]["extensions"];
@@ -57,15 +59,17 @@ export function lookupLanguageByExtension(ext) {
5759
}
5860
});
5961
});
60-
aceMode = languageAceModeFix(aceMode);
62+
if(fixlang) {
63+
aceMode = languageAceModeFix(aceMode);
64+
}
6165
return aceMode;
6266
}
6367

64-
export function getLang(commands, filePath) {
68+
export function getLang(commands, filePath, fixlang=false ) {
6569
const lang = lookupLanguageByAceMode(commands);
6670
if (lang) {
6771
return lang;
6872
}
6973
const ext = path.extname(filePath);
70-
return lookupLanguageByExtension(ext) || ext;
74+
return lookupLanguageByExtension(ext, fixlang) || ext;
7175
}

src/parser.js

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,18 @@ export function parseVariablesFromLabel(label) {
6060
"class": undefined,
6161
"name": undefined,
6262
"marker": undefined,
63-
"unindent": undefined
63+
"unindent": undefined,
64+
"edit": undefined,
65+
"theme": undefined,
66+
"check": undefined,
67+
"fixlang": undefined
6468
};
6569
Object.keys(keyvals).forEach(key => {
6670
var keyReg = key;
6771
if (key === "marker") {
6872
keyReg = "import|include";
6973
}
74+
7075
const regStr = "\^.*,?\\s*(" + keyReg + ")\\s*:\\s*[\"']([^'\"]*)[\"'],?.*\$";
7176
const reg = new RegExp(regStr);
7277
const res = label.match(reg);
@@ -90,6 +95,7 @@ export function embedCode({lang, filePath, originalPath, label, template, uninde
9095
const code = fs.readFileSync(filePath, "utf-8");
9196
const fileName = path.basename(filePath);
9297
const keyValueObject = parseVariablesFromLabel(label);
98+
9399
var content = code;
94100
// Slice content via line numbers.
95101
if (hasSliceRange(label)) {
@@ -102,15 +108,15 @@ export function embedCode({lang, filePath, originalPath, label, template, uninde
102108
content = removeMarkers(markerSliceCode(code, marker));
103109
}
104110
if (unindent || keyValueObject.unindent) {
105-
content = strip(content)
111+
content = strip(content);
106112
}
107113
return generateEmbedCode({
108114
keyValueObject,
109115
lang,
110116
fileName,
111117
originalPath,
112118
content,
113-
template
119+
template,
114120
});
115121
}
116122

@@ -137,7 +143,7 @@ export function generateEmbedCode({
137143
fileName,
138144
originalPath,
139145
content,
140-
template
146+
template,
141147
}) {
142148
const count = hasTitle(keyValueObject) ? codeCounter() : -1;
143149
// merge objects
@@ -150,11 +156,19 @@ export function generateEmbedCode({
150156
return handlebars(context);
151157
}
152158

159+
const templatePath = {
160+
default: path.join(__dirname, "..", "templates", "default-template.hbs"),
161+
full: path.join(__dirname, "..", "templates", "full-template.hbs"),
162+
ace: path.join(__dirname, "..", "templates", "ace-template.hbs"),
163+
acefull: path.join(__dirname, "..", "templates", "acefull-template.hbs")
164+
};
153165

154166
const defaultOptions = {
155-
template: fs.readFileSync(path.join(__dirname, "..", "template", "default-template.hbs"), "utf-8"),
156-
unindent: false
167+
template: "default",
168+
unindent: false,
169+
fixlang: false
157170
};
171+
158172
/**
159173
* generate code with options
160174
* @param {string} content
@@ -164,14 +178,31 @@ const defaultOptions = {
164178
*/
165179
export function parse(content, baseDir, options = {}) {
166180
const results = [];
167-
const template = options.template || defaultOptions.template;
181+
const isTemplateDefault = (options.template == undefined);
182+
const isTemplatePath = (templatePath[options.template] == undefined);
183+
let tPath;
184+
// No template option.
185+
if(isTemplateDefault) {
186+
tPath = templatePath[defaultOptions.template];
187+
}
188+
// Template option is a path.
189+
else if (isTemplatePath && fs.existsSync(options.template)) {
190+
tPath = options.template;
191+
}
192+
// Template option one of template/ directory.
193+
else {
194+
tPath = templatePath[options.template] || templatePath[defaultOptions.template];
195+
}
196+
const template = fs.readFileSync( tPath, "utf-8");
168197
const unindent = options.unindent || defaultOptions.unindent;
198+
const fixlang = (options.fixlang != undefined) ? options.fixlang : defaultOptions.fixlang;
199+
169200
let res;
170201
while (res = markdownLinkFormatRegExp.exec(content)) {
171202
const [all, label, originalPath] = res;
172203
const commands = splitLabelToCommands(label);
173204
if (containIncludeCommand(commands)) {
174-
const lang = getLang(commands, originalPath);
205+
const lang = getLang(commands, originalPath, fixlang );
175206
const absolutePath = path.resolve(baseDir, originalPath);
176207
const replacedContent = embedCode({
177208
lang,
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
- `{{id}}`: if label contain `id:` like this `[import, id:<value>]`
1818
- `{{class}}`: if label contain `class:` like this `[import, class:<value>]`
1919

20+
### ace plugin specific
21+
22+
- {{edit}} : allow code edition
23+
- {{check}} : allow syntax validation
24+
- {{theme}} : label for the theme
25+
2026
## Limitation
2127

2228
You should write with no space(indent).
@@ -68,4 +74,4 @@ to be
6874

6975
``` rust
7076
extern crate num;
71-
```
77+
```

templates/ace-template.hbs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{% if file.type=="asciidoc" %}++++{% endif %}
2+
{%ace edit="{{edit}}", check="{{check}}", theme="{{theme}}", lang="{{lang}}" %}
3+
{{{content}}}
4+
{%endace%}
5+
{% if file.type=="asciidoc" %}++++{% endif %}

templates/acefull-template.hbs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{#if title}}
2+
{{#if id}}
3+
{% if file.type=="asciidoc" %}
4+
> [[{{id}}]]link:{{originalPath}}[{{title}}]
5+
{% else %}
6+
> <a id="{{id}}" href="{{originalPath}}">{{title}}</a>
7+
{% endif %}
8+
{{else}}
9+
{% if file.type=="asciidoc" %}
10+
> [[{{title}}]]link:{{originalPath}}[{{title}}]
11+
{% else %}
12+
> <a id="{{title}}" href="{{originalPath}}">{{title}}</a>
13+
{% endif %}
14+
{{/if}}
15+
{{else}}
16+
{% if file.type=="asciidoc" %}
17+
> [[{{fileName}}]]link:{{originalPath}}[{{fileName}}]
18+
{% else %}
19+
> <a id="{{fileName}}" href="{{originalPath}}">{{fileName}}</a>
20+
{% endif %}
21+
{{/if}}
22+
23+
{% if file.type=="asciidoc" %}++++{% endif %}
24+
{%ace edit="{{edit}}", check="{{check}}", theme="{{theme}}", lang="{{lang}}" %}
25+
{{{content}}}
26+
{%endace%}
27+
{% if file.type=="asciidoc" %}++++{% endif %}

0 commit comments

Comments
 (0)