标签:extern glob lock 一个 menu lint generator 3.1 load
  想给自已的blog添加一个相册功能、给生活中的点点滴滴留影记录。搜寻网络上给Next主题添加相册功能的基本上没有,只能重头到尾开始一点点的实践。 
   
  大致的想法: 
    1. 相册展示类似于归档一样,按时间戳来分类 
    2.每一个时间节点都是一个小相册,展示的时候上面是相册的标题,下面是几张经典图片的缩略图 
    3.点击标题,进行相册的详细页面,可以看到更多关于这个小相册的图片 
    4.相册展示的特效类似于Lawlite 
    
   
  由于Hexo基于NodeJS开发的,通过插件的方式集成一些第三方的功能。比如归档是 通过hexo-generator-archive实现的,标签页是通过hexo-generator-tag实现的。更多Hexo插件请看Hexo Plugins.这里就不过多讨论。 
   
  本次实践修改的插件有: 
    1.hexo-generator-archive 
    2.hexo-generator-index 
    2.hexo-generator-category 
    4.hexo-generator-photo[自已新增的]
  每一个小相册都是一个MD文件,每次首页和归档生成的时候都会把相册加载进去。我想让相册和博客进行区别,所以在MD文件的开头会声明一个属性isPhoto,true表示相册、false表示普通博客文章。 
  hexo-generator-archive和hexo-generator-index中去除相册的展示。 
  修改插件的\lib\generator.js文件,在exports函数,变量声明完加上如下一段代码。
    //过滤所有的文章
     function filterPhoto(posts){
        var tmp = [];
        posts.forEach(function(post) {
          var isPhoto = post.isPhoto; //相册
          if(!isPhoto){
            tmp.push(post);
          }
        });
        posts.data = tmp;
        posts.length = tmp.length;
      }
      //hexo-generator-index中调用
      filterPhoto(posts);
      //hexo-generator-archive中调用
      filterPhoto(allPosts);
  归档的时候会显示所有文章的总数(包含相册),通过下列方式去除掉。 
  在hexo-generator-archive插件的\lib\generator.js文件添加如下注释的代码:
     function generate(path, posts, options) {
        options = options || {};
        options.archive = true;
        options.postLength = allPosts.length; //新增的
  修改归档的展示页面代码(themes\next\layout\archive.swig): 
  将site.posts.length改为page.postLength即可。
  新增hexo-generator-photo插件,自动生成相册时间戳界面,参考hexo-generator-archive插件。 
   
  拷贝hexo-generator-archive的源码,主要修改以下几个文件: 
   
  1.index.js:
    /* global hexo */
    ‘use strict‘;
    var assign = require(‘object-assign‘);
    // when archive disabled pagination, per_page should be 0.
    var per_page;
    if (hexo.config.photo === 1) {
      per_page = 0;
    } else if (typeof hexo.config.per_page === ‘undefined‘) {
      per_page = 10;
    } else {
      per_page = hexo.config.per_page;
    }
    hexo.config.photo_generator = assign({
      per_page: per_page,
      yearly: true,
      monthly: true,
      daily: false
    }, hexo.config.photo_generator);
    hexo.extend.generator.register(‘photo‘, require(‘./lib/generator‘));
  2.package.json:
    {
      "name": "hexo-generator-photo",
      "version": "0.0.1",
      "description": "photo generator for Hexo.",
      "main": "index",
      "scripts": {
        "eslint": "eslint .",
        "jscs": "jscs .",
        "test": "mocha test/index.js",
        "test-cov": "istanbul cover --print both _mocha -- test/index.js"
      },
      "directories": {
        "lib": "./lib"
      },
      "repository": "hexojs/hexo-generator-photo",
      "homepage": "http://hexo.io/",
      "keywords": [
        "hexo",
        "generator",
        "photo"
      ],
      "author": "",
      "license": "",
      "devDependencies": {
        "chai": "^1.9.1",
        "eslint": "^1.10.3",
        "eslint-config-hexo": "^1.0.2",
        "hexo": "^3.1.1",
        "istanbul": "^0.4.1",
        "jscs": "^2.7.0",
        "jscs-preset-hexo": "^1.0.1",
        "mocha": "^2.0.1"
      },
      "dependencies": {
        "hexo-pagination": "0.0.2",
        "object-assign": "^2.0.0"
      }
    }
  3.generator.js:
    ‘use strict‘;
    var pagination = require(‘hexo-pagination‘);
    var fmtNum = function(num) {
      return num < 10 ? ‘0‘ + num : num;
    };
    module.exports = function(locals) {
      var config = this.config;
      var photoDir = config.photo_dir;
      var paginationDir = config.pagination_dir || ‘page‘;
      var allPosts = locals.posts.sort(‘-date‘);
      var perPage = config.photo_generator.per_page;
      var result = [];
      if (!allPosts.length) return;
      function screenPhoto(posts){
        var tmp = [];
        posts.forEach(function(post) {
          var isPhoto = post.isPhoto; //相册
          if(isPhoto){
            tmp.push(post);
          }
        });
        posts.data = tmp;
        posts.length = tmp.length;
      }
      screenPhoto(allPosts);
      if (photoDir[photoDir.length - 1] !== ‘/‘) photoDir += ‘/‘;
      function generate(path, posts, options) {
        options = options || {};
        options.photo = true;
        options.postLength = allPosts.length;
        result = result.concat(pagination(path, posts, {
          perPage: perPage,
          layout: [‘photo‘, ‘index‘],
          format: paginationDir + ‘/%d/‘,
          data: options
        }));
      }
      generate(photoDir, allPosts);
      if (!config.photo_generator.yearly) return result;
      var posts = {};
      // Organize posts by date
      allPosts.forEach(function(post) {
          var date = post.date;
          var year = date.year();
          var month = date.month() + 1; // month is started from 0
          if (!posts.hasOwnProperty(year)) {
          // 13 arrays. The first array is for posts in this year
          // and the other arrays is for posts in this month
          posts[year] = [
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            []
          ];
        }
        posts[year][0].push(post);
        posts[year][month].push(post);
        // Daily
        if (config.photo_generator.daily) {
          var day = date.date();
          if (!posts[year][month].hasOwnProperty(day)) {
            posts[year][month].day = {};
          }
          (posts[year][month].day[day] || (posts[year][month].day[day] = [])).push(post);
        }
      });
      var Query = this.model(‘Post‘).Query;
      var years = Object.keys(posts);
      var year, data, month, monthData, url;
      // Yearly
      for (var i = 0, len = years.length; i < len; i++) {
        year = +years[i];
        data = posts[year];
        url = photoDir + year + ‘/‘;
        if (!data[0].length) continue;
        generate(url, new Query(data[0]), {year: year});
        if (!config.photo_generator.monthly && !config.photo_generator.daily) continue;
        // Monthly
        for (month = 1; month <= 12; month++) {
          monthData = data[month];
          if (!monthData.length) continue;
          if (config.photo_generator.monthly) {
            generate(url + fmtNum(month) + ‘/‘, new Query(monthData), {
              year: year,
              month: month
            });
          }
          if (!config.photo_generator.daily) continue;
          // Daily
          for (var day = 1; day <= 31; day++) {
            var dayData = monthData.day[day];
            if (!dayData || !dayData.length) continue;
            generate(url + fmtNum(month) + ‘/‘ + fmtNum(day) + ‘/‘, new Query(dayData), {
              year: year,
              month: month,
              day: day
            });
          }
        }
      }
      return result;
    };
  hexo执行调用Hexo-generator-photo插件: 
  网站根目录的package.json文件中添加如下一行:
    "hexo-server": "^0.2.0",  //下面添加,不要遗漏","
    "hexo-generator-photo":"^0.0.1"
  新增相册的swig文件(themes\next\layout\photo.swig):
    {% extends ‘_layout.swig‘ %}
    {% import ‘_macro/post-collapse-photo.swig‘ as post_template %}
    {% import ‘_macro/sidebar.swig‘ as sidebar_template %}
    {% block title %}{{ __(‘title.photo‘) }} | {{ config.title }}{% endblock %}
    {% block page_class %} page-archive {% endblock %}
    {% block content %}
      <section id="posts" class="posts-collapse">
        {% for post in page.posts %}
          {# Show year #}
          {% set year %}
          {% set post.year = date(post.date, ‘YYYY‘) %}
          {% if post.year !== year %}
            {% set year = post.year %}
            <div class="collection-title">
              <h2 class="archive-year motion-element" id="archive-year-{{ year }}">{{ year }}</h2>
            </div>
          {% endif %}
          {# endshow #}
          {{ post_template.render(post) }}
        {% endfor %}
      </section>
      {% include ‘_partials/pagination.swig‘ %}
    {% endblock %}
    {% block sidebar %}
      {{ sidebar_template.render(false) }}
    {% endblock %}
    {% block script_extra %}
      {% if theme.use_motion %}
        <script type="text/javascript" id="motion.page.archive">
          $(‘.archive-year‘).velocity(‘transition.slideLeftIn‘);
        </script>
      {% endif %}
    {% endblock %}
  添加相册子标题模板(themes\next\layout\_macro\post-collapse-photo.swig):
    {% macro render(post) %}
      <article class="post post-type-{{ post.type | default(‘normal‘) }}" itemscope itemtype="http://schema.org/Article">
        <header class="post-header2">
          <{% if theme.seo %}h3{% else %}h2{% endif %} class="post-title">
            {% if post.link %}{# Link posts #}
              <a class="post-title-link post-title-link-external" target="_blank" href="{{ url_for(post.link) }}" itemprop="url">
                {{ post.title or post.link }}
                <i class="fa fa-external-link"></i>
              </a>
            {% else %}
                <a class="post-title-link" href="{{ url_for(post.path) }}" itemprop="url">
                  {% if post.type === ‘picture‘ %}
                    {{ post.content }}
                  {% else %}
                    <span itemprop="name">{{ post.title | default(__(‘post.untitled‘)) }}</span>
                  {% endif %}
                </a>
            {% endif %}
          </{% if theme.seo %}h3{% else %}h2{% endif %}>
          <div>
            <ul class="box">
              {% for photo in post.photos %}
                <figure class="thumb"><img src="{{photo}}" alt=""></figure>
              {% endfor %}
            </ul>
          </div>
          <div class="post-meta">
            <time class="post-time" itemprop="dateCreated"
                  datetime="{{ moment(post.date).format() }}"
                  content="{{ date(post.date, config.date_format) }}" >
              {{ date(post.date, ‘MM-DD‘) }}
            </time>
          </div>
        </header>
      </article>
    {% endmacro %}
  新增样式(themes\next\source\css\_custom\custom.styl):
    box{ width:100%;}
    .box li{ float:left; width:100px; height:80px; margin-right:10px; padding:0; margin:5px; overflow:hidden;list-style:none;}  
    .posts-collapse .post-header2 {
        position: relative;
        transition-duration: 0.2s;
        transition-timing-function: ease-in-out;
        transition-delay: 0s;
        transition-property: border;
    }
    .thumb{
        width: 25%;
        height: 0;
        padding-bottom: 25%;
        position: relative;
        display: inline-block;
        text-align: center;
        margin:0px;
    }
    .thumb img{
        display: inline;
        margin: auto;
        max-width: 100%;
        height: auto;
    }
   
  站点文件配置(_config.yml)新增如下配置:
    # Directory节点添加如下配置
    photo_dir: photos //添加Photo生成目录
    //Photo生成配置
    photo_generator:
      per_page: 3   //默认展示的条数
      yearly: true
      monthly: true
主题文件配置(_config.yml)新增如下配置
menu:  //menu节点添加如下一行
  photos: /photos/
menu_icons: //menu节点下添加如下一行
  photos: book
中文显示(themes\next\languages\zh-Hans.yml):
title:  //节点下添加如下一行
  photo: 相册
menu: //节点下添加如下一行
  photos: 相册
  source\_posts目录下添加相册的MD文件,内容如下:
    ---
    title: 王二狗是个大帅哥
    date: 2017-06-17 10:26:32
    comments: false
    photos: ["http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg","http://img5.duitang.com/uploads/item/201508/10/20150810153526_2ifjW.jpeg"]
    isPhoto: true
    ---
    
    
通过`Hexo server`启动服务,访问`http://localhost:4000/photos/`即可看到生成的相册界面。
  
     
  安装Hexo之后,插件默认存放在blog\node_modules目录下。 
  插件开发的核心文件:index.js,package.json,generator.js 
  关于插件开发的Demo:Plugin Demo
标签:extern glob lock 一个 menu lint generator 3.1 load
原文地址:https://www.cnblogs.com/LuisYang/p/9356488.html