Greums's picture
major improvements to the app
a417977
raw
history blame
6.03 kB
import style from "./style.module.scss";
import {useMemo} from "preact/hooks";
import {smileysMap} from "@/utils/smileys";
// const blocks = {
// text: "text",
// img: "img",
// }
//
// type Segment = {
// type: keyof typeof blocks,
// content: string,
// }
export function Preview(props: {
raw: string,
}) {
const html = useMemo(() => {
const escaped = escapeHtml(props.raw);
return injectHTML(escaped)/*.replace(/\n/g, '<br/>')*/;
}, [props.raw]);
return (
<div className={style.wrapper} dangerouslySetInnerHTML={{__html: html}}/>
)
//
// return (
// <div className={style.wrapper}>
// {segments.map(seg => {
// if (seg.type === blocks.text) {
// return seg.content
// }
//
// if (seg.type === blocks.img) {
// return <img width="68" height="51" alt="noelshak" src={seg.content}/>
// }
// })}
// </div>
// )
}
function quoteReplacer(reg: RegExp, raw: string): string {
// return raw
const match = reg.exec(raw);
reg.lastIndex = 0;
if (!match) return raw;
const index = match.index;
const length = match[0].length;
return quoteReplacer(
reg,
raw.substring(0, index) + `<blockquote>${quoteReplacer(reg, match[0].replace(/^&gt; ?/gm, ""))}</blockquote>` + raw.substring(index + length)
);
}
// WARNING: the order is important
const jvcodeMap: [RegExp, string | ((reg: RegExp, raw: string) => string)][] = [
[ // Quotes
/^&gt;.*(?:\n&gt;.*)*/m,
quoteReplacer
],
[ // Wrap text with paragraphs
/(^|>)([^<]+)($|<)/g,
"$1<p>$2</p>$3"
],
[ // Replace line breaks between <p> tags with <br>
/<p>\s*([\s\S]*?)\s*<\/p>/g,
(reg, raw) => {
// console.log(raw)
return raw.replace(reg, (_, matched) => {
// const randomId = (Math.random() + 1).toString(36).substring(2);
console.log(matched)
return `<p>${matched.replace(/\n/g, "<br/>")}</p>`;
});
}
],
[ // Spoil
/&lt;spoil&gt;(.*?)&lt;\/spoil&gt;/gm,
(reg, raw) => {
return raw.replace(reg, (_, matched) => {
const randomId = (Math.random() + 1).toString(36).substring(2);
return `<span class="bloc-spoil-jv"><input type="checkbox" id="${randomId}" class="open-spoil"><label class="barre-head" for="${randomId}"><span class="txt-spoil">Spoil</span></label><span class="contenu-spoil">${matched}</span></span>`;
});
}
],
[ // Stickers
// /(^|<p>| )https?:\/\/image\.noelshack\.com\/(?:fichiers|minis)([A-z0-9/\-_.]+)/gm,
/(^|<[a-z]+\/?>| )https?:\/\/image\.noelshack\.com\/(?:fichiers|minis)([A-z0-9/\-_.]+)/gm,
"$1<img class=\"sticker\" width=\"68\" height=\"51\" alt=\"sticker\" src=\"https://image.noelshack.com/minis/$2\"/>"
],
[ // Vocaroo
/(^|<[a-z]+\/?>| )https:\/\/vocaroo.com\/(.+)/gm,
"$1<div><iframe width=\"300\" height=\"60\" src=\"https://vocaroo.com/embed/$2?autoplay=0\" frameborder=\"0\" allow=\"autoplay\"></iframe></div>"
],
[ // Regular links
/(^|<[a-z]+\/?>| )(https?:\/\/[-a-zA-Z0-9@:%._/+~#=?&;]+)/gm,
"$1<a href=\"$2\" target=\"_blank\">$2</a>"
],
// TODO: embeded youtube, utiliser le titre du topic pour chercher une vidéo corespondante avec l'API search de youtube
// Generate regexes for smileys
// ...smileysMap.map((maping) => {
// return [new RegExp(
// Object.keys(smileysMap).map(s => (
// "(?:(?:^| )" + s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ")"
// )).join("|"), "gm"
// ), `<img src="${maping[1]}" width="16" height="16" alt=""/>`]
// })
// (() => {
// new RegExp(
// smileysMap.map((mapping) => (
// "(?:(?:^| )" + s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ")"
// )).join("|"), "gm"
// )
// return [/(https?:\/\/image\.noelshack\.com\/\S+)/g, "<img width=\"68\" height=\"51\" alt=\"noelshak\" src=\"$1\"/>"]
// })()
...[...smileysMap].sort((a, b) => b[0].length - a[0].length).map(mapping => { // Sort smileys by length to match :-))) before :-)
return [
new RegExp("(<p>| )" + mapping[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), "gm"),
`$1<img src="https://image.jeuxvideo.com/smileys_img/${mapping[1]}.gif" alt="${mapping[0]}"/>`
];
})
];
function injectHTML(input: string): string {
// console.log("---------------------")
let text = input.slice()
for (const [regex, htmlOrFunc] of jvcodeMap) {
// Reset the regex @see https://stackoverflow.com/a/11477448/5912637
regex.lastIndex = 0;
// const regex = new RegExp(bbCode, 'gi');
// console.log(regex, html, input)
if (htmlOrFunc instanceof Function) {
text = htmlOrFunc(regex, text);
} else {
// console.log(regex)
// console.log(text)
text = text.replace(regex, htmlOrFunc as string);
}
}
// console.log(input)
return text;
}
function escapeHtml(unsafe: string): string {
// unsafe.re
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// function parseRaw(raw: string): Segment[] {
// // Regex pour capturer les URLs (HTTP, HTTPS)
// const urlRegex = /(https?:\/\/[^\s]+)/g;
//
// // Découper le texte en utilisant la regex, en gardant les URLs comme blocs séparés
// return raw.split(urlRegex).filter(seg => seg !== "").map(seg => {
// return {
// type: seg.includes(".png") || seg.includes(".jpg") ? blocks.img : blocks.text,
// content: seg,
// }
// });
// }