gitbook-plugin-tags-categories

1.0.28 • Public • Published

如何製作文章標籤與分類

簡介

可以在文章最後呈現分類&標籤

專案架構

20240724_gitbook-plugin-tags-categories
├─ .npmignore
├─ assets
│  └─ plugin.css
├─ CHANGELOG.md
├─ custom-release-notes-generator.js
├─ index.js
├─ LICENSE
├─ package-lock.json
├─ package.json
└─ README.md

目錄

一、事前準備

請先到github Fork這個專案到自己的本機目錄修改

https://github.com/billryan/gitbook-plugin-tags

二、操作步驟

STEP1:請先撰寫.gitlab-ci.yml

.gitlab-ci.yml
stages:
  - semantic-release
  - npm-deploy
# Change log 版號變更
semantic-release:
  stage: semantic-release
  image: node:latest
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc
    - npm install semver
    - npm install -g --save-dev conventional-changelog-conventionalcommits semantic-release @semantic-release/changelog @semantic-release/gitlab @semantic-release/git @semantic-release/npm @semantic-release/release-notes-generator @semantic-release/gitlab-config
    - export GL_TOKEN=${GL_TOKEN}
    - GL_TOKEN=${GL_TOKEN} npx semantic-release
  tags:
    - docker
npm-deploy:
  stage: npm-deploy
  script:
    - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc
    - npm publish
  needs:
    - semantic-release

STEP2:請先撰寫index.js

index.js
var slug = require('github-slugid');
var eol = require('os').EOL;

var tags_map = {};
var categories_map = {};

module.exports = {
  book: {
    assets: './assets',
    css: [
      "plugin.css"
    ]
  },
  hooks: {
    'page:before': function(page) {
      if (this.output.name !== 'website') return page;

      // Generate tags.html page
      if (page.path === 'tags.md') {
        return generateTagsPage(tags_map, categories_map);
      }

      // Process tags and categories in the page content
      page.content = processTagsAndCategories(page.content, page);

      return page;
    },

    'page': function(page) {
      // Add end slogan to the page content only once
      if (!page.content.includes('end-slogan')) {
        return addEndSlogan(page);
      }

      return page;
    }
  }
};

// 生成標籤頁
function generateTagsPage(tags_map, categories_map) {
  let tagsContent = '<div class="tags-page">';
  
  tagsContent += '<h1>我的筆記標籤</h1>';
  for (let key in tags_map) {
    if (tags_map.hasOwnProperty(key)) {
      let tagHeader = `<h2 id="${slug(key)}">${key}</h2>`;
      tagsContent += tagHeader;
      tagsContent += '<ul>';
      tags_map[key].forEach(function(tag) {
        let tagBody = `<li><a href="${tag.url}">${tag.title}</a></li>`;
        tagsContent += tagBody;
      });
      tagsContent += '</ul>';
    }
  }

  tagsContent += '<h1>我的筆記分類</h1>';
  for (let key in categories_map) {
    if (categories_map.hasOwnProperty(key)) {
      let categoryHeader = `<h2 id="${slug(key)}">${key}</h2>`;
      tagsContent += categoryHeader;
      tagsContent += '<ul>';
      categories_map[key].forEach(function(category) {
        let categoryBody = `<li><a href="${category.url}">${category.title}</a></li>`;
        tagsContent += categoryBody;
      });
      tagsContent += '</ul>';
    }
  }

  tagsContent += '</div>';
  return { content: tagsContent };
}

// 處理標籤和分類
function processTagsAndCategories(content, page) {
  let hasTitle = false;

  return content.replace(/(tags|categories):\s*(.+)/gi, function(match, type, values) {
    if (!hasTitle) {
      hasTitle = true;
      // 添加標題
      return `<div style="text-align: center;">
                <h2>本文標籤與分類</h2>
                ${processTagsOrCategories(type, values, page)}
              </div>`;
    } else {
      // 處理其餘標籤或分類
      return processTagsOrCategories(type, values, page);
    }
  });
}


