美文网首页
jsdoc 主题模板参考

jsdoc 主题模板参考

作者: 灯光树影 | 来源:发表于2020-01-08 20:18 被阅读0次

    文件目录

    使用npm安装jsdoc后,其文件目录结构如下:

    image.png
    其中templates放置了默认的主题模板。其中default主题的文件结构如下:
    image.png
    其中,publish.js是最重要的文件,它导出一个publish函数,在cli.js中被调用
    // 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是模板文件

    publish.js解析

    publish函数参数

    function (taffyData, opts, tutorials)
    

    taffyData是包含所有doclet的taffyData,doclet是@link,@name...
    比如使用了@name,就可以使用docs[0].name获取第一个@name值

    模板

    和模板相关的模块是:

    const template = require('jsdoc/template'); // 模板定义
    const helper = require('jsdoc/util/templateHelper'); // 模板的辅助函数库
    

    生成template的语句是

    // templatePath是配置文件中的opts.template或者使用cli时的template选项的值
    // 它应该是模板文件夹`tmpl`的所在文件夹的路径`(主题文件夹的根目录)`
    view = new template.Template( path.join(templatePath, 'tmpl') );
    

    再看template.js导出类的构造函数

    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的初始化语句:

    // 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获取即可。例如:

    // conf.json
    {
      templates: {
        selfProp: 'selfValue'
      }
    }
    
    // publish.js
    conf = env.conf.templates || {};
    conf.selfProp = conf.selfProp; // get selfProp
    

    template.js导出类的方法如下:

    • load(file: string) // 解析模板
    • partial(file: string, data: any) // 引用另一模板文件,data是载入模板的数据
    • render(file: string, data: any) // 渲染模板
      重点看render代码:
    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相关待续

    相关文章

      网友评论

          本文标题:jsdoc 主题模板参考

          本文链接:https://www.haomeiwen.com/subject/kvysactx.html