import React, { Component, PureComponent } from 'react';
import { format_time, Time, TitleLine } from './infrastructure/widgets';
import HtmlToReact from 'html-to-react';
import './Common.css';
import {
URL_PID_RE,
URL_RE,
PID_RE,
NICKNAME_RE,
TAG_RE,
split_text,
} from './text_splitter';
import { save_config } from './Config';
import renderMd from './Markdown';
export { format_time, Time, TitleLine };
export const API_BASE = '/_api/v1';
// https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
function escape_regex(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function is_video(s) {
try {
let url = new URL(s);
return (
url.pathname.endsWith('.mp4') ||
url.pathname.endsWith('.mov') ||
(url.searchParams.get('filetype') || '').startsWith('video/')
);
} catch (e) {
return false;
}
}
export function build_highlight_re(
txt,
split = ' ',
option = 'g',
isRegex = false,
) {
if (isRegex) {
try {
return new RegExp('(' + txt.slice(1, -1) + ')', option);
} catch (e) {
return /^$/g;
}
} else {
return txt
? new RegExp(
`(${txt
.split(split)
.filter((x) => !!x)
.map(escape_regex)
.join('|')})`,
option,
)
: /^$/g;
}
}
export function ColoredSpan(props) {
return (
{props.children}
);
}
function normalize_url(url) {
return /^https?:\/\//.test(url) ? url : 'http://' + url;
}
function stop_loading(e) {
e.target.parentNode.classList.remove('loading');
}
// props: text, show_pid, color_picker, search_param
export class HighlightedMarkdown extends Component {
render() {
const props = this.props;
const processDefs = new HtmlToReact.ProcessNodeDefinitions(React);
const processInstructions = [
{
shouldProcessNode: (node) => /^h[123456]$/.test(node.name),
processNode(node, children, index) {
let currentLevel = +node.name[1];
if (currentLevel < 3) currentLevel = 3;
const HeadingTag = `h${currentLevel}`;
return
);
},
},
{
shouldProcessNode: (node) => node.name === 'a',
processNode(node, children, index) {
return (
{children}
);
},
},
{
shouldProcessNode(node) {
return (
node.type === 'text' &&
(!node.parent ||
!node.parent.attribs ||
node.parent.attribs['encoding'] !== 'application/x-tex')
); // pid, nickname, search
},
processNode(node, children, index) {
const originalText = node.data;
let rules = [
['url_pid', URL_PID_RE],
['url', URL_RE],
['pid', PID_RE],
['nickname', NICKNAME_RE],
['tag', TAG_RE],
];
if (props.search_param) {
let search_kws = props.search_param.split(' ').filter((s) => !!s);
rules.push([
'search',
new RegExp(
`(${search_kws
.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.join('|')})`,
'g',
),
]);
}
const splitted = split_text(originalText, rules);
return (