feat: publish Regex Tools 0.2.0
This commit is contained in:
@@ -1,30 +1,44 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { ECMASCRIPT_REFERENCE } from "../regex/reference/token-reference";
|
||||
import type { RegexFlavourId } from "../regex/model/flavour";
|
||||
import {
|
||||
ECMASCRIPT_REFERENCE,
|
||||
PCRE2_REFERENCE,
|
||||
} from "../regex/reference/token-reference";
|
||||
|
||||
export function QuickReference({
|
||||
onInsert,
|
||||
onUsePattern,
|
||||
onClose,
|
||||
flavour = "ecmascript",
|
||||
}: {
|
||||
readonly onInsert: (syntax: string) => void;
|
||||
readonly onUsePattern: (syntax: string) => void;
|
||||
readonly onClose?: () => void;
|
||||
readonly flavour?: RegexFlavourId;
|
||||
}) {
|
||||
const [query, setQuery] = useState("");
|
||||
const reference =
|
||||
flavour === "pcre2" ? PCRE2_REFERENCE : ECMASCRIPT_REFERENCE;
|
||||
const entries = useMemo(() => {
|
||||
const needle = query.toLocaleLowerCase();
|
||||
const normalizeSearchText = (value: string) =>
|
||||
value
|
||||
.toLocaleLowerCase()
|
||||
.replaceAll(/[^\p{L}\p{N}]+/gu, " ")
|
||||
.trim();
|
||||
const needle = normalizeSearchText(query);
|
||||
return needle
|
||||
? ECMASCRIPT_REFERENCE.filter((entry) =>
|
||||
[
|
||||
entry.construct,
|
||||
entry.syntax,
|
||||
entry.explanation,
|
||||
entry.example,
|
||||
entry.flags.join(" "),
|
||||
entry.source,
|
||||
]
|
||||
.join(" ")
|
||||
.toLocaleLowerCase()
|
||||
.includes(needle),
|
||||
? reference.filter((entry) =>
|
||||
normalizeSearchText(
|
||||
[
|
||||
entry.construct,
|
||||
entry.syntax,
|
||||
entry.explanation,
|
||||
entry.example,
|
||||
entry.flags.join(" "),
|
||||
entry.source,
|
||||
].join(" "),
|
||||
).includes(needle),
|
||||
)
|
||||
: ECMASCRIPT_REFERENCE;
|
||||
}, [query]);
|
||||
: reference;
|
||||
}, [query, reference]);
|
||||
return (
|
||||
<section
|
||||
className="panel reference-panel"
|
||||
@@ -32,9 +46,27 @@ export function QuickReference({
|
||||
>
|
||||
<header className="panel-heading">
|
||||
<div>
|
||||
<p className="eyebrow">Original ECMAScript reference</p>
|
||||
<p className="eyebrow">
|
||||
Original {flavour === "pcre2" ? "PCRE2" : "ECMAScript"} reference
|
||||
</p>
|
||||
<h2 id="reference-heading">Quick reference</h2>
|
||||
</div>
|
||||
<div className="panel-heading-actions">
|
||||
<span>
|
||||
{entries.length} of {reference.length} constructs
|
||||
</span>
|
||||
{onClose ? (
|
||||
<button
|
||||
type="button"
|
||||
className="icon-button"
|
||||
aria-label="Close quick reference"
|
||||
data-dialog-initial-focus
|
||||
onClick={onClose}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</header>
|
||||
<label className="stacked-control">
|
||||
<span>Filter constructs</span>
|
||||
@@ -44,51 +76,57 @@ export function QuickReference({
|
||||
onChange={(event) => setQuery(event.target.value)}
|
||||
/>
|
||||
</label>
|
||||
<ul className="reference-list">
|
||||
{entries.map((entry) => (
|
||||
<li key={entry.id}>
|
||||
<div>
|
||||
<strong>{entry.construct}</strong>
|
||||
<code>{entry.syntax}</code>
|
||||
</div>
|
||||
<p>{entry.explanation}</p>
|
||||
<dl className="reference-meta">
|
||||
{entries.length > 0 ? (
|
||||
<ul className="reference-list">
|
||||
{entries.map((entry) => (
|
||||
<li key={entry.id}>
|
||||
<div>
|
||||
<dt>Flavour</dt>
|
||||
<dd>{entry.flavours.join(", ")}</dd>
|
||||
<strong>{entry.construct}</strong>
|
||||
<code>{entry.syntax}</code>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Relevant flags</dt>
|
||||
<dd>
|
||||
{entry.flags.length > 0 ? entry.flags.join(", ") : "None"}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Example</dt>
|
||||
<dd>
|
||||
<code>{entry.example}</code>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Source</dt>
|
||||
<dd>
|
||||
<a href={entry.sourceUrl} target="_blank" rel="noreferrer">
|
||||
{entry.source}
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{entry.caveat ? <small>{entry.caveat}</small> : null}
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button"
|
||||
onClick={() => onInsert(entry.example)}
|
||||
>
|
||||
Insert example
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<p>{entry.explanation}</p>
|
||||
<dl className="reference-meta">
|
||||
<div>
|
||||
<dt>Flavour</dt>
|
||||
<dd>{entry.flavours.join(", ")}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Relevant flags</dt>
|
||||
<dd>
|
||||
{entry.flags.length > 0 ? entry.flags.join(", ") : "None"}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Example</dt>
|
||||
<dd>
|
||||
<code>{entry.example}</code>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Source</dt>
|
||||
<dd>
|
||||
<a href={entry.sourceUrl} target="_blank" rel="noreferrer">
|
||||
{entry.source}
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{entry.caveat ? <small>{entry.caveat}</small> : null}
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button"
|
||||
onClick={() => onUsePattern(entry.example)}
|
||||
>
|
||||
Use example as pattern
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="empty-state" role="status">
|
||||
No reference constructs match “{query.trim()}”.
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user