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

feat(helper/toc): specify maximum number of items to output #5487

Merged
merged 5 commits into from
Jul 1, 2024

Conversation

KentarouTakeda
Copy link
Contributor

What does it do?

Added the ability to set an upper limit on the number of items in the table of contents output by the toc() helper.

If no value is specified, the default is Infinity. This is no different from previous behavior. If we specify a number greater than or equal to 1, the elements will be truncated in the following order.

  • Delete items from descendants to ancestors (from <h6> to <h1>) to fit within the specified number.
  • Subheadings, which are lower-level headings on the page, will be removed in groups by level.
  • The behavior differs only for the highest heading that appears on the page, which is deleted sequentially from the back.

For example, if we have a heading like this:

## 1
### 1-1
### 1-2
## 2
### 2-1

If 5 is specified for max_items, all items will be output. On the other hand, if we specify 4 or 3,

## 1
### 1-1 truncated
### 1-2 truncated
## 2
### 2-1 truncated

All <h3> are removed, resulting in two items being output. This is the same result as specifying 2 for max_items.
This is because this outline requires five elements to display up to <h3>.

Only the highest heading that appears on the page behaves differently. For example, if we specify 1 for max_items,

## 1
### 1-1 truncated
### 1-2 truncated
## 2 truncated
### 2-1 truncated

Instead of all <h2> being deleted at once as before, they will be deleted sequentially from the bottom. This is to avoid unintentionally not outputting anything.

In addition to the code, I welcome any feedback regarding the specifications described here. I believe this specification is the best, but if you have any other good ideas, I would definitely consider them.

Screenshots

Pull request tasks

  • Add test cases for the changes.
  • Passed the CI test.

Copy link

github-actions bot commented May 5, 2024

How to test

git clone -b max-items-of-toc https://github.com/KentarouTakeda/hexojs-hexo.git
cd hexo
npm install
npm test

@coveralls
Copy link

coveralls commented May 5, 2024

Pull Request Test Coverage Report for Build 9729543737

Details

  • 26 of 26 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.01%) to 99.49%

Totals Coverage Status
Change from base Build 9706521730: 0.01%
Covered Lines: 9369
Relevant Lines: 9417

💛 - Coveralls

@KentarouTakeda
Copy link
Contributor Author

It seems that the test is failing at some points unrelated to this pull request. Other pull requests have also failed, so I'll leave it as is.

@@ -27,7 +29,7 @@ function tocHelper(str: string, options: Options = {}) {
list_number: true
}, options);

const data = tocObj(str, { min_depth: options.min_depth, max_depth: options.max_depth });
const data = getAndTruncateTocObj(str, { min_depth: options.min_depth, max_depth: options.max_depth }, options.max_items);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user does not need max_items, then there is no need to perform this operation everytime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed: c17db64

I thought it was necessary to avoid tocObj() appearing multiple times in different places, so I wrote the skip judgment at the beginning of getAndTruncateTocObj() instead of where you gave the example.

Comment on lines 117 to 118
const min = Math.min(...data.map(item => item.level));
const max = Math.max(...data.map(item => item.level));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...data.map(item => item.level) They look the same,
I guess it doesn't need to be executed twice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed: f8d04a6

Comment on lines +121 to +123
for (let currentLevel = max; data.length > max_items && currentLevel > min; currentLevel--) {
data = data.filter(item => item.level < currentLevel);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be inefficient (iterating data over and over again). But I don't have any better idea for now.

Copy link
Member

@yoshinorin yoshinorin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uiolee @SukkaW
Do you have any suggestions? If possible, I would like to release this in version 7.3.0. #5506

Copy link
Member

@SukkaW SukkaW left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation is inefficient. But since the benchmark doesn't show any regression, I am good with that.

@yoshinorin yoshinorin merged commit c321bb6 into hexojs:master Jul 1, 2024
22 of 23 checks passed
@D-Sketon
Copy link
Member

D-Sketon commented Jul 2, 2024

Site needs to be updated

@yoshinorin
Copy link
Member

Site needs to be updated

@KentarouTakeda
Would you please submit a PR to https://github.com/hexojs/site ? Thanks :)

@KentarouTakeda
Copy link
Contributor Author

Of course!
Please wait just a moment.

@KentarouTakeda KentarouTakeda deleted the max-items-of-toc branch July 3, 2024 07:24
dimaslanjaka pushed a commit to dimaslanjaka/hexo that referenced this pull request Oct 3, 2024
)

* feat(helper/toc): specify maximum number of items to output

* perf: skip evaluation if `max_items` is not specified

* perf: streamline getting min and max heading level

---------

Co-authored-by: Uiolee <22849383+uiolee@users.noreply.github.com>
Co-authored-by: yoshinorin <yoshinorin.net@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants