简书自动生成目录小工具

简书MD语法不识别 [TOC] ,也不会根据标题行(#) 来插入目录,作为每次看资料喜欢先看目录把握总体的我来说,很不习惯,查找跳转也不方便,所以就考虑自己写个小脚本来自动识别并生成目录;
系统: mac 10.12
chrome: 59.0


一年过去了依然不支持.jpg

效果图.png

简书目录脚本地址

前言

  1. 之前是想参考 Octotree 做个侧边栏目录, 目录不随文章内容滚动而滚动,有点类似ms word的导航窗格,无奈技术不到家,而且要做成 chromeextension 的话还得上架(developer模式加载插件貌似会提示warning,不喜),感觉有点复杂了,放弃;

  2. 使用用户脚本管理器 Tampermonkey , 写个自动识别标题行并生成有序列表的小工具就好,简单可行;

脚本地址 上面已经给出了,这里顺便推荐下这个脚本 Jianshu MD AUTO Scroll ,写文章时,会同步滚动编辑区和预览区;

思路

通过识别 h2,h3,h4,h5,h6 标题行,在文章开头处插入列表, 按标题层级进行缩进, 点击可进行跳转;
P.S. 由于简书文章主标题是 h1 , 默认不插入目录中, 我是从 h2 开始识别的,有需要的话可以自行修改脚本;

1. html页面自动跳转方法

不管哪种方式都得给目标位置标签添加 id 属性,而简书标题行默认都不带 id 属性,如下图:

默认文章结构.png

2. 遍历并添加 id 属性

由于简书自带jquery了,所以可以直接使用;

var menuIndex = 0;
var firstPaddingOrder = 1; //第一个标题行标签层级 <h1> -> 1  , <h2> -> 2, 第一个层级不用缩进

let titles = $('body').find('h2,h3,h4,h5,h6');
if(titles.length == 0){
    return;
}

// 获取文章中除标题外的第一个目录行层级
let firstElement = titles.first();
let firstTagName = firstElement[0].tagName;
firstPaddingOrder = parseInt(firstTagName.substring(1));
// 遍历文章中的所有标题行, 按需添加id值, 并增加记录到目录列表中
titles.each(function(){
        let tagName = $(this)[0].tagName.toLocaleLowerCase();
        let content = $(this).text(); // 标题内容
        // 若标题的id不存在,则使用新id
        let newTagId =$(this).attr('id');
        if(!$(this).attr('id')){
            newTagId = 'id_'+menuIndex;
            $(this).attr('id',newTagId);
            menuIndex++;
            // 将搜索到的标题行信息插入到目录中
           appendMenuItem(tagName,newTagId,content);
        }
});       

3. 在文章开头处插入列表

通过 chrome 的开发者工具查看简书文章,发现文章内容位于 <div class="show-content">...</div> 中,因此可在该 div 起始处插入一个 <ol> 标签;

// 在 body 标签内部添加 aside 侧边栏,用于显示文档目录
$('.show-content').prepend('<aside id="sideMenu" style="width: 100%; padding: 0px 15px 5px 15px;margin-bottom:20px;background-color: #dedede">目录</aside>');
$('#sideMenu').append('<ol id="menu_nav_ol" style="list-style:none;margin:0px;padding:0px;">');// 不显示 li 项前面默认的点标志, 也不使用默认缩进

P.S. 之前想做成侧边栏的,所以用了 aside ,懒得改了,先保留吧;

4. 将搜索到的标题行信息插入到目录列表中

这里做了点优化,按层级进行了缩进,但文章内容默认的第一级标题(h1 不考虑)不缩进,比如,文章一级标题是 h3,二级标题是 h4 ,则生成目录项时, 从h4 才开始缩进20px;

function appendMenuItem(tagName,id,content){
    let paddingLeft = (tagName.substring(1) - firstPaddingOrder) * 20;
    $('#menu_nav_ol').append('<li class="' + id +'" style="padding-left: '+ paddingLeft +'px;">' + content + '</li>');
}

5. 对目录列表项进行点击跳转设定

其实上面一步也可以直接生成 <a> 标签, 那就不需要再做其他操作了,默认点击就可以跳转到指定区域:

$('#menu_nav_ol').append('<li class="' + id +'" style="padding-left: '+ paddingLeft +'px;"><a href="#'+id+'">' + content + '</a></li>');`

但正如最开始说的,这种方式会改变url(其实无关紧要),因此我使用的是第四种方式:

// 绑定目录li点击事件,点击时跳转到对应的位置
$('#menu_nav_ol li').on('click', function () {
    let targetId = $(this).attr('class');
    //            document.getElementById(id).scrollIntoView();
    $("#" + targetId)[0].scrollIntoView(true);
});

完整脚本

// ==UserScript==
// @name         Jianshu side menu
// @name:zh-CN   简书目录
// @description:zh-CN 自动插入目录
// @namespace    https://github.com/lucid-lynxz
// @version      0.1
// @description  try to take over the world!
// @author       Lynxz
// @match        http://www.jianshu.com/p/*
//// @require      http://code.jquery.com/jquery-latest.js
// @grant        none
// ==/UserScript==
// 简书文章自动插入目录的脚本,用于tampermonkey
// 简书已自带jquery了,不需要添加此依赖
var menuIndex = 0;
var firstPaddingOrder = 1; //第一个标题行标签层级 <h1> -> 1  , <h2> -> 2, 第一个层级不用缩进

function scrollToView(id) {
    var element = $("#" + id)[0];
    console.log(id + " \n" + element);
    //            document.getElementById(id).scrollIntoView();
    element.scrollIntoView();
}

// 在侧边栏中添加目录项
function appendMenuItem(tagName, id, content) {
    let paddingLeft = (tagName.substring(1) - firstPaddingOrder) * 20;
    //$('#menu_nav_ol').append('<li class="' + id +  '" style="list-style:none;padding-left: '+ paddingLeft +'px;">' + content + '</li>');
    $('#menu_nav_ol').append('<li class="' + id + '" style="padding-left: ' + paddingLeft + 'px;">' + content + '</li>');
    //$('#menu_nav_ol').append('<li class="' + id +'" style="padding-left: '+ paddingLeft +'px;"><a href="#'+id+'">' + content + '</a></li>');
}

(function () {
    'use strict';
    let titles = $('body').find('h2,h3,h4,h5,h6');
    if (titles.length == 0) {
        return;
    }
    // 在 body 标签内部添加 aside 侧边栏,用于显示文档目录
    $('.show-content').prepend('<aside id="sideMenu" style="width: 100%; padding: 0px 15px 5px 15px;margin-bottom:20px;background-color: #dedede">目录</aside>');
    $('#sideMenu').append('<ol id="menu_nav_ol" style="list-style:none;margin:0px;padding:0px;">');// 不显示 li 项前面默认的点标志, 也不使用默认缩进

    // 获取文章中除标题外的第一个目录行层级
    let firstElement = titles.first();
    let firstTagName = firstElement[0].tagName;
    firstPaddingOrder = parseInt(firstTagName.substring(1));
    // 遍历文章中的所有标题行, 按需添加id值, 并增加记录到目录列表中
    titles.each(function () {
        let tagName = $(this)[0].tagName.toLocaleLowerCase();
        let content = $(this).text();
        // console.log('oriId = '+$(this).attr('id') + '\t menuIndex = ' + menuIndex);
        // 若标题的id不存在,则使用新id
        let newTagId = $(this).attr('id');
        if (!$(this).attr('id')) {
            newTagId = 'id_' + menuIndex;
            $(this).attr('id', newTagId);
            menuIndex++;
        }
        // console.log('newId = ' +newTagId);
        appendMenuItem(tagName, newTagId, content);
    });

    $('#sideMenu').append('</ol>');
    // 绑定目录li点击事件,点击时跳转到对应的位置
    $('#menu_nav_ol li').on('click', function () {
        let targetId = $(this).attr('class');
        //            document.getElementById(id).scrollIntoView();
        $("#" + targetId)[0].scrollIntoView(true);
    });
})();

P.S. 功能和代码都很简单,但使用, 另外写了两个小脚本,有需要的也可以安装下:

  1. CSDN广告清除请自适应宽度
  2. 掘金博客文章不登录直接显示全文
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容