Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix loadSider false render structure issue #2470

Merged
merged 29 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
86ad7f3
fix: fix loadSider false render structure issue
Koooooo-7 Jul 19, 2024
378b85e
Merge branch 'develop' into fix-loadsidebar
Koooooo-7 Jul 19, 2024
20bf3a6
update: resolve merge conflict
Koooooo-7 Jul 19, 2024
0c21a1d
chore: fix ci
Koooooo-7 Jul 19, 2024
df5b9ec
chore: fix ci
Koooooo-7 Jul 19, 2024
31d3295
chore: fix ci
Koooooo-7 Jul 19, 2024
97b25f2
chore: fix ci
Koooooo-7 Jul 20, 2024
a942713
remove sidebar call in renderMain
Koooooo-7 Jul 20, 2024
d4c13a1
Merge branch 'develop' into fix-loadsidebar
Koooooo-7 Jul 20, 2024
8cf4640
fix:ci
Koooooo-7 Jul 20, 2024
73a6d14
chore: fix ci
Koooooo-7 Jul 20, 2024
5840fc4
chore: fix ci on jest
Koooooo-7 Jul 20, 2024
d3efb1d
chore: fix ci on jest
Koooooo-7 Jul 20, 2024
5224486
revert ci config
Koooooo-7 Jul 20, 2024
7628817
update: remove all sidebar.test.hs
Koooooo-7 Jul 20, 2024
6c83909
update: remove all sidebar.test.js
Koooooo-7 Jul 20, 2024
cd5988c
update: add test case1 for sidebar.test.js
Koooooo-7 Jul 20, 2024
a6fb2dd
update: replace to add no sidebar config test in sidebar.test.js
Koooooo-7 Jul 21, 2024
3364b33
update: reduce css selector verify case
Koooooo-7 Jul 21, 2024
9e8246b
dope
Koooooo-7 Jul 21, 2024
98fc093
dope2
Koooooo-7 Jul 21, 2024
d563679
Merge branch 'develop' into fix-loadsidebar
Koooooo-7 Jul 22, 2024
82ae5f5
fix: ci
Koooooo-7 Jul 24, 2024
3a0b3b3
huge: it seems I still need remove the --runInBand
Koooooo-7 Jul 24, 2024
32635ba
fix: remove page h1 heading in sidebar and correct class for ul
Koooooo-7 Jul 26, 2024
6b1fa06
update: put class on top ul elm
Koooooo-7 Jul 27, 2024
3612bf8
update: put class on top ul elm
Koooooo-7 Jul 27, 2024
1c82921
try add runInBand
Koooooo-7 Jul 27, 2024
b08908f
Merge branch 'develop' into fix-loadsidebar
Koooooo-7 Jul 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/core/fetch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,19 @@ export function Fetch(Base) {

_loadSideAndNav(path, qs, loadSidebar, cb) {
return () => {
if (!loadSidebar) {
return cb();
}

const fn = result => {
const renderSidebar = result => {
this._renderSidebar(result);
cb();
};

// Load sidebar
this.#loadNested(path, qs, loadSidebar, fn, this, true);
if (!loadSidebar) {
// Although, we don't load sidebar from sidebar file, we still need call the render to auto generate sidebar from headings toc
renderSidebar();
return;
}

// Load sidebar from the sidebar file
this.#loadNested(path, qs, loadSidebar, renderSidebar, this, true);
};
}

Expand Down
59 changes: 31 additions & 28 deletions src/core/render/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,8 @@ export class Compiler {
}

/**
* Compile sidebar
* @param {String} text Text content
* Compile sidebar, it uses _sidebar.md ( or specific file) or the content's headings toc to render sidebar.
* @param {String} text Text content from the sidebar file, maybe empty
* @param {Number} level Type of heading (h<level> tag)
* @returns {String} Sidebar element
*/
Expand All @@ -261,50 +261,53 @@ export class Compiler {
const currentPath = this.router.getCurrentPath();
let html = '';

// compile sidebar from _sidebar.md
if (text) {
html = this.compile(text);
} else {
for (let i = 0; i < toc.length; i++) {
if (toc[i].ignoreSubHeading) {
const deletedHeaderLevel = toc[i].level;
toc.splice(i, 1);
// Remove headers who are under current header
for (
let j = i;
j < toc.length && deletedHeaderLevel < toc[j].level;
j++
) {
toc.splice(j, 1) && j-- && i++;
}

i--;
return this.compile(text);
}
// compile sidebar from content's headings toc
for (let i = 0; i < toc.length; i++) {
if (toc[i].ignoreSubHeading) {
const deletedHeaderLevel = toc[i].depth;
toc.splice(i, 1);
// Remove headers who are under current header
for (
let j = i;
j < toc.length && deletedHeaderLevel < toc[j].depth;
j++
) {
toc.splice(j, 1) && j-- && i++;
}
}

const tree = this.cacheTree[currentPath] || genTree(toc, level);
html = treeTpl(tree, /* html */ '<ul>{inner}</ul>');
this.cacheTree[currentPath] = tree;
i--;
}
}

const tree = this.cacheTree[currentPath] || genTree(toc, level);
html = treeTpl(tree);
this.cacheTree[currentPath] = tree;
return html;
}

/**
* When current content redirect to a new path file, clean pre content headings toc
*/
resetToc() {
this.toc = [];
}

/**
* Compile sub sidebar
* @param {Number} level Type of heading (h<level> tag)
* @returns {String} Sub-sidebar element
*/
subSidebar(level) {
if (!level) {
this.toc = [];
return;
}

const currentPath = this.router.getCurrentPath();
const { cacheTree, toc } = this;

toc[0] && toc[0].ignoreAllSubs && toc.splice(0);
toc[0] && toc[0].level === 1 && toc.shift();
// remove the first heading from the toc if it is a top-level heading
toc[0] && toc[0].depth === 1 && toc.shift();

for (let i = 0; i < toc.length; i++) {
toc[i].ignoreSubHeading && toc.splice(i, 1) && i--;
Expand Down
2 changes: 1 addition & 1 deletion src/core/render/gen-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function genTree(toc, maxLevel) {
const last = {};

toc.forEach(headline => {
const level = headline.level || 1;
const level = headline.depth || 1;
const len = level - 1;

if (level > maxLevel) {
Expand Down
7 changes: 2 additions & 5 deletions src/core/render/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ export function Render(Base) {

this._renderTo(markdownElm, html);

// Render sidebar with the TOC
!docsifyConfig.loadSidebar && this._renderSidebar();

// Execute markdown <script>
if (
docsifyConfig.executeScript ||
Expand Down Expand Up @@ -298,6 +295,7 @@ export function Render(Base) {
}

this._renderTo('.sidebar-nav', this.compiler.sidebar(text, maxLevel));

sidebarToggleEl.setAttribute('aria-expanded', !isMobile());

const activeElmHref = this.router.toURL(this.route.path);
Expand All @@ -309,8 +307,7 @@ export function Render(Base) {
activeEl.parentNode.innerHTML +=
this.compiler.subSidebar(subMaxLevel) || '';
} else {
// Reset toc
this.compiler.subSidebar();
this.compiler.resetToc();
}

// Bind event
Expand Down
7 changes: 5 additions & 2 deletions src/core/render/tpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,13 @@ export function tree(
let innerHTML = '';
toc.forEach(node => {
const title = node.title.replace(/(<([^>]+)>)/g, '');
innerHTML += /* html */ `<li><a class="section-link" href="${node.slug}" title="${title}">${node.title}</a></li>`;
let current = `<li><a class="section-link" href="${node.slug}" title="${title}">${node.title}</a></li>`;
if (node.children) {
innerHTML += tree(node.children, tpl);
// when current node has children, we need put them all in parent's <li> block without the `class="app-sub-sidebar"` attribute
const children = tree(node.children, '<ul>{inner}</ul>');
current = `<li><a class="section-link" href="${node.slug}" title="${title}">${node.title}</a>${children}</li>`;
}
innerHTML += current;
});
return tpl.replace('{inner}', innerHTML);
}
Expand Down
121 changes: 121 additions & 0 deletions test/integration/sidebar.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import docsifyInit from '../helpers/docsify-init.js';

describe('Test sidebar render toc structure', function () {
test('Render sidebar with loadSidebar=true and the _sidebar.md file', async () => {
await docsifyInit({
config: {
loadSidebar: '_sidebar.md',
},
markdown: {
homepage: '# Hello World',
sidebar: `
- Getting started
- [Level1](QuickStart.md)
- [Level2](QuickStart2.md)
`,
},
waitForSelector: '.sidebar-nav > ul',
});

const sidebarElm = document.querySelector('.sidebar');
/**
* Expected render result
* ==========================
*<ul>
* <li>
* Getting started
* <ul>
* <li>
* <a href="#/QuickStart" title="Level1">Level1</a>
* <ul>
* <li><a href="#/QuickStart2" title="Level2">Level2</a></li>
* </ul>
* </li>
* </ul>
* </li>
* </ul>
*/

const GettingStarted = document.querySelector('.sidebar-nav > ul > li');
const level1_Elm = document.querySelector(
'.sidebar-nav > ul > li > ul> li',
);
const level1_A_tag = level1_Elm.querySelector('a');

const level2_Elm = level1_Elm.querySelector(' ul > li ');

const level2_A_tag = level2_Elm.querySelector('a');

expect(sidebarElm).not.toBeNull();
expect(GettingStarted).not.toBeNull();
expect(level1_Elm).not.toBeNull();
expect(level1_A_tag).not.toBeNull();
expect(level2_Elm).not.toBeNull();
expect(level2_A_tag).not.toBeNull();
expect(level1_A_tag.textContent).toContain('Level1');
expect(level2_A_tag.textContent).toContain('Level2');
});

test('Render sidebar with loadSidebar=false should be same to loadSidebar=true sidebar structure', async () => {
await docsifyInit({
config: {
loadSidebar: false,
},
markdown: {
homepage: `
# Getting started
some thing
## Level1
foo
### Level2
bar
`,
},
waitForSelector: '.sidebar-nav > ul',
});

const sidebarElm = document.querySelector('.sidebar');
/**
* Expected render result
* ==========================
*<ul>
* <li>
* Getting started
* <ul>
* <li>
* <a href="#/QuickStart" title="Level1">Level1</a>
* <ul>
* <li><a href="#/QuickStart2" title="Level2">Level2</a></li>
* </ul>
* </li>
* </ul>
* </li>
* </ul>
*/

const appSubSidebarTargetElm = document.querySelector('.sidebar-nav > ul');
expect(appSubSidebarTargetElm).not.toBeNull();
const ulClass = appSubSidebarTargetElm.className;
// the sidebar-nav > ul should have the class app-sub-sidebar
expect(ulClass).toContain('app-sub-sidebar');

const GettingStarted = document.querySelector('.sidebar-nav > ul > li');
const level1_Elm = document.querySelector(
'.sidebar-nav > ul > li > ul> li',
);
const level1_A_tag = level1_Elm.querySelector('a');

const level2_Elm = level1_Elm.querySelector(' ul > li ');

const level2_A_tag = level2_Elm.querySelector('a');

expect(sidebarElm).not.toBeNull();
expect(GettingStarted).not.toBeNull();
expect(level1_Elm).not.toBeNull();
expect(level1_A_tag).not.toBeNull();
expect(level2_Elm).not.toBeNull();
expect(level2_A_tag).not.toBeNull();
expect(level1_A_tag.textContent).toContain('Level1');
expect(level2_A_tag.textContent).toContain('Level2');
});
});
Loading