// 處理標籤和分類
function processTagsAndCategories(content, page) {
  let hasTitle = false;

  // 使用一個替換函數來處理標題的顯示
  return content.replace(/(tags|categories):\s*(.+)/gi, function(match, type, values) {
    if (!hasTitle) {
      hasTitle = true;
      // 添加標題和處理標籤或分類
      return `<div style="text-align: center;">
                <h3>彥的文章標籤與分類</h3>
                ${generateTagsOrCategoriesHTML(type, values, page)}
              </div>`;
    } else {
      // 只處理後續標籤或分類
      return generateTagsOrCategoriesHTML(type, values, page);
    }
  });
}

// 生成標籤或分類的 HTML
function generateTagsOrCategoriesHTML(type, values, page) {
  const itemList = values.split(',').map(item => item.trim());

  // 生成 HTML
  const html = itemList.map(item => 
    `<a class="${type}" href="../tags.html#${slug(item)}" style="margin: 0 10px;">
      <i class="fa ${type === 'tags' ? 'fa-tags' : 'fa-folder-open'}" aria-hidden="true"></i>${item}
    </a>`
  ).join('');

  // 更新 tags_map 或 categories_map
  itemList.forEach(function(item) {
    const map = (type.toLowerCase() === 'tags') ? tags_map : categories_map; // 確保大小寫不影響
    if (!map[item]) {
      map[item] = [];
    }
    map[item].push({
      url: page.path,
      title: page.title
    });
  });

  // 返回處理過的 HTML
  return `<div style="text-align: center;"><div class="${type}-list clearfix">${html}</div></div>`;
}

// 添加結尾標語到頁面內容
function addEndSlogan(page) {
  const endSlogan = '<div class="end-slogan" style="text-align:center;font-size:13px;letter-spacing:5px;user-select:none;color:#bbb;"><br>------------本文结束啦<i class="fa fa-star"></i>感谢您的閱讀------------<br><br></div>';
  // const separator = '<hr>';

  page.content += endSlogan;
  return page;
}

STEP3:請先撰寫assets\plugin.css

assets\plugin.css
.tags-page {
  padding: 20px;
}

.tags-page h1 {
  font-size: 28px;
  margin-bottom: 20px;
  border-bottom: 2px solid #eaeaea;
}

.tags-page h2 {
  margin-top: 30px;
  font-size: 24px;
  border-bottom: 1px solid #eaeaea;
  padding-bottom: 10px;
}

.tags-page ul {
  list-style: none;
  padding: 0;
}

.tags-page ul li {
  margin: 5px 0;
}

.tags-page ul li a {
  text-decoration: none;
  color: #3498db;
}

.tags-page ul li a:hover {
  text-decoration: underline;
}

.tags-list,
.categories-list {
  margin: 20px 0; /* 增加前后间距 */
}

.tags-list a,
.categories-list a {
  display: inline-block;
  padding: 5px 10px;
  margin: 5px;
  background-color: #f1f1f1;
  color: #333;
  text-decoration: none;
  border-radius: 3px;
}

.tags-list a:hover,
.categories-list a:hover {
  background-color: #3498db;
  color: white;
}

.fa-tags,
.fa-folder-open {
  margin-right: 10px; /* 增加图标和文字间距 */
}

STEP4:請先撰寫package.json

📝小提示:

1. name的名稱一定要改
2. version可以不用改,交給語意化版本處理,會自動跳號
3. repository、bugs、homepage請對應到該專案的gitlab
4. npmPublish要設為true,且message一定要設定,不然不會自動跳號

