From ff638eb0105a22780d5084da58da83c98dc6d324 Mon Sep 17 00:00:00 2001 From: innovaker <66737976+innovaker@users.noreply.github.com> Date: Fri, 6 Nov 2020 19:42:54 +0000 Subject: docs(codes): Add (key) codes documentation Create codes documentation for standardized keys. Closes #218. Fixes #308. Ref #21. --- docs/src/components/codes/Context.jsx | 17 +++++ docs/src/components/codes/Description.jsx | 51 ++++++++++++++ docs/src/components/codes/Footnote.jsx | 23 +++++++ docs/src/components/codes/FootnoteRef.jsx | 22 ++++++ docs/src/components/codes/FootnoteRefs.jsx | 43 ++++++++++++ docs/src/components/codes/Footnotes.jsx | 30 ++++++++ docs/src/components/codes/LinkIcon.jsx | 14 ++++ docs/src/components/codes/Name.jsx | 25 +++++++ docs/src/components/codes/OsLegend.jsx | 23 +++++++ docs/src/components/codes/OsSupport.jsx | 26 +++++++ docs/src/components/codes/OsSupportIcon.jsx | 51 ++++++++++++++ docs/src/components/codes/Table.jsx | 80 ++++++++++++++++++++++ docs/src/components/codes/TableRow.jsx | 70 +++++++++++++++++++ docs/src/components/codes/ToastyContainer.jsx | 22 ++++++ .../src/components/codes/ToastyCopyToClipboard.jsx | 30 ++++++++ 15 files changed, 527 insertions(+) create mode 100644 docs/src/components/codes/Context.jsx create mode 100644 docs/src/components/codes/Description.jsx create mode 100644 docs/src/components/codes/Footnote.jsx create mode 100644 docs/src/components/codes/FootnoteRef.jsx create mode 100644 docs/src/components/codes/FootnoteRefs.jsx create mode 100644 docs/src/components/codes/Footnotes.jsx create mode 100644 docs/src/components/codes/LinkIcon.jsx create mode 100644 docs/src/components/codes/Name.jsx create mode 100644 docs/src/components/codes/OsLegend.jsx create mode 100644 docs/src/components/codes/OsSupport.jsx create mode 100644 docs/src/components/codes/OsSupportIcon.jsx create mode 100644 docs/src/components/codes/Table.jsx create mode 100644 docs/src/components/codes/TableRow.jsx create mode 100644 docs/src/components/codes/ToastyContainer.jsx create mode 100644 docs/src/components/codes/ToastyCopyToClipboard.jsx (limited to 'docs/src/components/codes') diff --git a/docs/src/components/codes/Context.jsx b/docs/src/components/codes/Context.jsx new file mode 100644 index 0000000..4fdcbfc --- /dev/null +++ b/docs/src/components/codes/Context.jsx @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +export default function Context({ children }) { + return

{children}

