Skip to content

Commit 96a3aff

Browse files
committed
feat(renderers): use a templating system with EJS (#106)
Use http://ejs.co.
1 parent 21017fc commit 96a3aff

File tree

24 files changed

+453
-354
lines changed

24 files changed

+453
-354
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-disable no-console */
2+
3+
const getTemplatePath = require('../../lib/core/getTemplatePath');
4+
5+
describe('guessTemplatePath', () => {
6+
test('guess default', () => {
7+
expect(getTemplatePath().endsWith('lib/templates/default.ejs')).toBeTruthy();
8+
expect(getTemplatePath('default').endsWith('lib/templates/default.ejs')).toBeTruthy();
9+
});
10+
11+
test('guess docstrap', () => {
12+
const templatePath = getTemplatePath('./node_modules/ink-docstrap/template');
13+
14+
expect(templatePath.endsWith('lib/templates/docstrap.ejs')).toBeTruthy();
15+
});
16+
17+
test('guess minami', () => {
18+
const templatePath = getTemplatePath('node_modules/minami');
19+
20+
expect(templatePath.endsWith('lib/templates/minami.ejs')).toBeTruthy();
21+
});
22+
23+
test('guess tui', () => {
24+
const templatePath = getTemplatePath('node_modules/tui-jsdoc-template');
25+
26+
expect(templatePath.endsWith('lib/templates/tui.ejs')).toBeTruthy();
27+
});
28+
29+
test('guess unsupported', () => {
30+
console.warn = jest.fn();
31+
32+
expect(getTemplatePath('foo-bar').endsWith('lib/templates/default.ejs')).toBeTruthy();
33+
expect(console.warn).toHaveBeenCalledWith('The template "foo-bar" is not recognized by jsdoc-vuejs. Using default template as fallback.');
34+
});
35+
});

__tests__/guessers/guessRenderer.test.js

Lines changed: 0 additions & 29 deletions
This file was deleted.

config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
const config = require('jsdoc/env');
2-
const guessRenderer = require('./lib/core/guessRenderer');
2+
const getTemplatePath = require('./lib/core/getTemplatePath');
33

44
config['jsdoc-vuejs'] = config['jsdoc-vuejs'] || {};
55

66
// Detect JSDoc template if not specified
7-
if (!Object.prototype.hasOwnProperty.call(config['jsdoc-vuejs'], 'renderer')) {
8-
config['jsdoc-vuejs'].renderer = guessRenderer(config.opts.template || 'default');
7+
if (!Object.prototype.hasOwnProperty.call(config['jsdoc-vuejs'], 'template')) {
8+
config['jsdoc-vuejs'].template = getTemplatePath(config.opts.template || 'default');
99
}
1010

1111
module.exports = config;

cypress/integration/renderers/default.spec.js renamed to cypress/integration/templates/default.spec.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable newline-per-chained-call */
22

3-
describe('Renderers: default', () => {
3+
describe('Template: default', () => {
44
before(() => {
55
cy.visit('/../../../example/docs/module-better-components_BetterCounter.html');
66
cy.screenshot();
@@ -19,14 +19,14 @@ describe('Renderers: default', () => {
1919
it('should renders props correctly', () => {
2020
const props = [
2121
{
22-
name: '<b>initialCounter</b>',
22+
name: '<code>initialCounter</code>',
2323
type: 'Number',
2424
defaultValue: '-',
2525
required: '<b>Yes</b>',
2626
description: '-',
2727
},
2828
{
29-
name: '<b>step</b>',
29+
name: '<code>step</code>',
3030
type: 'Number',
3131
defaultValue: '<code>1</code>',
3232
required: 'No',
@@ -43,7 +43,7 @@ describe('Renderers: default', () => {
4343
.contains('Name')
4444
.next().contains('Type')
4545
.next().contains('Default value')
46-
.next().contains('Required ?')
46+
.next().contains('Required?')
4747
.next().contains('Description');
4848

4949
cy
@@ -68,7 +68,7 @@ describe('Renderers: default', () => {
6868
it('should renders data correctly', () => {
6969
const data = [
7070
{
71-
name: '<b>counter</b>',
71+
name: '<code>counter</code>',
7272
type: 'Number',
7373
defaultValue: '-',
7474
description: "Current counter's value",
@@ -106,9 +106,9 @@ describe('Renderers: default', () => {
106106

107107
it('should renders computed correctly', () => {
108108
const computeds = [
109-
{ name: '<b>fooList</b>', type: 'Array.&lt;String&gt;', description: 'A list of foo' },
110-
{ name: '<b>barList</b>', type: 'Array.&lt;String&gt;', description: 'A list of bar' },
111-
{ name: '<b>message</b>', type: 'String', description: 'A message' },
109+
{ name: '<code>fooList</code>', type: 'Array.&lt;String&gt;', description: 'A list of foo' },
110+
{ name: '<code>barList</code>', type: 'Array.&lt;String&gt;', description: 'A list of bar' },
111+
{ name: '<code>message</code>', type: 'String', description: 'A message' },
112112
];
113113

114114
cy.get('[data-jsdoc-vuejs="section-computed"]').contains('Computed');

cypress/integration/renderers/docstrap.spec.js renamed to cypress/integration/templates/docstrap.spec.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable newline-per-chained-call */
22

3-
describe('Renderers: docstrap', () => {
3+
describe('Template: docstrap', () => {
44
before(() => {
55
cy.visit('/../../../example/docs-docstrap//module-better-components_BetterCounter.html');
66
cy.screenshot();
@@ -19,14 +19,14 @@ describe('Renderers: docstrap', () => {
1919
it('should renders props correctly', () => {
2020
const props = [
2121
{
22-
name: '<b>initialCounter</b>',
22+
name: '<code>initialCounter</code>',
2323
type: 'Number',
2424
defaultValue: '-',
2525
required: '<b>Yes</b>',
2626
description: '-',
2727
},
2828
{
29-
name: '<b>step</b>',
29+
name: '<code>step</code>',
3030
type: 'Number',
3131
defaultValue: '<code>1</code>',
3232
required: 'No',
@@ -43,7 +43,7 @@ describe('Renderers: docstrap', () => {
4343
.contains('Name')
4444
.next().contains('Type')
4545
.next().contains('Default value')
46-
.next().contains('Required ?')
46+
.next().contains('Required?')
4747
.next().contains('Description');
4848

4949
cy
@@ -68,7 +68,7 @@ describe('Renderers: docstrap', () => {
6868
it('should renders data correctly', () => {
6969
const data = [
7070
{
71-
name: '<b>counter</b>',
71+
name: '<code>counter</code>',
7272
type: 'Number',
7373
defaultValue: '-',
7474
description: "Current counter's value",
@@ -106,9 +106,9 @@ describe('Renderers: docstrap', () => {
106106

107107
it('should renders computed correctly', () => {
108108
const computeds = [
109-
{ name: '<b>fooList</b>', type: 'Array.&lt;String&gt;', description: 'A list of foo' },
110-
{ name: '<b>barList</b>', type: 'Array.&lt;String&gt;', description: 'A list of bar' },
111-
{ name: '<b>message</b>', type: 'String', description: 'A message' },
109+
{ name: '<code>fooList</code>', type: 'Array.&lt;String&gt;', description: 'A list of foo' },
110+
{ name: '<code>barList</code>', type: 'Array.&lt;String&gt;', description: 'A list of bar' },
111+
{ name: '<code>message</code>', type: 'String', description: 'A message' },
112112
];
113113

114114
cy.get('[data-jsdoc-vuejs="section-computed"]').contains('Computed').should('have.class', 'subsection-title');

cypress/integration/renderers/minami.spec.js renamed to cypress/integration/templates/minami.spec.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable newline-per-chained-call */
22

3-
describe('Renderers: minami', () => {
3+
describe('Template: minami', () => {
44
before(() => {
55
cy.visit('/../../../example/docs-minami/module-better-components_BetterCounter.html');
66
cy.screenshot();
@@ -19,15 +19,15 @@ describe('Renderers: minami', () => {
1919
it('should renders props correctly', () => {
2020
const props = [
2121
{
22-
name: 'initialCounter',
23-
type: 'Number',
22+
name: '<code>initialCounter</code>',
23+
type: '<code>Number</code>',
2424
defaultValue: '-',
2525
required: '<b>Yes</b>',
2626
description: '-',
2727
},
2828
{
29-
name: 'step',
30-
type: 'Number',
29+
name: '<code>step</code>',
30+
type: '<code>Number</code>',
3131
defaultValue: '<code>1</code>',
3232
required: 'No',
3333
description: 'Step',
@@ -43,7 +43,7 @@ describe('Renderers: minami', () => {
4343
.contains('Name')
4444
.next().contains('Type')
4545
.next().contains('Default value')
46-
.next().contains('Required ?')
46+
.next().contains('Required?')
4747
.next().contains('Description');
4848

4949
cy
@@ -69,8 +69,8 @@ describe('Renderers: minami', () => {
6969
it('should renders data correctly', () => {
7070
const data = [
7171
{
72-
name: 'counter',
73-
type: 'Number',
72+
name: '<code>counter</code>',
73+
type: '<code>Number</code>',
7474
defaultValue: '-',
7575
description: "Current counter's value",
7676
},
@@ -107,9 +107,9 @@ describe('Renderers: minami', () => {
107107

108108
it('should renders computed correctly', () => {
109109
const computeds = [
110-
{ name: 'fooList', type: 'Array.&lt;String&gt;', description: 'A list of foo' },
111-
{ name: 'barList', type: 'Array.&lt;String&gt;', description: 'A list of bar' },
112-
{ name: 'message', type: 'String', description: 'A message' },
110+
{ name: '<code>fooList</code>', type: '<code>Array.&lt;String&gt;</code>', description: 'A list of foo' },
111+
{ name: '<code>barList</code>', type: '<code>Array.&lt;String&gt;</code>', description: 'A list of bar' },
112+
{ name: '<code>message</code>', type: '<code>String</code>', description: 'A message' },
113113
];
114114

115115
cy.get('[data-jsdoc-vuejs="section-computed"]').contains('Computed').should('have.class', 'subsection-title');

cypress/integration/renderers/tui.spec.js renamed to cypress/integration/templates/tui.spec.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable newline-per-chained-call */
22

3-
describe('Renderers: tui', () => {
3+
describe('Template: tui', () => {
44
before(() => {
55
cy.visit('/../../../example/docs-tui/module-better-components_BetterCounter.html');
66
cy.screenshot();
@@ -23,31 +23,31 @@ describe('Renderers: tui', () => {
2323
it('should renders props correctly', () => {
2424
const props = [
2525
{
26-
name: '<b>initialCounter</b>',
27-
type: 'Number',
26+
name: '<code>initialCounter</code>',
27+
type: '<span class="param-type">Number</span>',
2828
defaultValue: '-',
2929
required: '<b>Yes</b>',
3030
description: '-',
3131
},
3232
{
33-
name: '<b>step</b>',
34-
type: 'Number',
33+
name: '<code>step</code>',
34+
type: '<span class="param-type">Number</span>',
3535
defaultValue: '<code>1</code>',
3636
required: 'No',
3737
description: 'Step',
3838
},
3939
];
4040

4141
cy.get('[data-jsdoc-vuejs="section-props"]').contains('Props').should('have.class', 'subsection-title');
42-
cy.get('[data-jsdoc-vuejs="table-props"]').as('table-props').should('have.class', 'tui-grid-table');
42+
cy.get('[data-jsdoc-vuejs="table-props"]').as('table-props').should('have.class', 'params');
4343

4444
cy
4545
.get('@table-props')
4646
.find('> thead > tr > th')
4747
.contains('Name')
4848
.next().contains('Type')
4949
.next().contains('Default value')
50-
.next().contains('Required ?')
50+
.next().contains('Required?')
5151
.next().contains('Description');
5252

5353
cy
@@ -72,15 +72,15 @@ describe('Renderers: tui', () => {
7272
it('should renders data correctly', () => {
7373
const data = [
7474
{
75-
name: '<b>counter</b>',
76-
type: 'Number',
75+
name: '<code>counter</code>',
76+
type: '<span class="param-type">Number</span>',
7777
defaultValue: '-',
7878
description: "Current counter's value",
7979
},
8080
];
8181

8282
cy.get('[data-jsdoc-vuejs="section-data"]').contains('Data').should('have.class', 'subsection-title');
83-
cy.get('[data-jsdoc-vuejs="table-data"]').as('table-data').should('have.class', 'tui-grid-table');
83+
cy.get('[data-jsdoc-vuejs="table-data"]').as('table-data').should('have.class', 'params');
8484

8585
cy
8686
.get('@table-data')
@@ -110,13 +110,13 @@ describe('Renderers: tui', () => {
110110

111111
it('should renders computed correctly', () => {
112112
const computeds = [
113-
{ name: '<b>fooList</b>', type: 'Array.&lt;String&gt;', description: 'A list of foo' },
114-
{ name: '<b>barList</b>', type: 'Array.&lt;String&gt;', description: 'A list of bar' },
115-
{ name: '<b>message</b>', type: 'String', description: 'A message' },
113+
{ name: '<code>fooList</code>', type: '<span class="param-type">Array.&lt;String&gt;</span>', description: 'A list of foo' },
114+
{ name: '<code>barList</code>', type: '<span class="param-type">Array.&lt;String&gt;</span>', description: 'A list of bar' },
115+
{ name: '<code>message</code>', type: '<span class="param-type">String</span>', description: 'A message' },
116116
];
117117

118118
cy.get('[data-jsdoc-vuejs="section-computed"]').contains('Computed').should('have.class', 'subsection-title');
119-
cy.get('[data-jsdoc-vuejs="table-computed"]').as('table-computed').should('have.class', 'tui-grid-table');
119+
cy.get('[data-jsdoc-vuejs="table-computed"]').as('table-computed').should('have.class', 'params');
120120

121121
cy
122122
.get('@table-computed')

index.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ exports.handlers = {
4040
// It can be the main doclet before `export default {}`
4141
// with at least one `@vue-*` tag
4242
if (e.doclet._isVueDoc) {
43-
const { renderer } = config['jsdoc-vuejs'];
44-
const props = e.doclet._vueProps || [];
45-
const data = e.doclet._vueData || [];
46-
const computed = e.doclet._vueComputed || [];
43+
const { template } = config['jsdoc-vuejs'];
44+
const data = {
45+
props: e.doclet._vueProps || [],
46+
data: e.doclet._vueData || [],
47+
computed: e.doclet._vueComputed || [],
48+
};
4749

48-
e.doclet.description = render(renderer, e.doclet.description || '', props, data, computed);
50+
render(template, data, (err, str) => {
51+
if (err) throw err;
52+
53+
e.doclet.description = str;
54+
});
4955

5056
// Remove meta for not rendering source for this doclet
5157
delete e.doclet.meta;

lib/core/getTemplatePath.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const { resolve } = require('path');
2+
3+
module.exports = function getTemplatePath(template) {
4+
// eslint-disable-next-line no-param-reassign
5+
template = template || 'default';
6+
7+
const path = (() => {
8+
switch (true) {
9+
case template === 'default':
10+
return `${__dirname}/../templates/default.ejs`;
11+
case /ink-docstrap\/template/.test(template):
12+
return `${__dirname}/../templates/docstrap.ejs`;
13+
case /minami/.test(template):
14+
return `${__dirname}/../templates/minami.ejs`;
15+
case /tui-jsdoc-template/.test(template):
16+
return `${__dirname}/../templates/tui.ejs`;
17+
default:
18+
// eslint-disable-next-line no-console
19+
console.warn(`The template "${template}" is not recognized by jsdoc-vuejs. Using default template as fallback.`);
20+
return `${__dirname}/../templates/default.ejs`;
21+
}
22+
})();
23+
24+
return resolve(path);
25+
};

0 commit comments

Comments
 (0)