Skip to content

Add color for highlighting fenced code blocks #2649

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

Merged
merged 31 commits into from
Apr 13, 2025

Conversation

IanCheah
Copy link
Contributor

@IanCheah IanCheah commented Mar 16, 2025

What is the purpose of this pull request?

  • Documentation update
  • Bug fix
  • Feature addition or enhancement
  • Code maintenance
  • DevOps
  • Improve developer experience
  • Others, please explain:

Fixes #2594

Overview of changes:

The new highlight feature

Now users are able to specify the color at each section they want to highlight by adding a @ followed by a color.
Previously, users will specify an inline code highlight as shown below. Depending on the code theme, the highlight will be default to #e6e6fa for the light theme and #000000 for the dark theme.
java {.line-numbers highlight-lines="1[:],3['Inventory'],3[4::6],4['It\'s designed'],5,6[8:15],6[18:],8[0::2],12[:]-14,16-18,20[12:]-22,24[1::]-26"}

With the new update, users can specify a color they want at each section. For example,
java {.line-numbers highlight-lines="1[:]@pink,3['Inventory']@blue,3[4::6]@orange,4['It\'s designed']@#000000,5,6[8:15]@purple,6[18:]@yellow,8[0::2],12[:]-14,16-18,20[12:]-22,24[1::]-26"}
Those sections of code with no color specified will fallback on the default highlight color in the previous implementation.

Running the above code will result in a inlinecode block that looks like this:
image

Changes to the documentation

I have added a relevant section under the User Guide. Here is the link to it https://inline-highlight.netlify.app/userguide/formattingcontents#code.

Anything you'd like to highlight/discuss:

Possible Improvements

Currently, users will be able to insert color in the format of either strings like blue, red, etc or hexadecimal representations of colors like #000000, #e6e6fa, etc. I intended for formats like rgb(230,230,230) or rgba(255, 87, 51, 0.5) to be recognized as well, which would be beneficial for people who are proficient with CSS.

The use of @

I used @ to separate the code lines as well as the color. The reason why I chose @ is because I wanted to use the string::split method and I had to choose a character that was not already present. Feel free to let me know if there are better/more intuitive way rather than @

Testing instructions:

  1. Fetch the PR
  2. Try out highlight feature as specified in the user guide.
  3. Add a @color field behind every comma-separated highlight section.

Proposed commit message: (wrap lines at 72 characters)
Add flexibility to highlighting fenced code blocks


Checklist: ☑️

  • Updated the documentation for feature additions and enhancements
  • Added tests for bug fixes or features
  • Linked all related issues
  • No unrelated changes

Reviewer checklist:

Indicate the SEMVER impact of the PR:

  • Major (when you make incompatible API changes)
  • Minor (when you add functionality in a backward compatible manner)
  • Patch (when you make backward compatible bug fixes)

At the end of the review, please label the PR with the appropriate label: r.Major, r.Minor, r.Patch.

Breaking change release note preparation (if applicable):

  • To be included in the release note for any feature that is made obsolete/breaking

Give a brief explanation note about:

  • what was the old feature that was made obsolete
  • any replacement feature (if any), and
  • how the author should modify his website to migrate from the old feature to the replacement feature (if possible).

@IanCheah IanCheah marked this pull request as draft March 16, 2025 13:59
import * as fs from 'fs';
import * as path from 'path';

const siteJsonPath = path.join(__dirname, '../../../../../../docs/site.json');
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if I understand this correctly. Would this always read the site.json from the docs? It won't read the site.json from the custom site, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, it just reads the site.json from the docs, which is wrong. I'm not sure how to extract the codeTheme field from the site.json from the custom site though.

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that the Site class stores the rootPath of the user's MarkBind site. Perhaps there's a way to pass that information to this file to get an absolute path to the site.json.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the inputs. I reused the initial logic to handle for the case where I want the default coloring. Initially, highlights are dealt with by the highlighted class. So what I did is to have a conditional check at each highlight, if there is no color specified, I reused the logic of the highlighted class, else, I simply added a custom style depending on the color input.

@IanCheah IanCheah marked this pull request as ready for review March 31, 2025 03:38
Copy link
Contributor

@gerteck gerteck left a comment

Choose a reason for hiding this comment

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

Thank you for your PR! Have some changes and comments that I think need to be addressed, do let me know if I have misunderstood the logic.

Copy link

codecov bot commented Apr 3, 2025

Codecov Report

Attention: Patch coverage is 61.90476% with 48 lines in your changes missing coverage. Please review.

Project coverage is 52.03%. Comparing base (1856da1) to head (8eecc8c).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
packages/core/src/html/codeblockProcessor.ts 0.00% 26 Missing and 2 partials ⚠️
packages/core/src/lib/markdown-it/index.ts 0.00% 15 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2649      +/-   ##
==========================================
+ Coverage   51.90%   52.03%   +0.13%     
==========================================
  Files         130      130              
  Lines        7104     7162      +58     
  Branches     1477     1593     +116     
==========================================
+ Hits         3687     3727      +40     
+ Misses       3263     3131     -132     
- Partials      154      304     +150     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@yyccbb yyccbb left a comment

Choose a reason for hiding this comment

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

Suggested some possible improvements. LGTM!

@yyccbb
Copy link
Contributor

yyccbb commented Apr 7, 2025

As for using "@" to indicate color, I am thinking would it be possible to just use "#" will a more robust parsing mechanism?