; +} + +Context.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, +}; diff --git a/docs/src/components/codes/Description.jsx b/docs/src/components/codes/Description.jsx new file mode 100644 index 0000000..6d8c5f6 --- /dev/null +++ b/docs/src/components/codes/Description.jsx @@ -0,0 +1,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( + + {description.substr(index + pos, chars.length)} + {meaning ? {meaning} : undefined} + + ); + lastIndex = index + str.length; + return acc; + }, []); + if (lastIndex < description.length) { + parts.push(description.substr(lastIndex)); + } + return parts; +} + +export default function Description({ description = "" }) { + return ( + {renderSpecialCharacters(description)} + ); +} + +Description.propTypes = { + description: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/Footnote.jsx b/docs/src/components/codes/Footnote.jsx new file mode 100644 index 0000000..c9396a3 --- /dev/null +++ b/docs/src/components/codes/Footnote.jsx @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +export default function Footnote({ children, symbol, id }) { + return ( +
+
{symbol}
+
{children}
+
+ ); +} + +Footnote.propTypes = { + children: PropTypes.element.isRequired, + symbol: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + id: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/FootnoteRef.jsx b/docs/src/components/codes/FootnoteRef.jsx new file mode 100644 index 0000000..c7b11a7 --- /dev/null +++ b/docs/src/components/codes/FootnoteRef.jsx @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +export default function FootnoteRef({ children, anchor }) { + return ( + + {children} + + ); +} + +FootnoteRef.propTypes = { + children: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) + .isRequired, + anchor: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/FootnoteRefs.jsx b/docs/src/components/codes/FootnoteRefs.jsx new file mode 100644 index 0000000..3782c13 --- /dev/null +++ b/docs/src/components/codes/FootnoteRefs.jsx @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import FootnoteRef from "./FootnoteRef"; + +function joinReactElements(arr, delimiter) { + return arr.reduce((acc, fragment) => { + if (acc === null) { + return fragment; + } + return ( + <> + {acc} + {delimiter} + {fragment} + + ); + }, null); +} + +export default function FootnoteRefs({ footnotes }) { + return ( + + {joinReactElements( + footnotes.map((footnote) => ( + + {footnote.symbol} + + )), + ", " + )} + + ); +} + +FootnoteRefs.propTypes = { + footnotes: PropTypes.array.isRequired, +}; diff --git a/docs/src/components/codes/Footnotes.jsx b/docs/src/components/codes/Footnotes.jsx new file mode 100644 index 0000000..b382141 --- /dev/null +++ b/docs/src/components/codes/Footnotes.jsx @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import Footnote from "./Footnote"; + +export default function Footnotes({ footnotes = [], id }) { + return ( +
+ +
Notes
+
+ {footnotes.map((footnote) => ( + + {footnote.value} + + ))} +
+
+ ); +} + +Footnotes.propTypes = { + footnotes: PropTypes.array.isRequired, + id: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/LinkIcon.jsx b/docs/src/components/codes/LinkIcon.jsx new file mode 100644 index 0000000..5bfeebd --- /dev/null +++ b/docs/src/components/codes/LinkIcon.jsx @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; +export default function LinkIcon() { + return ; +} + +LinkIcon.propTypes = {}; diff --git a/docs/src/components/codes/Name.jsx b/docs/src/components/codes/Name.jsx new file mode 100644 index 0000000..52dc734 --- /dev/null +++ b/docs/src/components/codes/Name.jsx @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import ToastyCopyToClipboard from "./ToastyCopyToClipboard"; + +export default function Name({ children, name }) { + return ( + + + {children} + + + ); +} + +Name.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, + name: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/OsLegend.jsx b/docs/src/components/codes/OsLegend.jsx new file mode 100644 index 0000000..c53907f --- /dev/null +++ b/docs/src/components/codes/OsLegend.jsx @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import operatingSystems from "@site/src/data/operating-systems"; + +export default function OsLegend() { + return ( +
+ {operatingSystems.map(({ key, className, heading, title }) => ( +
+ {heading} + {title} +
+ ))} +
+ ); +} + +OsLegend.propTypes = {}; diff --git a/docs/src/components/codes/OsSupport.jsx b/docs/src/components/codes/OsSupport.jsx new file mode 100644 index 0000000..2cb60c9 --- /dev/null +++ b/docs/src/components/codes/OsSupport.jsx @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import OsSupportIcon from "./OsSupportIcon"; +import FootnoteRefs from "./FootnoteRefs"; + +export default function OsSupport({ value, footnotes = [] }) { + return ( + <> + + {footnotes.length > 0 ? ( + + ) : undefined} + + ); +} + +OsSupport.propTypes = { + value: PropTypes.oneOf([true, false, null]), + footnotes: PropTypes.array.isRequired, +}; diff --git a/docs/src/components/codes/OsSupportIcon.jsx b/docs/src/components/codes/OsSupportIcon.jsx new file mode 100644 index 0000000..a518d62 --- /dev/null +++ b/docs/src/components/codes/OsSupportIcon.jsx @@ -0,0 +1,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 Icon = ({ children, className, title }) => ( + + {children} + +); + +Icon.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, + className: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, +}; + +export const Supported = () => ( + + ⭐ + +); +export const NotSupported = () => ( + + ❌ + +); +export const NotTested = () => ( + + ❔ + +); + +export default function OsSupportIcon({ value }) { + if (value === true) { + return ; + } + if (value === false) { + return ; + } + return ; +} + +OsSupportIcon.propTypes = { + value: PropTypes.oneOf([true, false, null]), +}; diff --git a/docs/src/components/codes/Table.jsx b/docs/src/components/codes/Table.jsx new file mode 100644 index 0000000..c7dd20c --- /dev/null +++ b/docs/src/components/codes/Table.jsx @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import TableRow from "./TableRow"; +import Footnotes from "./Footnotes"; +import LinkIcon from "./LinkIcon"; +import operatingSystems from "@site/src/data/operating-systems"; +import { getCodes } from "@site/src/hid"; +import { getGroup } from "@site/src/groups"; +import { getFootnote } from "@site/src/footnotes"; + +function extractFootnoteIds(codes) { + return Array.from( + new Set( + codes + .flatMap(({ footnotes }) => Object.values(footnotes)) + .map((refs) => (Array.isArray(refs) ? refs.flat() : refs)) + ) + ); +} + +export default function Table({ group }) { + const codes = getCodes(getGroup(group)); + + const footnotesAnchor = group + "-" + "footnotes"; + + const tableFootnotes = extractFootnoteIds(codes).map((id, i) => { + const Component = getFootnote(id); + return { + id, + anchor: footnotesAnchor, + symbol: i + 1, + value: Component ? : undefined, + }; + }); + + return ( +
+ + + + + + + {operatingSystems.map(({ key, className, heading, title }) => ( + + ))} + + + + {Array.isArray(codes) + ? codes.map((code) => ( + + )) + : undefined} + +
NamesDescription + + + {heading} +
+ {tableFootnotes.length > 0 ? ( + + ) : undefined} +
+ ); +} + +Table.propTypes = { + group: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/TableRow.jsx b/docs/src/components/codes/TableRow.jsx new file mode 100644 index 0000000..a560911 --- /dev/null +++ b/docs/src/components/codes/TableRow.jsx @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import Name from "./Name"; +import Description from "./Description"; +import Context from "./Context"; +import LinkIcon from "./LinkIcon"; +import OsSupport from "./OsSupport"; +import operatingSystems from "@site/src/data/operating-systems"; + +export default function TableRow({ + names, + description, + context = "", + clarify = false, + documentation, + os, + footnotes, + tableFootnotes, +}) { + return ( + + + {names.map((name) => ( + + {name} + + ))} + + + + {clarify && context ? {context} : undefined} + + +
+ + + + {operatingSystems.map(({ key, className, title }) => ( + + + (Array.isArray(footnotes[key]) && + footnotes[key].includes(id)) || + footnotes[key] == id + )} + /> + + ))} + + ); +} + +TableRow.propTypes = { + names: PropTypes.array.isRequired, + description: PropTypes.string.isRequired, + context: PropTypes.string.isRequired, + clarify: PropTypes.bool, + documentation: PropTypes.string.isRequired, + os: PropTypes.object.isRequired, + footnotes: PropTypes.object.isRequired, + tableFootnotes: PropTypes.array.isRequired, +}; diff --git a/docs/src/components/codes/ToastyContainer.jsx b/docs/src/components/codes/ToastyContainer.jsx new file mode 100644 index 0000000..ee4e3bc --- /dev/null +++ b/docs/src/components/codes/ToastyContainer.jsx @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; + +export default function ToastyContainer() { + return ( + + ); +} + +ToastyContainer.propTypes = {}; diff --git a/docs/src/components/codes/ToastyCopyToClipboard.jsx b/docs/src/components/codes/ToastyCopyToClipboard.jsx new file mode 100644 index 0000000..b0e9809 --- /dev/null +++ b/docs/src/components/codes/ToastyCopyToClipboard.jsx @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import { toast } from "react-toastify"; +import { CopyToClipboard } from "react-copy-to-clipboard"; + +export default function ToastyCopyToClipboard({ children, text }) { + const notify = () => + toast( + + 📋 Copied {text} + + ); + return ( +
+ {children} +
+ ); +} + +ToastyCopyToClipboard.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, + text: PropTypes.string.isRequired, +}; -- cgit v1.2.3