summaryrefslogtreecommitdiff
path: root/docs/src/components/codes/Description.jsx
blob: 6d8c5f62b4c8297072b53a3e889d668724592b63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/*
 * Copyright (c) 2020 The ZMK Contributors
 *
 * SPDX-License-Identifier: CC-BY-NC-SA-4.0
 */

import React from "react";
import PropTypes from "prop-types";

const specialCharactersRegex = /(?:^|\s)((?:&(?:(?:\w+)|(?:#\d+));)|[_]|[^\w\s])(?:\s*\[([^[\]]+?)\])/g;

function renderSpecialCharacters(description) {
  const matches = Array.from(description.matchAll(specialCharactersRegex));
  if (matches.length == 0) return description;
  let lastIndex = 0;
  const parts = matches.reduce((acc, match, i) => {
    const { index } = match;
    const str = match[0];
    const chars = match[1];
    const meaning = match[2];
    if (index != lastIndex) {
      acc.push(description.substring(lastIndex, index));
    }
    const pos = str.indexOf(chars);
    if (pos > 0) {
      acc.push(description.substr(index, pos));
    }
    acc.push(
      <span key={i} className="symbol" title={meaning ?? ""}>
        <code>{description.substr(index + pos, chars.length)}</code>
        {meaning ? <span className="meaning">{meaning}</span> : undefined}
      </span>
    );
    lastIndex = index + str.length;
    return acc;
  }, []);
  if (lastIndex < description.length) {
    parts.push(description.substr(lastIndex));
  }
  return parts;
}

export default function Description({ description = "" }) {
  return (
    <span className="description">{renderSpecialCharacters(description)}</span>
  );
}

Description.propTypes = {
  description: PropTypes.string.isRequired,
};