Confluence Copy Title Link

Add permalink to conflucence document, Enhanced side tree.

目前为 2021-08-27 提交的版本。查看 最新版本

// ==UserScript==
// @name         Confluence Copy Title Link
// @namespace    https://blog.simplenaive.cn
// @version      0.11
// @description  Add permalink to conflucence document, Enhanced side tree.
// @author       You
// @match        https://confluence.zhenguanyu.com/*
// @icon         https://www.google.com/s2/favicons?domain=zhenguanyu.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    console.log(window.$)
    const $ = s => document.querySelector(s);
    const $$ = s => Array.from(document.querySelectorAll(s));
    const waitUI = cb => new Promise((res) => res(cb()));

    let state = {
        enhanced: false
    }

    const styles = `
    .header-with-link {
        display: flex;
        align-items: center;
    }
    .header-link {
        color: #0049B0!important;
        border: 2px solid #0049B0;
        border-radius: 5px;
        font-size: 14px;
        margin-left: 10px;
        padding: 0px 3px;
    }
    ._yifei-message {
        position: fixed;
        top: 150px;
        box-shadow: 0 2px 10px rgb(0 0 0 / 25%);
        background: white;
        color: black;
        transform: translateY(-50px);
        transition: all ease .3s;
        left: 50%;
        padding: 10px 20px;
        border-radius: 5px;
        opacity: 0;
    }

    ._yifei-message-show {
        transform: translateY(0);
        opacity: 1;
    }

    .plugin_pagetree_children_content:hover {
        background: #eee;
        cursor: pointer;
    }

    .plugin_pagetree_children_list > li {
        margin: 0!important;
    }

    .plugin_pagetree_children_content {
        padding: 5px;
        border-radius: 3px;
    }

    .plugin_pagetree_childtoggle_container {
        padding-top: 3px;
    }
    `

    const addStyle = () => {
        const styleSheet = document.createElement("style")
        styleSheet.type = "text/css"
        styleSheet.innerText = styles
        document.head.appendChild(styleSheet)
    }

    class Message {
        constructor() {
            this.dom = document.createElement('div')
            this.dom.className = '_yifei-message'
            this.SHOW_CLASS = '_yifei-message-show'
            this.timeout = null;
            document.body.appendChild(this.dom)
        }
        show (text) {
            this.timeout && clearTimeout(this.timeout)
            this.dom.innerText = text
            this.dom.classList.add(this.SHOW_CLASS)
            this.timeout = setTimeout(() => this.hide(), 1500)
        }

        hide() {
            this.dom.classList.remove(this.SHOW_CLASS)
        }
    }

    const message = new Message()

    const addLinkToHeader = () => {
        const headers = new Array(6).fill(0).map((v, i) => {
            return $$(`h${i + 1}`)
        }).reduce((p, c) => p.concat(c), []).filter(v => v.id)
        console.log(headers)

        headers.forEach(h => {
            const link = document.createElement('a')
            link.className = 'header-link'
            link.innerText = '#'

            link.href = location.hash ? location.href.replace(location.hash, `#${h.id}`) : location.href + `#${h.id}`
            link.title = 'click to copy link'

            link.onclick = () => {
                console.log('click', link.href)
                message.show('链接已复制到剪切板')
                navigator.clipboard.writeText(link.href)
            };

            h.classList.add('header-with-link')
            h.appendChild(link)
        })
    }

    const addLinkToComment = () => {
        const comments = $$('.comment-thread')
        console.log(comments)

        comments.forEach(c => {
            const actions = c.querySelector('.comment-actions')

            // confluence 自带 permalink,但是不想用
            // const permalink = c.querySelector('.comment-actions-secondary')
            // permalink.style.display = 'inline'

            const action = document.createElement('ul')
            action.className = 'comment-action-copy'

            const link = document.createElement('a')

            link.innerText = '复制评论链接'
            link.href = location.hash ? location.href.replace(location.hash, `#${c.id}`) : location.href + `#${c.id}`
            link.title = 'click to copy link'

            link.onclick = () => {
                console.log('click', link.href)
                message.show('链接已复制到剪切板')
                navigator.clipboard.writeText(link.href)
            };

            action.appendChild(link)
            actions.appendChild(action)
        })
    }

    const addPreviewBtnToEditPage = () => {
        if (location.href.indexOf('resumedraft') < 0) return;
        console.log('add preview btn')
        const expandBtn = $('#rte-button-ellipsis')
        const btnContainer = $('.cancel-button-container-shared-draft')

        const doPreview = () => {
            waitUI(expandBtn.click).then(() => {
                const previewBtn = $('#rte-button-preview')
                previewBtn.click()
            })
        }

        const prevBtn = document.createElement('button')
        prevBtn.className = 'aui-button'
        btnContainer.appendChild(prevBtn)
    }

    const enhanceTree = () => {
        const doEnhance = () => {
            const items = $$('.plugin_pagetree_children_content')

            if (items.length > 0) state.enhanced = true

            items.forEach(dom => {
                if (dom.enhanced) return
                dom.enhanced = true
                dom.onclick = () => {
                    dom.previousElementSibling.children[0].click()
                }
            })
        }

        const listenDom = () => {
            const side = $('.acs-side-bar')
            if (!side || side.enhanced) return

            // observe side bar
            const config = { childList: true, attributes: true }
            const callback = function(mutationsList) {
                // enhance child tree when new items loaded
                doEnhance()
            };

            const observer = new MutationObserver(callback)
            observer.observe(side, config)

            side.enhanced = true
            console.log('observed', side)

            // enhance first
            doEnhance()

            // disable onmousemove event
            document.body.onmousemove = () => {}
        }


        document.body.onmousemove = listenDom;
    }

    const openDialog = () => {
        const dialog = $('.content-macro')
        console.log('opening', dialog)
        dialog.click()
        closeDialog()
    }

    const closeDialog = () => {
        const cancel = $('#macro-details-page .button-panel-cancel-link')
        cancel.click()
    }

    const confirmDialog = (t = 500) => {
        setTimeout(() => $('#macro-details-page .button-panel-button.ok').click(), t)
    }

    const addFastInfo = () => {
        const infoBtn = $('#macro-info')
        const childrenBtn = $('#macro-children')
        const buttons = [
            ['#macro-info', 'info-filled', '信息', confirmDialog],
            ['#macro-children', 'overview', '子页面', () => {
                console.log('ok')
                setTimeout(() => {
                    $('#macro-param-all').click()
                    confirmDialog(100)
                }, 500)
            }]
        ]
        const oldCb = document.body.onmousemove;

        const tryToAddDom = () => {
            const toolbar = $('.aui-toolbar2-primary')
            console.log(toolbar)
            if (!toolbar || toolbar.enhanced) return

            openDialog()
            const newTools = document.createElement('ul')
            newTools.className = 'aui-buttons'

            buttons.forEach(([bid, icon, name, cb]) => {
                console.log(bid, icon, name)

                // create new icons
                const li = document.createElement('li')
                li.className = 'toolbar-item aui-button aui-button-subtle'

                li.innerHTML = `
                    <span class="icon aui-icon aui-icon-small aui-iconfont-${icon}">${name}</span>
                `
                li.onclick = () => {
                    $(bid).click()
                    console.log('click', bid)
                    cb()
                }

                newTools.appendChild(li)
            })

            toolbar.enhanced = true
            document.body.onmousemove = oldCb;

            toolbar.appendChild(newTools)
        }


        document.body.onmousemove = () => {
            oldCb()
            tryToAddDom()
        }
    }

    const debugMode = () => {
        const userLinks = $$('.confluence-userlink')
        userLinks.forEach(v => v.style.filter = 'blur(4px)')
        $('#breadcrumbs').style.filter = 'blur(4px)'
        document.onclick = () => $('#wm').style.filter = 'blur(5px)'
    }

    addStyle()
    addLinkToHeader()
    addLinkToComment()
    addPreviewBtnToEditPage()
    enhanceTree()
    addFastInfo()
    // debugMode()
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址