@IanCheah
Copy link
Contributor Author

As for using "@" to indicate color, I am thinking would it be possible to just use "#" will a more robust parsing mechanism?

Users can specify a color using hex, for e.g. #000000. Using # to indicate color may lead to colors that are specified using hex to be incorrectly parsed. For e.g 1[:]##000000 will result in the color being wrongly parsed.

@yyccbb
Copy link
Contributor

yyccbb commented Apr 12, 2025

As for using "@" to indicate color, I am thinking would it be possible to just use "#" will a more robust parsing mechanism?

Users can specify a color using hex, for e.g. #000000. Using # to indicate color may lead to colors that are specified using hex to be incorrectly parsed. For e.g 1[:]##000000 will result in the color being wrongly parsed.

I think there was a typo. What I meant was something like 1[:]#00ff00 or 1[:]#y. I think in general putting both hex color codes and color names after the same # will not lead to confusion? Correct me if I am wrong.
I just thought it would be good to avoid introducing new symbols as far as possible to make it easier on the users.

@IanCheah IanCheah changed the title Branch inline highlight new Add color for highlights in fenced code blocks Apr 13, 2025
@IanCheah
Copy link
Contributor Author

As for using "@" to indicate color, I am thinking would it be possible to just use "#" will a more robust parsing mechanism?

Users can specify a color using hex, for e.g. #000000. Using # to indicate color may lead to colors that are specified using hex to be incorrectly parsed. For e.g 1[:]##000000 will result in the color being wrongly parsed.

I think there was a typo. What I meant was something like 1[:]#00ff00 or 1[:]#y. I think in general putting both hex color codes and color names after the same # will not lead to confusion? Correct me if I am wrong. I just thought it would be good to avoid introducing new symbols as far as possible to make it easier on the users.

Currently what the code does is it will split by @ to obtain the color specified on the right of @, the color will then be added to the HTML like this style="background-color:${color};".

If split by # to obtain the resulting hex, say 000000, there will need to be additional checks before adding it into the HTML. This is because the current approach will result in something like style="background-color:000000;"

What about something that is not already present?

@lhw-1
Copy link
Contributor

lhw-1 commented Apr 13, 2025

I think there was a typo. What I meant was something like 1[:]#00ff00 or 1[:]#y. I think in general putting both hex color codes and color names after the same # will not lead to confusion? Correct me if I am wrong.

On the contrary, given that the convention is to have # for color hex codes and not for names (e.g. "red" or "blue"), having # would not be consistent with standard color notation conventions. Moreover, I don't think I would like the additional logic we would have to implement (e.g. check if string is 6 or 3 letters containing hexadecimal to decide if it is hex or not) - seems unnecessary. I think using @ is perfectly fine.

I agree that the usage of the color highlighting makes the string quite complex though. The example given:

java {.line-numbers highlight-lines="1[:]@pink,3['Inventory']@blue,3[4::6]@orange,4['It\'s designed']@#000000,5@rgb(120, 130, 250),6[8:15]@purple,6[18:]@yellow,8[0::2],12[:]-14,16-18,20[12:]-22,24[1::]-26"}

This is quite unreadable to me at this point, and if the person wants more organized color highlighting for their code (e.g. highlight whenever certain keywords appear), this will be quite annoying to modify one by one. I think it's certainly going to be worth discussing how to improve this feature.

But as a first stage implementation, I think this is a good first step.

Copy link
Contributor

@lhw-1 lhw-1 left a comment

Choose a reason for hiding this comment

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

Thanks for the PR @IanCheah! A few comments mostly on a potential refactor PR after this one (and likely after v6).

Another idea is expanding the colored highlight idea for specific keywords; it might be nice if the user can e.g. pass in a key-value mapping for keywords to colors, and we apply that mapping over a given code block. Maybe we can even expand this to beyond code blocks, to the page (or pages) in general. I think this can be further discussed in a separate issue!

return appliedRule.isUnboundedSlice()
? { highlightType: HIGHLIGHT_TYPES.WholeLine, bounds: null }
: { highlightType: HIGHLIGHT_TYPES.PartialText, bounds: appliedRule.bounds };
handleLineRange(lineNumber: number): {
Copy link
Contributor

Choose a reason for hiding this comment

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

There seems to be quite a few conditional checks in this function... I think that a refactor of these into separate functions might be good for readability and to simplify the logic. There seems to be this:

results.push({
  highlightType: HIGHLIGHT_TYPES.<Somthing>,
  bounds: null,
  color: this.color,
});

That seems to be repeated quite a bit - which I think would also benefit from a refactoring round.

color?: string;
}[] = [];
// Iterate over all rule components to find matches for the current line
this.ruleComponents.forEach((ruleComponent) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above. One too many nested conditionals for my comfort... We can take a look at a separate refactor PR after the v6 release. Seems like we should at least do a refactor round before the highlight logic becomes a bit too convoluted.

@lhw-1 lhw-1 changed the title Add color for highlights in fenced code blocks Add color for highlighting fenced code blocks Apr 13, 2025
@lhw-1 lhw-1 merged commit c2e18a7 into MarkBind:master Apr 13, 2025
11 checks passed
@github-actions github-actions bot added the r.Minor Version resolver: increment by 0.1.0 label Apr 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
r.Minor Version resolver: increment by 0.1.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow users to specify highlight colour in inline code
8 participants