生成文档树列表项

生成文档树列表项

see https://ld246.com/article/1741359650489

pc端

// 第一步 调用 listDocsByPath获取文档树文档信息
//fetchSyncPost('/api/filetree/listDocsByPath', {notebook:'20240723175050-336994k',path:'/20240728220858-adaleye'})

// 第二步 调用genFileHTML函数生成li项
// see https://github.com/siyuan-note/siyuan/blob/1317020c1791edf440da7f836d366567e03dd843/app/src/layout/dock/Files.ts#L1224
function genFileHTML(item) {
        let countHTML = "";
        if (item.count && item.count > 0) {
            countHTML = `<span class="popover__block counter b3-tooltips b3-tooltips__nw" aria-label="${window.siyuan.languages.ref}">${item.count}</span>`;
        }
        const ariaLabel = genDocAriaLabel(item, escapeAriaLabel);
        const paddingLeft = (item.path.split("/").length - 1) * 18;
        return `<li data-node-id="${item.id}" data-name="${Lute.EscapeHTMLStr(item.name)}" draggable="true" data-count="${item.subFileCount}" 
data-type="navigation-file" 
style="--file-toggle-width:${paddingLeft + 18}px" 
class="b3-list-item b3-list-item--hide-action" data-path="${item.path}">
    <span style="padding-left: ${paddingLeft}px" class="b3-list-item__toggle b3-list-item__toggle--hl${item.subFileCount === 0 ? " fn__hidden" : ""}">
        <svg class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg>
    </span>
    <span class="b3-list-item__icon b3-tooltips b3-tooltips__n popover__block" data-id="${item.id}" aria-label="${window.siyuan.languages.changeIcon}">${unicode2Emoji(item.icon || (item.subFileCount === 0 ? (window.siyuan.storage['local-images']?.file||'1f4c4') : (window.siyuan.storage['local-images']?.folder||'1f4d1')))}</span>
    <span class="b3-list-item__text ariaLabel" data-position="parentE"
aria-label="${ariaLabel}">${getDisplayName(item.name, true, true)}</span>
    <span data-type="more-file" class="b3-list-item__action b3-tooltips b3-tooltips__nw" aria-label="${window.siyuan.languages.more}">
        <svg><use xlink:href="#iconMore"></use></svg>
    </span>
    <span data-type="new" class="b3-list-item__action b3-tooltips b3-tooltips__nw${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.newSubDoc}">
        <svg><use xlink:href="#iconAdd"></use></svg>
    </span>
    ${countHTML}
</li>`;
}

function genDocAriaLabel(item, escapeMethod) {
    return `${escapeMethod(getDisplayName(item.name, true, true))} <small class='ft__on-surface'>${item.hSize}</small>${item.bookmark ? "<br>" + window.siyuan.languages.bookmark + " " + escapeMethod(item.bookmark) : ""}${item.name1 ? "<br>" + window.siyuan.languages.name + " " + escapeMethod(item.name1) : ""}${item.alias ? "<br>" + window.siyuan.languages.alias + " " + escapeMethod(item.alias) : ""}${item.memo ? "<br>" + window.siyuan.languages.memo + " " + escapeMethod(item.memo) : ""}${item.subFileCount !== 0 ? window.siyuan.languages.includeSubFile.replace("x", item.subFileCount) : ""}<br>${window.siyuan.languages.modifiedAt} ${item.hMtime}<br>${window.siyuan.languages.createdAt} ${item.hCtime}`;
}

function escapeAriaLabel(html) {
    if (!html) {
        return html;
    }
    return html.replace(/"/g, "&quot;").replace(/'/g, "&apos;")
        .replace(/</g, "&amp;lt;").replace(/&lt;/g, "&amp;lt;");
}

function getDisplayName(filePath, basename = true, removeSY = false) {
    let name = filePath;
    if (basename) {
        name = pathPosix().basename(filePath);
    }
    if (removeSY && name.endsWith(".sy")) {
        name = name.substr(0, name.length - 3);
    }
    return name;
}

function pathPosix() {
    if (require && require('path').posix) {
        return require('path').posix;
    }
    return path;
}

// unicode转emoji
// 使用示例:unicode2Emoji('1f4c4');
// see https://ld246.com/article/1726920727424
function unicode2Emoji(unicode, className = "", needSpan = false, lazy = false) {
    if (!unicode) {
        return "";
    }
    let emoji = "";
    if (unicode.indexOf(".") > -1) {
        emoji = `<img class="${className}" ${lazy ? "data-" : ""}src="/emojis/${unicode}"/>`;
    } else {
        try {
            unicode.split("-").forEach(item => {
                if (item.length < 5) {
                    emoji += String.fromCodePoint(parseInt("0" + item, 16));
                } else {
                    emoji += String.fromCodePoint(parseInt(item, 16));
                }
            });
            if (needSpan) {
                emoji = `<span class="${className}">${emoji}</span>`;
            }
        } catch (e) {
            // 自定义表情搜索报错 https://github.com/siyuan-note/siyuan/issues/5883
            // 这里忽略错误不做处理
        }
    }
    return emoji;
}

手机端

// see https://github.com/siyuan-note/siyuan/blob/1317020c1791edf440da7f836d366567e03dd843/app/src/mobile/dock/MobileFiles.ts#L725
function genMobileFileHTML(item) {
    let countHTML = "";
    if (item.count && item.count > 0) {
        countHTML = `<span class="counter">${item.count}</span>`;
    }
    return `<li data-node-id="${item.id}" data-name="${Lute.EscapeHTMLStr(item.name)}" data-type="navigation-file" 
class="b3-list-item" data-path="${item.path}">
<span style="padding-left: ${(item.path.split("/").length - 1) * 20}px" class="b3-list-item__toggle${item.subFileCount === 0 ? " fn__hidden" : ""}">
    <svg class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg>
</span>
<span class="b3-list-item__icon">${unicode2Emoji(item.icon || (item.subFileCount === 0 ? (window.siyuan.storage['local-images']?.file||'1f4c4') : (window.siyuan.storage['local-images']?.folder||'1f4d1')))}</span>
<span class="b3-list-item__text">${getDisplayName(item.name, true, true)}</span>
<span data-type="more-file" class="b3-list-item__action b3-tooltips b3-tooltips__nw" aria-label="${window.siyuan.languages.more}">
    <svg><use xlink:href="#iconMore"></use></svg>
</span>
<span data-type="new" class="b3-list-item__action b3-tooltips b3-tooltips__nw${window.siyuan.config.readonly ? " fn__none" : ""}" aria-label="${window.siyuan.languages.newSubDoc}">
    <svg><use xlink:href="#iconAdd"></use></svg>
</span>
${countHTML}
</li>`;
};

封装通过文档id生成li项

async function getTreeDocById(id, box, path) {
    if(!box || path) {
        const doc = await fetchSyncPost('/api/filetree/getDoc', {id:id});
        box = doc?.data?.box;
        path = doc?.data?.path;
        if(!box || !path) return;
    }
    if(path.toLocaleLowerCase().endsWith('.sy')) {
        const pathArr = path.split('/');
        pathArr.pop();
        path = pathArr.join('/');
        path = path === '' ? '/' : path;
    }
    let list = await fetchSyncPost('/api/filetree/listDocsByPath', {notebook:box, path:path});
    list = list.data?.files?.filter(item=>item.id === id) || [];
    return list[0];
}

image.png

留下你的脚步
推荐阅读