chore(doc-gen): new syntax for cheatsheet items
This commit is contained in:
parent
8459a4dd5c
commit
3ede7bfea9
|
@ -1,6 +1,6 @@
|
|||
var Package = require('dgeni').Package;
|
||||
|
||||
module.exports = new Package('cheatsheet', [require('../content-package')])
|
||||
module.exports = new Package('cheatsheet', [require('../content-package'), require('../target-package')])
|
||||
|
||||
.factory(require('./services/cheatsheetItemParser'))
|
||||
.processor(require('./processors/createCheatsheetDoc'))
|
||||
|
|
|
@ -29,57 +29,92 @@
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
module.exports = function cheatsheetItemParser() {
|
||||
|
||||
module.exports = function cheatsheetItemParser(targetEnvironments) {
|
||||
return function(text) {
|
||||
var index = 0;
|
||||
var fields = getFields(text, ['syntax', 'description']);
|
||||
|
||||
var item = {
|
||||
syntax: '',
|
||||
bold: [],
|
||||
description: ''
|
||||
};
|
||||
|
||||
var STATES = {
|
||||
inSyntax: function() {
|
||||
if (text.charAt(index) !== '`') throw new Error('item syntax must start with a backtick');
|
||||
index += 1;
|
||||
var syntaxStart = index;
|
||||
while(index < text.length && text.charAt(index) !== '`') index++;
|
||||
if (index === text.length) throw new Error('item syntax must end with a backtick');
|
||||
item.syntax = text.substring(syntaxStart, index);
|
||||
state = STATES.pipe;
|
||||
index++;
|
||||
},
|
||||
pipe: function() {
|
||||
if (text.charAt(index) === '|') {
|
||||
index++;
|
||||
while(index < text.length && /\s/.test(text.charAt(index))) index++;
|
||||
state = STATES.bold;
|
||||
} else {
|
||||
state = STATES.description;
|
||||
fields.forEach(function(field) {
|
||||
if (!field.languages || targetEnvironments.someActive(field.languages)) {
|
||||
switch(field.name) {
|
||||
case 'syntax':
|
||||
parseSyntax(field.value.trim());
|
||||
break;
|
||||
case 'description':
|
||||
item.description = field.value.trim();
|
||||
break;
|
||||
}
|
||||
},
|
||||
bold: function() {
|
||||
if (text.charAt(index) !== '`') throw new Error('bold matcher must start with a backtick');
|
||||
index += 1;
|
||||
var boldStart = index;
|
||||
while(index < text.length && text.charAt(index) !== '`') index++;
|
||||
if (index === text.length) throw new Error('bold matcher must end with a backtick');
|
||||
item.bold.push(text.substring(boldStart, index));
|
||||
state = STATES.pipe;
|
||||
index++;
|
||||
},
|
||||
description: function() {
|
||||
item.description = text.substring(index);
|
||||
state = null;
|
||||
}
|
||||
};
|
||||
|
||||
var state = STATES.inSyntax;
|
||||
while(state) {
|
||||
state();
|
||||
}
|
||||
});
|
||||
|
||||
return item;
|
||||
|
||||
function parseSyntax(text) {
|
||||
var index = 0;
|
||||
|
||||
if (text.charAt(index) !== '`') throw new Error('item syntax must start with a backtick');
|
||||
|
||||
var start = index + 1;
|
||||
index = text.indexOf('`', start);
|
||||
if (index === -1) throw new Error('item syntax must end with a backtick');
|
||||
item.syntax = text.substring(start, index);
|
||||
start = index + 1;
|
||||
|
||||
// skip to next pipe
|
||||
while(index < text.length && text.charAt(index) !== '|') index += 1;
|
||||
|
||||
while(text.charAt(start) === '|') {
|
||||
|
||||
start += 1;
|
||||
|
||||
// skip whitespace
|
||||
while(start < text.length && /\s/.test(text.charAt(start))) start++;
|
||||
|
||||
if (text.charAt(start) !== '`') throw new Error('bold matcher must start with a backtick');
|
||||
|
||||
start += 1;
|
||||
index = text.indexOf('`', start);
|
||||
if (index === -1) throw new Error('bold matcher must end with a backtick');
|
||||
item.bold.push(text.substring(start, index));
|
||||
start = index + 1;
|
||||
|
||||
}
|
||||
|
||||
if (start !== text.length) {
|
||||
throw new Error('syntax field must only contain a syntax code block and zero or more bold ' +
|
||||
'matcher code blocks, delimited by pipes.\n' +
|
||||
'Instead it was "' + text + '"');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getFields(text, fieldNames) {
|
||||
var FIELD_START = /^([^:(]+)\(?([^)]+)?\)?:$/;
|
||||
var lines = text.split('\n');
|
||||
var fields = [];
|
||||
var field, line;
|
||||
while(lines.length) {
|
||||
line = lines.shift();
|
||||
var match = FIELD_START.exec(line);
|
||||
if (match && fieldNames.indexOf(match[1]) !== -1) {
|
||||
// start new field
|
||||
if (field) {fields.push(field);}
|
||||
field = { name: match[1], languages: (match[2] && match[2].split(' ')), value: ''};
|
||||
} else {
|
||||
if (!field) throw new Error('item must start with one of the following field specifiers:\n' +
|
||||
fieldNames.map(function(field) { return field + ':'; }).join('\n') + '\n' +
|
||||
'but instead it contained: "' + text + '"');
|
||||
field.value += line + '\n';
|
||||
}
|
||||
}
|
||||
if (field) {fields.push(field);}
|
||||
|
||||
return fields;
|
||||
}
|
|
@ -8,45 +8,86 @@ describe('cheatsheetItemParser', function() {
|
|||
dgeni = new Dgeni([mockPackage()]);
|
||||
injector = dgeni.configureInjector();
|
||||
cheatsheetItemParser = injector.get('cheatsheetItemParser');
|
||||
var targetEnvironments = injector.get('targetEnvironments');
|
||||
targetEnvironments.addAllowed('js');
|
||||
targetEnvironments.addAllowed('ts', true);
|
||||
});
|
||||
|
||||
it('should extract the syntax', function() {
|
||||
expect(cheatsheetItemParser('`abc`')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: [],
|
||||
description: ''
|
||||
describe('no language targets', function() {
|
||||
it('should extract the syntax', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: [],
|
||||
description: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract the bolds', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`|`bold1`|`bold2`')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract the description', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`|`bold1`|`bold2`\ndescription:\nsome description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow bold to be optional', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`\ndescription:\nsome description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: [],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow whitespace between the parts', function() {
|
||||
expect(cheatsheetItemParser('syntax:\n`abc`| `bold1`| `bold2`\ndescription:\n\nsome description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract the bolds', function() {
|
||||
expect(cheatsheetItemParser('`abc`|`bold1`|`bold2`')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: ''
|
||||
describe('with language targets', function() {
|
||||
it('should extract the active language', function() {
|
||||
expect(cheatsheetItemParser('syntax(ts):\n`abc`|`bold1`|`bold2`\ndescription(ts):\nsome description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should ignore the non-active language', function() {
|
||||
expect(cheatsheetItemParser('syntax(js):\n`abc`|`bold1`|`bold2`\ndescription(js):\nsome description')).toEqual({
|
||||
syntax: '',
|
||||
bold: [],
|
||||
description: ''
|
||||
});
|
||||
});
|
||||
|
||||
it('should select the active language and ignore non-active language', function() {
|
||||
expect(cheatsheetItemParser(
|
||||
'syntax(js):\n`JS`|`boldJS``\n' +
|
||||
'syntax(ts):\n`TS`|`boldTS`\n' +
|
||||
'description(js):\nJS description\n' +
|
||||
'description(ts):\nTS description')).toEqual({
|
||||
syntax: 'TS',
|
||||
bold: ['boldTS'],
|
||||
description: 'TS description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should error if a language target is used that is not allowed', function() {
|
||||
expect(function() {
|
||||
cheatsheetItemParser('syntax(dart):\n`abc`|`bold1`|`bold2`\ndescription(ts):\nsome description');
|
||||
}).toThrowError('Error accessing target "dart". It is not in the list of allowed targets: js,ts');
|
||||
});
|
||||
});
|
||||
|
||||
it('should extract the description', function() {
|
||||
expect(cheatsheetItemParser('`abc`|`bold1`|`bold2`some description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow bold to be optional', function() {
|
||||
expect(cheatsheetItemParser('`abc`some description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: [],
|
||||
description: 'some description'
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow whitespace between the parts', function() {
|
||||
expect(cheatsheetItemParser('`abc`| `bold1`| `bold2`\n\nsome description')).toEqual({
|
||||
syntax: 'abc',
|
||||
bold: ['bold1', 'bold2'],
|
||||
description: '\n\nsome description'
|
||||
});
|
||||
})
|
||||
});
|
Loading…
Reference in New Issue