mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-14 00:01:03 +00:00
bf00412863
In the touch shell the back, forward, disclosure, date-range and flow arrows kept pointing right in Arabic, so Settle up showed the debt the wrong way round and Vacay's year arrows pointed inward. The shell now mirrors lucide's direction arrows in right-to-left languages; an icon that names its own treatment keeps it, and the lightbox arrows stay on their physical sides. Latin user text in Arabic rows lost its beginning when cut and moved its punctuation to the wrong end. Names, titles, addresses and file names take their direction from their own text (dir=auto) and still line up with the row; markdown paragraphs, chat messages, poll options and journal stories are isolated; signed balances, amounts, sizes, rates and leg figures read as one left-to-right run; URL fields read left to right. Name pairs joined by an arrow isolate each name and point from the first to the second. The hero progress and poll result bars fill from the start edge. Arabic and Hebrew uppercase caption labels grow a step and take the muted ink, and a todo's due date in a notification is written in the reader's language instead of as YYYY-MM-DD.
82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import type { Components, Options } from 'react-markdown'
|
|
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize'
|
|
|
|
type HastNode = { type: string; children?: HastNode[] }
|
|
|
|
/**
|
|
* react-markdown never builds an element out of raw HTML, it shows the markup
|
|
* verbatim instead. It does that after the rehype plugins ran, though, so the
|
|
* sanitizer gets the raw nodes first and drops them without a trace: a note
|
|
* reading "Zimmernummer <TBD>" loses the placeholder on screen while the stored
|
|
* text still has it (#2177). Turning raw into text up front keeps it readable
|
|
* and still yields no element.
|
|
*/
|
|
function rehypeRawAsText() {
|
|
return (tree: HastNode) => {
|
|
const walk = (node: HastNode) => {
|
|
if (node.type === 'raw') node.type = 'text'
|
|
for (const child of node.children || []) walk(child)
|
|
}
|
|
walk(tree)
|
|
}
|
|
}
|
|
|
|
// remark-gfm already writes footnote ids with the `user-content-` prefix, and
|
|
// the hrefs pointing at them carry it too. Clobbering them a second time only
|
|
// makes target and reference disagree.
|
|
const schema = { ...defaultSchema, clobberPrefix: '' }
|
|
|
|
export const sanitizedMarkdownPlugins: NonNullable<Options['rehypePlugins']> = [
|
|
rehypeRawAsText,
|
|
[rehypeSanitize, schema],
|
|
]
|
|
|
|
/**
|
|
* A paragraph or heading of user text runs in its own direction: a Latin note
|
|
* in the Arabic UI keeps its question mark and full stop at its end (and an
|
|
* Arabic one in an English UI), while the block keeps the alignment of the page
|
|
* around it. The isolate is inline, so the block itself stays as it was.
|
|
*/
|
|
export const isolatedTextBlocks: Components = {
|
|
p: ({ children }) => (
|
|
<p>
|
|
<bdi>{children}</bdi>
|
|
</p>
|
|
),
|
|
h1: ({ children }) => (
|
|
<h1>
|
|
<bdi>{children}</bdi>
|
|
</h1>
|
|
),
|
|
h2: ({ children }) => (
|
|
<h2>
|
|
<bdi>{children}</bdi>
|
|
</h2>
|
|
),
|
|
h3: ({ children }) => (
|
|
<h3>
|
|
<bdi>{children}</bdi>
|
|
</h3>
|
|
),
|
|
}
|
|
|
|
/**
|
|
* Links as in markdownLinkComponents (#1629): own tab plus `rel` protection.
|
|
* The exception is a footnote or heading link, which points inside the text
|
|
* that is already on screen, so opening a tab for it would only reload the trip
|
|
* somewhere else.
|
|
*/
|
|
export const sanitizedMarkdownComponents: Components = {
|
|
...isolatedTextBlocks,
|
|
a: ({ children, href, ...rest }) =>
|
|
href?.startsWith('#') ? (
|
|
<a {...rest} href={href}>
|
|
{children}
|
|
</a>
|
|
) : (
|
|
<a {...rest} href={href} target="_blank" rel="noopener noreferrer nofollow">
|
|
{children}
|
|
</a>
|
|
),
|
|
}
|