Skip to content

Commit

Permalink
fix: prevent loop with overlapping chars (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
atomiks authored Dec 8, 2023
1 parent 06c821a commit 403a4bb
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 27 deletions.
23 changes: 8 additions & 15 deletions src/chars/charsHighlighter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { CharsElement } from '../..';
import { getElementsToHighlight } from './getElementsToHighlight';
import { wrapHighlightedChars } from './wrapHighlightedChars';
import { toString } from 'hast-util-to-string';
import { hasOwnProperty, isElement } from '../utils';
import { isElement } from '../utils';

/**
* Loops through the child nodes and finds the nodes that make up the chars.
Expand Down Expand Up @@ -73,7 +73,7 @@ export function charsHighlighter(
const props = isElement(childNode) ? childNode.properties : {};
if (
props &&
!hasOwnProperty(props, 'rehype-pretty-code-visited') &&
!Object.hasOwn(props, 'rehype-pretty-code-visited') &&
!Object.hasOwn(props, 'data-highlighted-chars-mark')
) {
return toString(childNode);
Expand All @@ -82,19 +82,12 @@ export function charsHighlighter(
.join('');
}
}
});

element.children.forEach((childNode) => {
if (!isElement(childNode)) {
return;
}

if (
hasOwnProperty(childNode.properties ?? {}, 'rehype-pretty-code-visited')
) {
if (childNode.properties) {
delete childNode.properties['rehype-pretty-code-visited'];
}
}
});
element.children.forEach((childNode) => {
if (!isElement(childNode)) return;
if (Object.hasOwn(childNode.properties, 'rehype-pretty-code-visited')) {
delete childNode.properties['rehype-pretty-code-visited'];
}
});
}
3 changes: 1 addition & 2 deletions src/chars/getElementsToHighlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
getContent,
nextElementMaybeContinuesChars,
} from './utils';
import { hasOwnProperty } from '../utils';

export function getElementsToHighlight(
element: Element,
Expand All @@ -32,7 +31,7 @@ export function getElementsToHighlight(
!maybeElement ||
maybeElement.type !== 'element' ||
// ignore any previously matched chars within
hasOwnProperty(
Object.hasOwn(
maybeElement.properties ?? {},
'rehype-pretty-code-visited',
)
Expand Down
3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
isInlineCode,
getThemeNames,
replaceLineClass,
hasOwnProperty,
} from './utils';

interface ApplyProps {
Expand Down Expand Up @@ -111,7 +110,7 @@ function apply(
}
}

if (hasOwnProperty(code.properties, 'data-line-numbers')) {
if (Object.hasOwn(code.properties, 'data-line-numbers')) {
code.properties['data-line-numbers-max-digits'] =
lineNumbersMaxDigits.toString().length;
}
Expand Down
9 changes: 1 addition & 8 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Theme } from '..';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function isJSONTheme(value: any): value is ThemeRegistrationRaw {
return value ? hasOwnProperty(value, 'tokenColors') : false;
return value ? Object.hasOwn(value, 'tokenColors') : false;
}

export function isElement(
Expand All @@ -17,13 +17,6 @@ export function isText(value: ElementContent | null): value is Text {
return value ? value.type === 'text' : false;
}

export function hasOwnProperty(
object: Record<string, unknown>,
string: string,
) {
return {}.hasOwnProperty.call(object, string);
}

export function isInlineCode(
element: Element,
parent: Element | Root | undefined,
Expand Down
8 changes: 8 additions & 0 deletions test/fixtures/highlightedCharsLoop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Highlighted chars loop

Overlapping chars should not cause infinite loop

```js /carrot/ /car/
const carrot = 'carrot';
const car = 'car';
```
64 changes: 64 additions & 0 deletions test/results/highlightedCharsLoop.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

<style>
html {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
}
body {
margin: 30px auto;
max-width: 800px;
}
pre {
padding: 16px;
}
span > code {
background: black;
padding: 4px;
}
[data-highlighted-line], [data-highlighted-chars] {
background-color: rgba(255, 255, 255, 0.25);
}
code[data-line-numbers] {
counter-reset: line;
}
code[data-line-numbers]>[data-line]::before {
counter-increment: line;
content: counter(line);
display: inline-block;
width: 1rem;
margin-right: 2rem;
text-align: right;
color: gray;
}

[data-rehype-pretty-code-figure] code[data-theme*=' '],
[data-rehype-pretty-code-figure] code[data-theme*=' '] span {
color: var(--shiki-light) !important;
background-color: var(--shiki-light-bg) !important;
}

@media (prefers-color-scheme: dark) {
[data-rehype-pretty-code-figure] code[data-theme*=' '],
[data-rehype-pretty-code-figure] code[data-theme*=' '] span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
}
}

.diff.add {
background-color: rgba(0, 255, 100, 0.25);
}
.diff.remove {
background-color: rgba(255, 100, 200, 0.35);
}
</style>
<h1>Highlighted chars loop</h1>
<p>Overlapping chars should not cause infinite loop</p>
<figure data-rehype-pretty-code-figure="">
<pre
style="background-color: #24292e; color: #e1e4e8"
tabindex="0"
data-language="js"
data-theme="github-dark"
><code data-language="js" data-theme="github-dark" style="display: grid;"><span data-line=""><span style="color:#F97583">const</span><span style="color:#79B8FF"> </span><mark data-highlighted-chars="" class="word"><span style="color:#79B8FF">carrot</span></mark><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> '</span><mark data-highlighted-chars="" class="word"><span style="color:#9ECBFF">carrot</span></mark><span style="color:#9ECBFF">'</span><span style="color:#E1E4E8">;</span></span>
<span data-line=""><span style="color:#F97583">const</span><span style="color:#79B8FF"> </span><mark data-highlighted-chars="" class="word"><span style="color:#79B8FF">car</span></mark><span style="color:#F97583"> =</span><span style="color:#9ECBFF"> '</span><mark data-highlighted-chars="" class="word"><span style="color:#9ECBFF">car</span></mark><span style="color:#9ECBFF">'</span><span style="color:#E1E4E8">;</span></span></code></pre>
</figure>

0 comments on commit 403a4bb

Please sign in to comment.