jsdoc 主題模板參考

文件目錄

使用npm安裝jsdoc後,其文件目錄結構以下:
image.png
其中templates放置了默認的主題模板。其中default主題的文件結構以下:
image.png
其中,publish.js是最重要的文件,它導出一個publish函數,在cli.js中被調用html

// cli.js
publishPromise = template.publish(
    // 保存全部數據的Taffy對象,見下面
    taffy(props.docs), 
    // env是一個保存運行環境信息的對象
    // 參考:lib/jsdoc/env.js
    env.opts,
    // 暫時未
    resolver.root
);

// publish.js
// 這裏的publish就是上面的template.publish
exports.publish = function (taffyData, opts, tutorials) {
  // ...
}

參考:taffydb
而static文件夾放置靜態文件,它會被原封不動地複製到生成的文件夾中,tmpl是模板文件npm

publish.js解析

publish函數參數

function (taffyData, opts, tutorials)

taffyData是包含全部doclet對象的taffy對象,參考doclet.js,
多數和@description,@example等對應。name指代當前@kind的名字json

模板

和模板相關的模塊是:函數

const template = require('jsdoc/template'); // 模板定義
const helper = require('jsdoc/util/templateHelper'); // 模板的輔助函數庫

生成template的語句是ui

// templatePath是配置文件中的opts.template或者使用cli時的template選項的值
// 它應該是模板文件夾`tmpl`的所在文件夾的路徑`(主題文件夾的根目錄)`
view = new template.Template( path.join(templatePath, 'tmpl') );

再看template.js導出類的構造函數this

constructor(filepath) {
    // 模板文件所在路徑
    this.path = filepath;
    // layout的文件名
    this.layout = null;
    // 代表使用的模板語法
    this.settings = {
        evaluate: /<\?js([\s\S]+?)\?>/g,
        interpolate: /<\?js=([\s\S]+?)\?>/g,
        escape: /<\?js~([\s\S]+?)\?>/g
    };
}

layout的初始化語句:lua

// env.conf是配置文件導出的對象
conf = env.conf.templates || {};
conf.default = conf.default || {};

// ....

// 設置layout的路徑
view.layout = conf.default.layoutFile ?
        path.getResourcePath(path.dirname(conf.default.layoutFile),
            path.basename(conf.default.layoutFile) ) :
        'layout.tmpl';

因此,若是要自定義模板(假設爲selfTheme,如下都以其爲例)的配置項,只須要使用env.conf.templates獲取便可。例如:url

// conf.json
{
  templates: {
    selfProp: 'selfValue'
  }
}

// publish.js
conf = env.conf.templates || {};
conf.selfProp = conf.selfProp; // get selfProp

template.js導出類的方法以下:spa

  • load(file: string) // 解析模板
  • partial(file: string, data: any) // 引用另外一模板文件,data是載入模板的數據
  • render(file: string, data: any) // 渲染模板

重點看render代碼:code

render(file, data) {
    // 渲染當前模板文件
    let content = this.partial(file, data);

    if (this.layout) {
        // 將當前內容賦值給data.content,傳遞給layout模板
        data.content = content;
        content = this.partial(this.layout, data);
    }

    return content;
}

所以,在layout.tmpl文件中,有content變量表示當前頁內容

<?js= content ?>

固然,同時具備data包含的其它屬性變量
在publish.js中,直接使用render函數的有兩處。

// function generate(title, docs, filename, resolveLinks)
docData = {
    env: env,
    title: title, // 標題
    docs: docs // 見下面docs
};
html = view.render('container.tmpl', docData);

// function generateTutorial(title, tutorial, filename)
const tutorialData = {
    title: title,
    header: tutorial.title,
    content: tutorial.parse(),
    children: tutorial.children
};
const tutorialPath = path.join(outdir, filename);
let html = view.render('tutorial.tmpl', tutorialData);

因此,要修改各頁面的標題,只須要將調用這兩個函數的title函數換掉,好比:

generate('Global', [{kind: 'globalobj'}], globalUrl)
// 改爲
generate('MyGlobal', [{kind: 'globalobj'}], globalUrl)

不太重點仍是添加模板變量和方法

// 添加變量,只須要改變render調用時的data,好比如下改變container.tmpl的變量
docData = {
    env: env,
    title: title, // 標題
    docs: docs,
    myVar: 'myVar'
};
html = view.render('container.tmpl', docData);

// 添加方法
view.find = find;
view.linkto = linkto;
view.resolveAuthorLinks = resolveAuthorLinks;
view.tutoriallink = tutoriallink;
view.htmlsafe = htmlsafe;
view.outputSourceFiles = outputSourceFiles;
view.nav = buildNav(members);

// 在模板中可使用`this.method`來調用,由於模板的this指向view
// 好比
// <?js this.find()  ?>

添加到view中的方法/屬性:

  • find(spec)

經過find({kind: 'class'})來獲取全部class,也能夠添加其它doclet:find({kind, 'class', memberOf: 'Class1' })

  • linkTo(longname, linkText)

渲染一個跳轉到longname
)即namepath所指代的url的連接(a標籤),文本是linkText
resolveAuthorLinks
渲染形如Jane Doe <jdoe@example.org> 的文本爲<a href="mailto:jdoe@example.org">Jane Doe</a>

  • htmlsafe(str) 轉義html文本
  • outputSourceFiles 是否導出源文件的標誌
  • nav 導航欄標籤

docs

docs是一個包含數據的Taffy對象,它的來源是:

data = taffyData
// 獲取各部分的數據taffy對象
members = helper.getMembers(data)
classes = taffy(members.classes);
modules = taffy(members.modules);
namespaces = taffy(members.namespaces);
mixins = taffy(members.mixins);
externals = taffy(members.externals);
interfaces = taffy(members.interfaces);

// 獲取對應longname的docs
const myClasses = helper.find(classes, {longname: longname});
const myExternals = helper.find(externals, {longname: longname});
const myInterfaces = helper.find(interfaces, {longname: longname});
const myMixins = helper.find(mixins, {longname: longname});
const myModules = helper.find(modules, {longname: longname});
const myNamespaces = helper.find(namespaces, {longname: longname});

// myClasses等就是傳入模板文件的docs變量

if (myModules.length) {
    generate(`Module: ${myModules[0].name}`, myModules, helper.longnameToUrl[longname]);
}

if (myClasses.length) {
    generate(`Class: ${myClasses[0].name}`, myClasses, helper.longnameToUrl[longname]);
}

if (myNamespaces.length) {
    generate(`Namespace: ${myNamespaces[0].name}`, myNamespaces, helper.longnameToUrl[longname]);
}

if (myMixins.length) {
    generate(`Mixin: ${myMixins[0].name}`, myMixins, helper.longnameToUrl[longname]);
}

if (myExternals.length) {
    generate(`External: ${myExternals[0].name}`, myExternals, helper.longnameToUrl[longname]);
}

if (myInterfaces.length) {
    generate(`Interface: ${myInterfaces[0].name}`, myInterfaces, helper.longnameToUrl[longname]);
}

在模板中則用this.find({kind: 'class'})代替(view.find)
docs的元素內容是:

// 參考doclet.js
{
  comment: ''
  name: '',,
  kind: '',
  // ...
}

特別的:

// source
{
  kind: 'source',
  code: ''
}

// main page
{
  kind: 'mainpage',
  readme: opts.readme,
  longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'
}

// global
{
  kind: 'globalobj'
}
tutorials相關待續
相關文章
相關標籤/搜索