GithubHelp home page GithubHelp logo

cojoclaudiu / highlight-words Goto Github PK

View Code? Open in Web Editor NEW

This project forked from tricinel/highlight-words

0.0 0.0 0.0 1.59 MB

Split a piece text into multiple chunks based on a search query, allowing you to highlight the matches afterwards.

License: MIT License

JavaScript 6.27% TypeScript 92.21% Shell 1.52%

highlight-words's Introduction

Give it a piece of text and a search query, and it splits it into chunks separating matches from non-matches, allowing you to highlight the matches, visually or otherwise, in your app.

Build status Node Version Npm version Npm downloads License

Installation

yarn add highlight-words
npm i --save highlight-words

Usage

To use it, give it the body of text to search in and the query to search for.

import highlightWords from 'highlight-words';

const chunks = highlightWords({
  text: 'The quick brown fox jumped over the lazy dog',
  query: 'over'
});

console.log(chunks);
/*
[
  {
    key: '62acb210-76dd-4682-b948-8d359a966dcb'
    text: 'The brown fox jumped ',
    match: false
  },
  {
    key: '69779adf-6d7c-45ec-ae9b-49d0cb292e28';
    text: 'over',
    match: true
  },
  {
    key: '46c5b7a0-5414-47c5-81ba-2496f33fe2f6';
    text: ' the lazy dog',
    match: false
  }
]
*/

Play with this example on Code Sandbox.

Alternatively, you can also use a regular expression as part of the query string to search for.

const chunks = highlightWords({
  text: 'The quick brown fox jumped over the lazy dog',
  query: '/(quick|brown|fox)/'
});

console.log(chunks);
/*
[
  {
    key: '62acb210-76dd-4682-b948-8d359a966dcb'
    text: 'The ',
    match: false
  },
  {
    key: '69779adf-6d7c-45ec-ae9b-49d0cb292e28'
    text: 'quick',
    match: true
  },
  {
    key: 'a72a6578-9111-4dca-a30d-676aaf7964c0'
    text: ' ',
    match: false
  },
  {
    key: '24301852-f38b-4b54-b1fe-d8a82f47c49e'
    text: 'brown',
    match: true
  },
  {
    key: 'a72a6578-9111-4dca-a30d-676aaf7964c0'
    text: ' ',
    match: false
  },
  {
    key: '797b3bab-9244-451c-b246-4b03025b0691'
    text: 'fox',
    match: true
  },
  {
    key: 'c86dbb8a-3e5f-4c05-a48c-684abbb517e8'
    text: ' jumped over the lazy dog',
    match: false
  }
]
*/

If using a regular expresssion, you can choose to either enclose the pattern in a string or not. In both cases, you need to format the regular expression properly, i.e. enclose the pattern between slashes, and you need to create capture groups, so that the match is remembered for later use.

Valid regular expression usage

query: '/(quick|brown|fox)/'
query: /(quick|brown|fox)/

Invalid regular expression usage

query: '(quick|brown|fox)'
query: '/quick|brown|fox/'
query: /quick|brown|fox/

Options

You can add a few options for the highlighter.

  • clipBy. If you want to clip the occurences that are not a match and display elipses around them. This can help to provide context around your matches.
  • matchExactly. By default, the highlighter will look for occurences of either words in your query. For example, if you have brown fox as your query, the highlighter will consider both brown and fox as separate matches. If set to true, then only the exact match of brown fox will be considered.

matchExactly will have no effect if you're using a regular expression as your query, since you will have full control over the query in that case.

Arguments

highlightWords accepts an object as an argument, with the following structure:

Property Type Required? Description Default
text String โœ“ The body of text you want to search in. empty
query String โœ“ The word(s) or regular expression you want to search for. empty
clipBy Number How many words do you want to clip from the non matches. null
matchExactly Boolean Should we match the complete query or individual words in it? false

What it returns

highlightWords returns an array of objects, each object with the following structure:

Property Type Description
key String A unique key to help you when you want to use the chunks in a map function, e.g. with React or Angular.
text String The word or words in the chunk.
match Boolean Is this chunk a match for your search?

Use it with the framework of your choice

By default, the highlighter won't assume any HTML element to wrap matched text, so you can do whatever you want with the matches.

React

<p>
  {chunks.map(({ text, match, key }) =>
    match ? (
      <span className="highlight" key={key}>
        {text}
      </span>
    ) : (
      <span key={key}>{text}</span>
    )
  )}
  };
</p>

Play with the React example on Code Sandbox.

Angular

<p>
  <span *ngFor="let chunk of chunks; trackBy: key" class="highlight">
    {{ chunk.text }}
  </span>
</p>

Play with the Angular example on Code Sandbox.

Vue

<p>
  <span
    v-for="chunk in chunks"
    :key="chunk.key"
    v-bind:class="{ active: chunk.match }"
  >
    {{ chunk.text }}
  </span>
</p>

Play with the Vue example on Code Sandbox.

Svelte

<p>
  {#each chunks as chunk (chunk.key)}
  <span class:highlight="{chunk.match}">{chunk.text}</span>
  {/each}
</p>

Play with the Svelte example on Code Sandbox.

A note on accessibility

When we are splitting a piece of text into multiple chunks for the purpose of styling each chunk differently, and then using said chunks instead of the original text, we are doing a disservice to our users who might rely on a screen reader. This is because some screen readers will read out the chunks of text individually rather than in one continous flow. For example, if we were to split the text Eeeh! Help me!, highlight-words will return to us several chunks. We then might decide to wrap each chunk's text in a span, like so:

<p>
  <span>E</span>
  <span>e</span>
  <span>e</span>
  <span>h! H</span>
  <span>e</span>
  <span>lp m</span>
  <span>e</span>
  <span>!</span>
</p>

Some screen readers will announce each letter e individually. Not ideal!

Let's make it accessible by using aria attributes to allow screen readers to correctly announce our text.

<p aria-label="Eeeh! Help me!">
  <span aria-hidden="true">E</span>
  <span aria-hidden="true">e</span>
  <span aria-hidden="true">e</span>
  <span aria-hidden="true">h! H</span>
  <span aria-hidden="true">e</span>
  <span aria-hidden="true">lp m</span>
  <span aria-hidden="true">e</span>
  <span aria-hidden="true">!</span>
</p>

or, for less repetition:

<p aria-label="Eeeh! Help me!">
  <span aria-hidden="true">
    <span>E</span>
    <span>e</span>
    <span>e</span>
    <span>h! H</span>
    <span>e</span>
    <span>lp m</span>
    <span>e</span>
    <span>!</span>
  </span>
</p>

For a much better write-up than I could put together, have a read of Michelle Barker's How to Accessibly Split Text.

License

MIT License - fork, modify and use however you want.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.