Skip to content

Commit

Permalink
feat: add ignoreHtmlTag option
Browse files Browse the repository at this point in the history
  • Loading branch information
Gumball12 committed Aug 6, 2022
1 parent 30c7d49 commit c209f8c
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 23 deletions.
20 changes: 16 additions & 4 deletions README.md
Expand Up @@ -24,13 +24,13 @@ An Open-Source JavaScript Implementation of [Bionic Reading API](https://bionic-
| [Support ESM and CommonJS](#usage) ||
| [Custom `sep` Style](#options-sep) ||
| [Fixation-Points](#options-fixationpoint) ||
| [Ignore HTML Tags](#options-ignorehtmltag) ||

### Work in Progress

| Feature | Issues |
| ---------------------------------------------------- | ------------------------------------------------------- |
| Saccade | [#21](https://github.com/Gumball12/text-vide/issues/21) |
| Apply the Bionic Reading technique without HTML code | [#36](https://github.com/Gumball12/text-vide/issues/36) |
| Feature | Issues |
| ------- | ------------------------------------------------------- |
| Saccade | [#21](https://github.com/Gumball12/text-vide/issues/21) |

## ⚙️ Install

Expand Down Expand Up @@ -85,6 +85,7 @@ textVide('text-vide', {
type Options = Partial<{
sep: string | string[];
fixationPoint: number;
ignoreHtmlTag: boolean;
}>;
```

Expand Down Expand Up @@ -117,6 +118,17 @@ textVide('text-vide'); // '<b>tex</b>t-<b>vid</b>e'
textVide('text-vide', { fixationPoint: 5 }); // '<b>t</b>ext-<b>v</b>ide'
```

#### `ignoreHtmlTag`<a id="options-ignorehtmltag"></a>

- Default Value: `true`

If this option is `true`, HTML tags are not highlighted.

```ts
textVite('<div>abcd</div>efg'); // '<div><b>abc</b>d</div><b>ef</b>g'
textVite('<div>abcd</div>efg', { ignoreHtmlTag: false }); // '<<b>di</b>v><b>abc</b>d</<b>di</b>v><b>ef</b>g'
```

## License

[MIT](./LICENSE) @Gumball12
59 changes: 57 additions & 2 deletions apps/sandbox/src/App.tsx
Expand Up @@ -19,22 +19,31 @@ type Edits = {
firstSep: string;
secondSep: string;
fixationPoint: string;
ignoreHtmlTag: string;
input: string;
};

const defaultEdits: Edits = {
firstSep: '<b>',
secondSep: '</b>',
fixationPoint: '1',
ignoreHtmlTag: '1', // 1 = true, 0 = false
input: INITIAL_INPUT,
};

const storeEdits = ({ firstSep, secondSep, fixationPoint, input }: Edits) => {
const storeEdits = ({
firstSep,
secondSep,
fixationPoint,
input,
ignoreHtmlTag,
}: Edits) => {
const search = [
`firstSep=${encodeURIComponent(firstSep)}`,
`secondSep=${encodeURIComponent(secondSep)}`,
`fixationPoint=${encodeURIComponent(fixationPoint)}`,
`input=${encodeURIComponent(input)}`,
`ignoreHtmlTag=${encodeURIComponent(ignoreHtmlTag)}`,
].join('&');

// eslint-disable-next-line
Expand Down Expand Up @@ -90,6 +99,7 @@ type Action = {
| 'INPUT'
| 'HIGHLIGHTED_TEXT'
| 'COPIED'
| 'TOGGLE_IGNORE_HTML_TAG'
| 'RESET';
value: string;
copied: boolean;
Expand Down Expand Up @@ -120,6 +130,11 @@ const reducer: Reducer<State, Action> = (state, { type, value, copied }) => {
return { ...state, copiedEffect: copied };
}

if (type === 'TOGGLE_IGNORE_HTML_TAG') {
const nextIgnoreHtmlTag = state.ignoreHtmlTag === '1' ? '0' : '1';
return { ...state, ignoreHtmlTag: nextIgnoreHtmlTag };
}

if (type === 'RESET') {
return {
...defaultEdits,
Expand All @@ -145,13 +160,15 @@ const App = () => {
fixationPoint,
copiedEffect,
highlightedText,
ignoreHtmlTag,
} = state;

useEffect(() => {
const store = setTimeout(() => {
const options = {
sep: [firstSep, secondSep],
fixationPoint: parseInt(fixationPoint),
ignoreHtmlTag: ignoreHtmlTag === '1',
};

const highlightedText = textVide(input, options);
Expand All @@ -167,11 +184,12 @@ const App = () => {
secondSep,
input,
fixationPoint,
ignoreHtmlTag,
});
}, DEBOUNCE_TIMEOUT);

return () => clearTimeout(store);
}, [firstSep, secondSep, input, fixationPoint]);
}, [firstSep, secondSep, input, fixationPoint, ignoreHtmlTag]);

const copyUrl = () => {
const { href: url } = location;
Expand All @@ -198,6 +216,7 @@ const App = () => {
secondSep,
fixationPoint,
input,
ignoreHtmlTag,
});

return (
Expand Down Expand Up @@ -276,6 +295,23 @@ const App = () => {
<ToggleButton value="5">5</ToggleButton>
</ToggleButtonGroup>

<Button
className="!hidden sm:!block"
variant="outlined"
color="success"
onClick={() =>
dispatchState({
type: 'TOGGLE_IGNORE_HTML_TAG',
value: '',
copied: false,
})
}
>
{ignoreHtmlTag === '1'
? 'not ignore html tags'
: 'ignore html tags'}
</Button>

<Button
className="!block sm:!hidden"
variant="outlined"
Expand All @@ -285,6 +321,25 @@ const App = () => {
reset
</Button>
</section>

<section>
<Button
className="!block sm:!hidden"
variant="outlined"
color="success"
onClick={() =>
dispatchState({
type: 'TOGGLE_IGNORE_HTML_TAG',
value: '',
copied: false,
})
}
>
{ignoreHtmlTag === '1'
? 'not ignore html tags'
: 'ignore html tags'}
</Button>
</section>
</section>

<section>
Expand Down
19 changes: 13 additions & 6 deletions packages/text-vide/src/__tests__/getOptions.test.ts
@@ -1,48 +1,55 @@
import { describe, expect, it } from 'vitest';
import getOptions from '../getOptions';
import { Options } from '../types';

describe('test getOptions()', () => {
it('pass empty object', () => {
const expected = {
const expected: Options = {
sep: ['<b>', '</b>'],
fixationPoint: 1,
ignoreHtmlTag: true,
};

expect(getOptions({})).toEqual(expected);
});

it('pass undefined value', () => {
const maybeOptions = {
const undefinedOptionValues = {
sep: undefined,
fixationPoint: undefined,
ignoreHtmlTag: undefined,
};

const expected = {
const expected: Options = {
sep: ['<b>', '</b>'],
fixationPoint: 1,
ignoreHtmlTag: true,
};

expect(getOptions(maybeOptions)).toEqual(expected);
expect(getOptions(undefinedOptionValues)).toEqual(expected);
});

it('pass empty string value', () => {
const maybeOptions = {
sep: ['', ''],
fixationPoint: undefined,
ignoreHtmlTag: undefined,
};

const expected = {
const expected: Options = {
sep: ['', ''],
fixationPoint: 1,
ignoreHtmlTag: true,
};

expect(getOptions(maybeOptions)).toEqual(expected);
});

it('pass valid value', () => {
const expected = {
const expected: Options = {
sep: ['a', 'b'],
fixationPoint: 0, // but it's okay
ignoreHtmlTag: false,
};

expect(getOptions(expected)).toEqual(expected);
Expand Down
92 changes: 84 additions & 8 deletions packages/text-vide/src/__tests__/index.test.ts
Expand Up @@ -226,48 +226,124 @@ describe('numbers', () => {
it('1234567890', () => {
const text = '1234567890';
const expected = '1234567890';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('1234-567890', () => {
const text = '1234-567890';
const expected = '1234-567890';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('a1234567890', () => {
const text = 'a1234567890';
const expected = '<b>a12345678</b>90';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('1234567890a', () => {
const text = '1234567890a';
const expected = '<b>123456789</b>0a';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('1234a567890', () => {
const text = '1234a567890';
const expected = '<b>1234a5678</b>90';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('@1234567890', () => {
const text = '@1234567890';
const expected = '@1234567890';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('1234567890@', () => {
const text = '1234567890@';
const expected = '1234567890@';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});

it('1234@567890', () => {
const text = '1234@567890';
const expected = '1234@567890';
expect(textVide(text), expected);
expect(textVide(text)).toBe(expected);
});
});

describe('with html tags', () => {
it('normal text', () => {
const text = 'abcdefg';
const expected = '<b>abcde</b>fg';
expect(textVide(text)).toBe(expected);
});

it('with a tag', () => {
const text = '<a>abcd</a>efg';
const expected = '<a><b>abc</b>d</a><b>ef</b>g';
expect(textVide(text)).toBe(expected);
});

it('with b tag', () => {
const text = '<b>abcd</b>efg';
const expected = '<b><b>abc</b>d</b><b>ef</b>g';
expect(textVide(text)).toBe(expected);
});

it('with div tag', () => {
const text = '<div>abcd</div>efg';
const expected = '<div><b>abc</b>d</div><b>ef</b>g';
expect(textVide(text)).toBe(expected);
});

it('complex html tags', () => {
const text = `<div class="bionic-reader-container">
<span class="w bionic"><b class="b bionic">nor</b>mal </span><span class="w bionic"><b class="b bionic">te</b>xt</span>: <span class="w bionic"><b class="b bionic">abcd</b>efg</span><br><span class="w bionic"><b class="b bionic">wi</b>th </span><span class="w bionic"><b class="b bionic">a</b> </span><span class="w bionic"><b class="b bionic">t</b>ag</span>: <a target="_blank"><span class="w bionic"><b class="b bionic">ab</b>cd</span></a><span class="w bionic"><b class="b bionic">e</b>fg</span><br><span class="w bionic"><b class="b bionic">wi</b>th </span><span class="w bionic"><b class="b bionic">b</b> </span><span class="w bionic"><b class="b bionic">t</b>ag</span>: <b><span class="w bionic"><b class="b bionic">ab</b>cd</span></b><span class="w bionic"><b class="b bionic">e</b>fg</span><br><span class="w bionic"><b class="b bionic">wi</b>th </span><span class="w bionic"><b class="b bionic">d</b>iv </span><span class="w bionic"><b class="b bionic">t</b>ag</span>: <div><span class="w bionic"><b class="b bionic">ab</b>cd</span></div><span class="w bionic"><b class="b bionic">e</b>fg</span><br>
<!-- <div class="br-foot-node">
<p style="margin: 32px 0 32px 70px; font-weight: 700; font-size: 26px; line-height: 1.6em;">
</p>
<p>
Bionic Reading<sup>®</sup><br>
A higher dimension of reading.<br>
<a href="https://bionic-reading.com">bionic-reading.com</a>
</p>
<br/>
<br/>
<p>
</p>
</div> -->
</div>`;

const expected = `<div class="bionic-reader-container">
<span class="w bionic"><b class="b bionic"><b>no</b>r</b><b>ma</b>l </span><span class="w bionic"><b class="b bionic"><b>t</b>e</b><b>x</b>t</span>: <span class="w bionic"><b class="b bionic"><b>abc</b>d</b><b>ef</b>g</span><br><span class="w bionic"><b class="b bionic"><b>w</b>i</b><b>t</b>h </span><span class="w bionic"><b class="b bionic">a</b> </span><span class="w bionic"><b class="b bionic">t</b><b>a</b>g</span>: <a target="_blank"><span class="w bionic"><b class="b bionic"><b>a</b>b</b><b>c</b>d</span></a><span class="w bionic"><b class="b bionic">e</b><b>f</b>g</span><br><span class="w bionic"><b class="b bionic"><b>w</b>i</b><b>t</b>h </span><span class="w bionic"><b class="b bionic">b</b> </span><span class="w bionic"><b class="b bionic">t</b><b>a</b>g</span>: <b><span class="w bionic"><b class="b bionic"><b>a</b>b</b><b>c</b>d</span></b><span class="w bionic"><b class="b bionic">e</b><b>f</b>g</span><br><span class="w bionic"><b class="b bionic"><b>w</b>i</b><b>t</b>h </span><span class="w bionic"><b class="b bionic">d</b><b>i</b>v </span><span class="w bionic"><b class="b bionic">t</b><b>a</b>g</span>: <div><span class="w bionic"><b class="b bionic"><b>a</b>b</b><b>c</b>d</span></div><span class="w bionic"><b class="b bionic">e</b><b>f</b>g</span><br>
<!-- <div class="br-foot-node">
<p style="margin: 32px 0 32px 70px; font-weight: 700; font-size: 26px; line-height: 1.6em;">
</p>
<p>
Bionic Reading<sup>®</sup><br>
A higher dimension of reading.<br>
<a href="https://bionic-reading.com">bionic-reading.com</a>
</p>
<br/>
<br/>
<p>
</p>
</div> -->
</div>`;

expect(textVide(text)).toBe(expected);
});
});
2 changes: 2 additions & 0 deletions packages/text-vide/src/getOptions.ts
Expand Up @@ -3,9 +3,11 @@ import defaults from 'utils/defaults';

const DEFAULT_SEP = ['<b>', '</b>'];
const DEFAULT_FIXATION_POINT = 1;
const DEFAULT_IGNORE_HTML_TAG = true;

export default (maybeOptions: Partial<Options>): Options =>
defaults(maybeOptions, {
sep: DEFAULT_SEP,
fixationPoint: DEFAULT_FIXATION_POINT,
ignoreHtmlTag: DEFAULT_IGNORE_HTML_TAG,
});

0 comments on commit c209f8c

Please sign in to comment.