package.json
{
    "name": "gitbook-plugin-tags-categories",
    "version": "1.0.14",
    "description": "Gitbook tags-categories for markhsu",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "semantic-release": "semantic-release"
    },
    "repository": {
        "type": "git",
        "url": "git+https://markweb.idv.tw:10443/gitbooknpmproject/gitbook-plugin-tags-categories.git"
    },
    "author": "小彥",
    "license": "ISC",
    "bugs": {
        "url": "https://markweb.idv.tw:10443/gitbooknpmproject/gitbook-plugin-tags-categories/-/issues"
    },
    "homepage": "https://markweb.idv.tw:10443/gitbooknpmproject/gitbook-plugin-tags-categories/-/blob/master/README.md",
    "dependencies": {
        "semver": "^7.6.3"
    },
    "engines": {
        "gitbook": ">=3.0.0"
    },
    "release": {
        "extends": "@semantic-release/gitlab-config",
        "analyzeCommits": {
            "preset": "angular",
            "releaseRules": [
                {
                    "type": "feat",
                    "release": "minor"
                },
                {
                    "type": "fix",
                    "release": "patch"
                },
                {
                    "type": "docs",
                    "release": "patch"
                },
                {
                    "type": "style",
                    "release": "patch"
                },
                {
                    "type": "chore",
                    "release": "patch"
                },
                {
                    "type": "refactor",
                    "release": "patch"
                },
                {
                    "type": "test",
                    "release": "patch"
                },
                {
                    "type": "build",
                    "release": "patch"
                },
                {
                    "type": "ci",
                    "release": "patch"
                }
            ]
        },
        "plugins": [
            [
                "@semantic-release/commit-analyzer",
                {
                    "path": "./custom-release-notes-generator.js"
                }
            ],
            [
                "@semantic-release/release-notes-generator",
                {
                    "preset": "conventionalcommits",
                    "presetConfig": {
                        "types": [
                            {
                                "type": "feat",
                                "section": "✨ 新增功能"
                            },
                            {
                                "type": "fix",
                                "section": "🐞 錯誤修正"
                            },
                            {
                                "type": "perf",
                                "section": "🚀 效能調整"
                            },
                            {
                                "type": "revert",
                                "section": "⏪ 退版"
                            },
                            {
                                "type": "docs",
                                "section": "📃 文件調整",
                                "hidden": false
                            },
                            {
                                "type": "style",
                                "section": "🌈 樣式調整",
                                "hidden": false
                            },
                            {
                                "type": "chore",
                                "section": "🛠️ 重大更新",
                                "hidden": true
                            },
                            {
                                "type": "refactor",
                                "section": "🔨 程式碼重構",
                                "hidden": true
                            },
                            {
                                "type": "test",
                                "section": "🔬 單元測試",
                                "hidden": false
                            },
                            {
                                "type": "build",
                                "section": "🔧 程式重構",
                                "hidden": false
                            },
                            {
                                "type": "ci",
                                "section": "🐎 持續整合",
                                "hidden": false
                            },
                            {
                                "type": "other",
                                "section": "🔄 其他",
                                "hidden": false
                            }
                        ]
                    },
                    "parserOpts": {
                        "noteKeywords": [
                            "BREAKING CHANGE",
                            "BREAKING CHANGES",
                            "BREAKING"
                        ]
                    }
                }
            ],
            "@semantic-release/gitlab",
            [
                "@semantic-release/git",
                {
                    "assets": [
                        "package.json",
                        "package-lock.json",
                        "CHANGELOG.md"
                    ],
                    "message": "${nextRelease.type === 'major' ? '🛠️chore(release):這次是重大版更!!!' : '🐞feat/fix(release):這只是小版更!!!'}\n\n v${nextRelease.version} 新的專案版本已釋出!!! [skip ci]"
                }
            ]
        ],
        "prepare": [
            "@semantic-release/changelog",
            "@semantic-release/npm",
            {
                "path": "@semantic-release/git",
                "assets": [
                    "package.json",
                    "package-lock.json",
                    "CHANGELOG.md"
                ],
                "npmPublish": true,
                "message": "${nextRelease.type === 'major' ? '🛠️chore(release):這次是重大版更!!!' : '🐞feat/fix(release):這只是小版更!!!'}\n\n v${nextRelease.version} 新的專案版本已釋出!!! [skip ci]"
            }
        ],
        "generateNotes": {
            "path": "./custom-release-notes-generator.js"
        }
    }
}

三、完成結果

Readme

Keywords

none

Package Sidebar

Install

npm i gitbook-plugin-tags-categories

Weekly Downloads

3

Version

1.0.28

License

ISC

Unpacked Size

43.3 kB

Total Files

8

Last publish

Collaborators

  • mark20240214