Changes to importer.scroll.pub

ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated index.scroll
index.scroll
Changed around line 1
- scrollVersionLink
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated index.scroll
index.scroll
Changed around line 1
+ scrollVersionLink
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated index.scroll
index.scroll
Changed around line 1
- editButton
+ editButton /edit.html
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated index.scroll
index.scroll
Changed around line 1
+ editButton
Breck Yunits
Breck Yunits
2 months ago
latex.js
Changed around line 1
- section: "# ",
- subsection: "## ",
- subsubsection: "### ",
- paragraph: "*",
- begin: {
- itemize: "- ",
- enumerate: "1. ",
- quote: "> ",
- verbatim: "code\n",
- center: "center\n",
- figure: "figure\n",
- },
+ 'section': '# ',
+ 'subsection': '## ',
+ 'subsubsection': '### ',
+ 'paragraph': '*',
+ 'begin': {
+ 'itemize': '- ',
+ 'enumerate': '1. ',
+ 'quote': '> ',
+ 'verbatim': 'code\n',
+ 'center': 'center\n',
+ 'figure': 'figure\n',
+ }
- textbf: "*",
- textit: "_",
- texttt: "`",
- emph: "_",
- href: "link",
+ 'textbf': '*',
+ 'textit': '_',
+ 'texttt': '`',
+ 'emph': '_',
+ 'href': 'link'
-
+
- scroll = scroll.replace(/%.*$/gm, "");
-
+ scroll = scroll.replace(/%.*$/gm, '');
+
+ // Handle \input commands first
+ scroll = this.convertInputCommands(scroll);
+
-
+
-
+
-
+
-
- // Handle lists
- scroll = this.convertLists(scroll);
-
- // Handle images
- scroll = this.convertImages(scroll);
-
+
-
+
-
+
+ convertInputCommands(text) {
+ // Match \input{filename} with or without .tex extension
+ const inputRegex = /\\input\{([^}]+)\}/g;
+ return text.replace(inputRegex, (match, filename) => {
+ // Remove .tex extension if present and add .scroll
+ const scrollFile = filename.replace(/\.tex$/, '') + '.scroll';
+ return `${scrollFile}`;
+ });
+ }
+
-
+
-
+
- const prefix = this.blockCommands.begin[env] || "";
-
- if (env === "itemize" || env === "enumerate") {
+ const prefix = this.blockCommands.begin[env] || '';
+
+ if (env === 'itemize' || env === 'enumerate') {
- } else if (env === "verbatim") {
- return `${prefix}${content.trim()}`;
- } else if (env === "figure") {
+ } else if (env === 'verbatim') {
+ return `code\n${content.trim()}`;
+ } else if (env === 'figure') {
-
+
- .split("\n")
- .map((line) => " " + line)
- .join("\n");
-
+ .split('\n')
+ .map(line => ' ' + line)
+ .join('\n');
+
-
+
+ convertListItems(content, type) {
+ const marker = type === 'itemize' ? '- ' : '1. ';
+ return content
+ .split('\\item')
+ .slice(1) // Skip first empty element
+ .map(item => marker + item.trim())
+ .join('\n') + '\n';
+ }
+
-
+
- Object.keys(this.blockCommands).forEach((cmd) => {
- if (cmd === "begin") return;
- const regex = new RegExp(`\\\\${cmd}{([^}]+)}`, "g");
+ Object.keys(this.blockCommands).forEach(cmd => {
+ if (cmd === 'begin') return;
+ const regex = new RegExp(`\\\\${cmd}{([^}]+)}`, 'g');
-
+
-
+
- Object.keys(this.inlineCommands).forEach((cmd) => {
- const regex = new RegExp(`\\\\${cmd}{([^}]+)}`, "g");
+ Object.keys(this.inlineCommands).forEach(cmd => {
+ const regex = new RegExp(`\\\\${cmd}{([^}]+)}`, 'g');
- if (cmd === "href") {
- const [url, text] = content.split("}{");
- return `${text}\n link ${url} ${text}`;
+ if (cmd === 'href') {
+ // Handle \href{url}{text}
+ const [url, linkText] = content.split('}{');
+ return `${linkText.replace('}', '')}\n link ${url} ${linkText.replace('}', '')}`;
-
+
- "\\&": "&",
- "\\%": "%",
- "\\$": "$",
- "\\#": "#",
- "\\_": "_",
- "\\{": "{",
- "\\}": "}",
- "~": " ",
- "``": '"',
- "''": '"',
+ '\\&': '&',
+ '\\%': '%',
+ '\\$': '$',
+ '\\#': '#',
+ '\\_': '_',
+ '\\{': '{',
+ '\\}': '}',
+ '~': ' ',
+ '``': '"',
+ "''": '"'
-
+
- Object.keys(charMap).forEach((char) => {
- result = result.replace(
- new RegExp(char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
- charMap[char],
- );
+ Object.keys(charMap).forEach(char => {
+ result = result.replace(new RegExp(char.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), charMap[char]);
-
+
- convertListItems(content, type) {
- const marker = type === "itemize" ? "- " : "1. ";
- const lines = content
- .split("\\item")
- .slice(1) // Skip first empty element
- .map((item) => marker + item.trim())
- .join("\n");
- return lines + "\n";
- }
-
-
- const imagePath = content.match(includegraphicsRegex)?.[1] || "";
- const caption = content.match(captionRegex)?.[1] || "";
-
+
+ const imagePath = content.match(includegraphicsRegex)?.[1] || '';
+ const caption = content.match(captionRegex)?.[1] || '';
+
-
+
- result = result.replace(/\\cite\{([^}]+)\}/g, "^$1");
-
+ result = result.replace(/\\cite\{([^}]+)\}/g, '^$1');
+
- result = result.replace(/\\ref\{([^}]+)\}/g, "^$1");
-
+ result = result.replace(/\\ref\{([^}]+)\}/g, '^$1');
+
- return (
- text
- .replace(/\n\s*\n\s*\n/g, "\n\n") // Remove extra blank lines
- .replace(/[ \t]+$/gm, "") // Remove trailing whitespace
- .trim() + "\n"
- ); // Ensure single newline at end
+ return text
+ .replace(/\n\s*\n\s*\n/g, '\n\n') // Remove extra blank lines
+ .replace(/[ \t]+$/gm, '') // Remove trailing whitespace
+ .trim() + '\n'; // Ensure single newline at end
- // module.exports = LaTeXToScroll;
+ // For Node.js environment
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = LaTeXToScroll;
+ }
markdown.js
Changed around line 1
- // Mapping of common Markdown patterns
Changed around line 18: class MarkdownToScroll {
- footnoteRef: /\[\^(\d+)\]/g,
- footnoteDef: /^\[\^(\d+)\]:\s*(.+)$/,
- // Split into lines for block-level processing
- let lines = markdown.trim().split("\n");
- let scroll = "";
+ if (!markdown) return '';
+
+ let lines = markdown.toString().trim().split('\n');
+ let scroll = '';
- let codeBlockContent = "";
- let inTable = false;
- let tableContent = [];
+ let codeBlockContent = '';
+ let inList = false;
+ let listIndentLevel = 0;
- const line = lines[i];
-
- // Handle code blocks first
- if (line.startsWith("```")) {
+ let line = lines[i].trimEnd();
+
+ // Handle code blocks
+ if (line.startsWith('```')) {
- codeBlockContent = "";
+ codeBlockContent = '';
- scroll += this.convertCodeBlock(codeBlockContent.trim()) + "\n\n";
+ scroll += 'code\n' + codeBlockContent.trim() + '\n\n';
- codeBlockContent += line + "\n";
+ codeBlockContent += line + '\n';
- // Handle tables
- if (line.startsWith("|")) {
- if (!inTable) {
- inTable = true;
- tableContent = [];
- }
- if (!this.blockPatterns.tableDelimiter.test(line)) {
- tableContent.push(line);
- }
+ // Handle horizontal rules
+ if (this.blockPatterns.horizontalRule.test(line)) {
+ scroll += '---\n\n';
- } else if (inTable) {
- scroll += this.convertTable(tableContent) + "\n\n";
- inTable = false;
- tableContent = [];
- // Process block-level patterns
- let processed = false;
-
- // Headers
+ // Handle headers
- scroll +=
- "#".repeat(headerMatch[1].length) +
- " " +
- this.convertInlineElements(headerMatch[2]) +
- "\n\n";
- processed = true;
- }
-
- // Horizontal Rule
- if (this.blockPatterns.horizontalRule.test(line)) {
- scroll += "---\n\n";
- processed = true;
+ scroll += '#'.repeat(headerMatch[1].length) + ' ' +
+ this.convertInlineElements(headerMatch[2]) + '\n\n';
+ continue;
- // Blockquotes
+ // Handle blockquotes
- scroll += "> " + this.convertInlineElements(blockquoteMatch[1]) + "\n";
- processed = true;
+ scroll += '> ' + this.convertInlineElements(blockquoteMatch[1]) + '\n';
+ continue;
- // Unordered Lists
+ // Handle lists
- if (ulMatch) {
- scroll += "- " + this.convertInlineElements(ulMatch[1]) + "\n";
- processed = true;
- }
-
- // Ordered Lists
- if (olMatch) {
- scroll += "1. " + this.convertInlineElements(olMatch[1]) + "\n";
- processed = true;
- }
-
- // Footnote Definitions
- const footnoteMatch = line.match(this.blockPatterns.footnoteDef);
- if (footnoteMatch) {
- scroll +=
- "^" +
- footnoteMatch[1] +
- " " +
- this.convertInlineElements(footnoteMatch[2]) +
- "\n";
- processed = true;
- }
-
- // Regular paragraphs
- if (!processed && line.trim()) {
- scroll += "* " + this.convertInlineElements(line) + "\n\n";
+ if (ulMatch || olMatch) {
+ const content = (ulMatch || olMatch)[1];
+ const marker = ulMatch ? '- ' : '1. ';
+ scroll += marker + this.convertInlineElements(content) + '\n';
+ continue;
- // Preserve blank lines
- if (!line.trim()) {
- scroll += "\n";
+ // Handle regular paragraphs
+ if (line.trim()) {
+ scroll += '* ' + this.convertInlineElements(line) + '\n\n';
+ } else {
+ scroll += '\n';
Changed around line 95: class MarkdownToScroll {
- let result = text;
-
- // Convert images before links (to avoid nested parsing issues)
- result = result.replace(
- this.inlinePatterns.image,
- (match, alt, src, title) => {
- let scroll = `\nimage ${src}`;
- if (alt) scroll += `\n caption ${alt}`;
- return scroll;
- },
- );
+ if (!text) return '';
+ let result = text.toString();
+
+ // Convert images before links
+ result = result.replace(this.inlinePatterns.image, (match, alt, src, title) => {
+ let scroll = `\nimage ${src}`;
+ if (alt) scroll += `\n caption ${alt}`;
+ return scroll;
+ });
- result = result.replace(
- this.inlinePatterns.link,
- (match, text, url, title) => {
- let scroll = text + "\n link " + url + " " + text;
- if (title) scroll += "\n title " + title;
- return scroll;
- },
- );
+ result = result.replace(this.inlinePatterns.link, (match, text, url) => {
+ return `${text}\n link ${url} ${text}`;
+ });
- .replace(this.inlinePatterns.bold, "*$1*")
- .replace(this.inlinePatterns.italic, "_$1_")
- .replace(this.inlinePatterns.code, "`$1`")
- .replace(this.inlinePatterns.strikethrough, "strike $1")
- .replace(this.inlinePatterns.footnoteRef, "^$1");
+ .replace(this.inlinePatterns.bold, '*$1*')
+ .replace(this.inlinePatterns.italic, '_$1_')
+ .replace(this.inlinePatterns.code, '`$1`')
+ .replace(this.inlinePatterns.strikethrough, 'strike $1');
- convertCodeBlock(content) {
- return "code\n" + content;
- }
-
- convertTable(tableContent) {
- let scroll = "table\n";
- scroll += " data\n";
-
- // Convert each table row to CSV format
- tableContent.forEach((row) => {
- const cells = row
- .split("|")
- .filter((cell) => cell.trim()) // Remove empty cells from start/end
- .map((cell) => cell.trim())
- .map((cell) => this.convertInlineElements(cell))
- .join(",");
- scroll += " " + cells + "\n";
- });
-
- return scroll;
- }
-
- return (
- scroll
- .replace(/\n{3,}/g, "\n\n") // Remove extra blank lines
- .replace(/[ \t]+$/gm, "") // Remove trailing whitespace
- .trim() + "\n"
- ); // Ensure single newline at end
+ return scroll
+ .replace(/\n{3,}/g, '\n\n') // Remove extra blank lines
+ .replace(/[ \t]+$/gm, '') // Remove trailing whitespace
+ .replace(/\^undefined\n/g, '') // Remove undefined references
+ .replace(/\n\n+/g, '\n\n') // Normalize multiple newlines
+ .trim() + '\n'; // Ensure single newline at end
- // module.exports = MarkdownToScroll;
+ // For Node.js environment
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = MarkdownToScroll;
+ }
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 23
- padding-top: 1rem;
+ padding-top: 0.2rem;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 33
- margin-bottom: 1rem;
+ margin-bottom: 0.2rem;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 23
+ padding-top: 1rem;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 33
+ margin-top: 0;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 32
- margin-bottom: 2rem;
+ margin-bottom: 1rem;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 28
- h1 {
+ h1,
+ h2 {
- h2 {
- text-align: center;
- }
-
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 34
+ h2 {
+ text-align: center;
+ }
+
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 108
-

Scroll Importer - HTML, Markdown, and LaTeX to Scroll

+

Scroll Importer

+

Convert HTML, Markdown, and LaTeX to Scroll

ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 108
-

Format Converter

+

Scroll Importer - HTML, Markdown, and LaTeX to Scroll

ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated latex.js
latex.js
Changed around line 189: class LaTeXToScroll {
- module.exports = LaTeXToScroll;
+ // module.exports = LaTeXToScroll;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated markdown.js
markdown.js
Changed around line 203: class MarkdownToScroll {
- module.exports = MarkdownToScroll;
+ // module.exports = MarkdownToScroll;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated html.js
html.js
Changed around line 247: if (typeof window === "undefined") {
- module.exports = HTMLToScroll;
+ // module.exports = HTMLToScroll;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated index.scroll
index.scroll
Changed around line 1
- theme roboto
-
- Hello World my name is
+ claude.html
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
Changed around line 1
+
+
+
+
+ Format Converter - LaTeX/HTML/Markdown to Scroll
+
+
+
+

Format Converter

+
+
+
+
+ Input
+
+ >(Paste content to detect format)
+ >
+
+
+
+ id="input"
+ placeholder="Paste your LaTeX, HTML, or Markdown content here..."
+ >
+
+
+
+
Scroll Output
+
+
+
+ id="output"
+ readonly
+ placeholder="Converted content will appear here..."
+ >
+
+
+
+
+
+
+
+
+
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated claude.html
claude.html
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated markdown.js
markdown.js
Changed around line 1
+ class MarkdownToScroll {
+ constructor() {
+ // Mapping of common Markdown patterns
+ this.blockPatterns = {
+ header: /^(#{1,6})\s+(.+)$/,
+ horizontalRule: /^[\*\-_]{3,}$/,
+ blockquote: /^>\s*(.+)$/,
+ unorderedList: /^[\*\-+]\s+(.+)$/,
+ orderedList: /^\d+\.\s+(.+)$/,
+ codeBlock: /^```(\w*)\n([\s\S]*?)```$/m,
+ table: /^\|(.+)\|$/,
+ tableDelimiter: /^\|(?:[-:]+[-| :]*)\|$/,
+ };
+
+ this.inlinePatterns = {
+ bold: /\*\*(.+?)\*\*/g,
+ italic: /\b_(.+?)_\b/g,
+ code: /`(.+?)`/g,
+ strikethrough: /~~(.+?)~~/g,
+ link: /\[([^\]]+)\]\(([^)]+)\)(?:\{([^}]+)\})?/g,
+ image: /!\[([^\]]*)\]\(([^)]+)\)(?:\{([^}]+)\})?/g,
+ footnoteRef: /\[\^(\d+)\]/g,
+ footnoteDef: /^\[\^(\d+)\]:\s*(.+)$/,
+ };
+ }
+
+ convert(markdown) {
+ // Split into lines for block-level processing
+ let lines = markdown.trim().split("\n");
+ let scroll = "";
+ let inCodeBlock = false;
+ let codeBlockContent = "";
+ let inTable = false;
+ let tableContent = [];
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+
+ // Handle code blocks first
+ if (line.startsWith("```")) {
+ if (!inCodeBlock) {
+ inCodeBlock = true;
+ codeBlockContent = "";
+ continue;
+ } else {
+ scroll += this.convertCodeBlock(codeBlockContent.trim()) + "\n\n";
+ inCodeBlock = false;
+ continue;
+ }
+ }
+
+ if (inCodeBlock) {
+ codeBlockContent += line + "\n";
+ continue;
+ }
+
+ // Handle tables
+ if (line.startsWith("|")) {
+ if (!inTable) {
+ inTable = true;
+ tableContent = [];
+ }
+ if (!this.blockPatterns.tableDelimiter.test(line)) {
+ tableContent.push(line);
+ }
+ continue;
+ } else if (inTable) {
+ scroll += this.convertTable(tableContent) + "\n\n";
+ inTable = false;
+ tableContent = [];
+ }
+
+ // Process block-level patterns
+ let processed = false;
+
+ // Headers
+ const headerMatch = line.match(this.blockPatterns.header);
+ if (headerMatch) {
+ scroll +=
+ "#".repeat(headerMatch[1].length) +
+ " " +
+ this.convertInlineElements(headerMatch[2]) +
+ "\n\n";
+ processed = true;
+ }
+
+ // Horizontal Rule
+ if (this.blockPatterns.horizontalRule.test(line)) {
+ scroll += "---\n\n";
+ processed = true;
+ }
+
+ // Blockquotes
+ const blockquoteMatch = line.match(this.blockPatterns.blockquote);
+ if (blockquoteMatch) {
+ scroll += "> " + this.convertInlineElements(blockquoteMatch[1]) + "\n";
+ processed = true;
+ }
+
+ // Unordered Lists
+ const ulMatch = line.match(this.blockPatterns.unorderedList);
+ if (ulMatch) {
+ scroll += "- " + this.convertInlineElements(ulMatch[1]) + "\n";
+ processed = true;
+ }
+
+ // Ordered Lists
+ const olMatch = line.match(this.blockPatterns.orderedList);
+ if (olMatch) {
+ scroll += "1. " + this.convertInlineElements(olMatch[1]) + "\n";
+ processed = true;
+ }
+
+ // Footnote Definitions
+ const footnoteMatch = line.match(this.blockPatterns.footnoteDef);
+ if (footnoteMatch) {
+ scroll +=
+ "^" +
+ footnoteMatch[1] +
+ " " +
+ this.convertInlineElements(footnoteMatch[2]) +
+ "\n";
+ processed = true;
+ }
+
+ // Regular paragraphs
+ if (!processed && line.trim()) {
+ scroll += "* " + this.convertInlineElements(line) + "\n\n";
+ }
+
+ // Preserve blank lines
+ if (!line.trim()) {
+ scroll += "\n";
+ }
+ }
+
+ return this.cleanup(scroll);
+ }
+
+ convertInlineElements(text) {
+ let result = text;
+
+ // Convert images before links (to avoid nested parsing issues)
+ result = result.replace(
+ this.inlinePatterns.image,
+ (match, alt, src, title) => {
+ let scroll = `\nimage ${src}`;
+ if (alt) scroll += `\n caption ${alt}`;
+ return scroll;
+ },
+ );
+
+ // Convert links
+ result = result.replace(
+ this.inlinePatterns.link,
+ (match, text, url, title) => {
+ let scroll = text + "\n link " + url + " " + text;
+ if (title) scroll += "\n title " + title;
+ return scroll;
+ },
+ );
+
+ // Convert other inline elements
+ result = result
+ .replace(this.inlinePatterns.bold, "*$1*")
+ .replace(this.inlinePatterns.italic, "_$1_")
+ .replace(this.inlinePatterns.code, "`$1`")
+ .replace(this.inlinePatterns.strikethrough, "strike $1")
+ .replace(this.inlinePatterns.footnoteRef, "^$1");
+
+ return result;
+ }
+
+ convertCodeBlock(content) {
+ return "code\n" + content;
+ }
+
+ convertTable(tableContent) {
+ let scroll = "table\n";
+ scroll += " data\n";
+
+ // Convert each table row to CSV format
+ tableContent.forEach((row) => {
+ const cells = row
+ .split("|")
+ .filter((cell) => cell.trim()) // Remove empty cells from start/end
+ .map((cell) => cell.trim())
+ .map((cell) => this.convertInlineElements(cell))
+ .join(",");
+ scroll += " " + cells + "\n";
+ });
+
+ return scroll;
+ }
+
+ cleanup(scroll) {
+ return (
+ scroll
+ .replace(/\n{3,}/g, "\n\n") // Remove extra blank lines
+ .replace(/[ \t]+$/gm, "") // Remove trailing whitespace
+ .trim() + "\n"
+ ); // Ensure single newline at end
+ }
+ }
+
+ module.exports = MarkdownToScroll;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated markdown.js
markdown.js
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated html.js
html.js
Changed around line 1
+ class HTMLToScroll {
+ constructor() {
+ // Mapping of HTML elements to Scroll syntax
+ this.blockElements = {
+ h1: "# ",
+ h2: "## ",
+ h3: "### ",
+ h4: "#### ",
+ h5: "##### ",
+ p: "*",
+ blockquote: "> ",
+ pre: "code\n",
+ ul: null, // Handled specially
+ ol: null, // Handled specially
+ figure: null, // Handled specially
+ };
+
+ this.inlineElements = {
+ strong: "*",
+ b: "*",
+ em: "_",
+ i: "_",
+ code: "`",
+ a: null, // Handled specially
+ img: null, // Handled specially
+ };
+
+ // Elements that should create line breaks before/after
+ this.blockLevelElements = new Set([
+ "div",
+ "p",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "ul",
+ "ol",
+ "li",
+ "blockquote",
+ "pre",
+ "figure",
+ ]);
+ }
+
+ convert(html) {
+ // Create a DOM parser
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(html, "text/html");
+
+ // Convert the body content
+ return this.convertNode(doc.body).trim() + "\n";
+ }
+
+ convertNode(node, indent = "") {
+ let result = "";
+
+ // Handle text nodes
+ if (node.nodeType === Node.TEXT_NODE) {
+ const text = node.textContent.trim();
+ if (text) {
+ result += indent + this.escapeSpecialCharacters(text);
+ }
+ return result;
+ }
+
+ // Skip comments and other node types
+ if (node.nodeType !== Node.ELEMENT_NODE) {
+ return result;
+ }
+
+ const tagName = node.tagName.toLowerCase();
+
+ // Handle block elements
+ if (this.blockElements.hasOwnProperty(tagName)) {
+ result += this.convertBlockElement(node, indent);
+ }
+ // Handle inline elements
+ else if (this.inlineElements.hasOwnProperty(tagName)) {
+ result += this.convertInlineElement(node, indent);
+ }
+ // Handle special cases
+ else if (tagName === "div") {
+ result += this.convertDiv(node, indent);
+ }
+ // Handle unknown elements by just processing their children
+ else {
+ for (const child of node.childNodes) {
+ result += this.convertNode(child, indent);
+ }
+ }
+
+ return result;
+ }
+
+ convertBlockElement(node, indent) {
+ const tagName = node.tagName.toLowerCase();
+ let result = "";
+
+ switch (tagName) {
+ case "ul":
+ return this.convertList(node, indent, "- ");
+
+ case "ol":
+ return this.convertList(node, indent, "1. ");
+
+ case "figure":
+ return this.convertFigure(node, indent);
+
+ case "pre":
+ if (node.firstElementChild?.tagName.toLowerCase() === "code") {
+ result += indent + "code\n";
+ result += indent + node.textContent.trim() + "\n";
+ } else {
+ result += indent + "code\n";
+ result += indent + node.textContent.trim() + "\n";
+ }
+ break;
+
+ default:
+ const prefix = this.blockElements[tagName];
+ const content = this.getNodeContent(node, indent);
+ result += indent + prefix + content + "\n";
+ }
+
+ return result;
+ }
+
+ convertInlineElement(node, indent) {
+ const tagName = node.tagName.toLowerCase();
+ let result = "";
+
+ switch (tagName) {
+ case "a":
+ return this.convertLink(node, indent);
+
+ case "img":
+ return this.convertImage(node, indent);
+
+ default:
+ const marker = this.inlineElements[tagName];
+ const content = this.getNodeContent(node, "");
+ result += marker + content.trim() + marker;
+ }
+
+ return result;
+ }
+
+ convertList(node, indent, marker) {
+ let result = "\n";
+ for (const child of node.children) {
+ if (child.tagName.toLowerCase() === "li") {
+ result +=
+ indent +
+ marker +
+ this.getNodeContent(child, indent + " ").trim() +
+ "\n";
+ }
+ }
+ return result;
+ }
+
+ convertLink(node, indent) {
+ const href = node.getAttribute("href");
+ const text = node.textContent.trim();
+ const title = node.getAttribute("title");
+
+ if (!href) return text;
+
+ let result = text + "\n";
+ result += indent + ` link ${href} ${text}`;
+ if (title) {
+ result += `\n${indent} title ${title}`;
+ }
+ return result;
+ }
+
+ convertImage(node, indent) {
+ const src = node.getAttribute("src");
+ const alt = node.getAttribute("alt");
+
+ if (!src) return "";
+
+ let result = `\nimage ${src}`;
+ if (alt) {
+ result += `\n caption ${alt}`;
+ }
+ return result + "\n";
+ }
+
+ convertFigure(node, indent) {
+ let result = "\n";
+ const img = node.querySelector("img");
+ const figcaption = node.querySelector("figcaption");
+
+ if (img) {
+ const src = img.getAttribute("src");
+ result += indent + `image ${src}\n`;
+ }
+
+ if (figcaption) {
+ result += indent + ` caption ${figcaption.textContent.trim()}\n`;
+ }
+
+ return result;
+ }
+
+ convertDiv(node, indent) {
+ let result = "";
+ const className = node.getAttribute("class");
+
+ if (className) {
+ result += `\n${indent}class ${className}\n`;
+ }
+
+ for (const child of node.childNodes) {
+ result += this.convertNode(child, indent + (className ? " " : ""));
+ }
+
+ return result;
+ }
+
+ getNodeContent(node, indent) {
+ let content = "";
+ for (const child of node.childNodes) {
+ content += this.convertNode(child, indent);
+ }
+ return content;
+ }
+
+ escapeSpecialCharacters(text) {
+ return text
+ .replace(/\*/g, "\\*")
+ .replace(/\_/g, "\\_")
+ .replace(/\`/g, "\\`")
+ .replace(/\[/g, "\\[")
+ .replace(/\]/g, "\\]")
+ .replace(/\^/g, "\\^");
+ }
+ }
+
+ // For Node.js environment
+ if (typeof window === "undefined") {
+ const { JSDOM } = require("jsdom");
+ global.Node = new JSDOM().window.Node;
+ global.DOMParser = new JSDOM().window.DOMParser;
+ }
+
+ module.exports = HTMLToScroll;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated html.js
html.js
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated latex.js
latex.js
Changed around line 1
+ class LaTeXToScroll {
+ constructor() {
+ this.blockCommands = {
+ section: "# ",
+ subsection: "## ",
+ subsubsection: "### ",
+ paragraph: "*",
+ begin: {
+ itemize: "- ",
+ enumerate: "1. ",
+ quote: "> ",
+ verbatim: "code\n",
+ center: "center\n",
+ figure: "figure\n",
+ },
+ };
+
+ this.inlineCommands = {
+ textbf: "*",
+ textit: "_",
+ texttt: "`",
+ emph: "_",
+ href: "link",
+ };
+ }
+
+ convert(latex) {
+ let scroll = latex;
+
+ // Remove comments
+ scroll = scroll.replace(/%.*$/gm, "");
+
+ // Handle block environments
+ scroll = this.convertEnvironments(scroll);
+
+ // Handle section commands
+ scroll = this.convertSections(scroll);
+
+ // Handle inline formatting
+ scroll = this.convertInlineCommands(scroll);
+
+ // Handle special characters
+ scroll = this.convertSpecialCharacters(scroll);
+
+ // Handle lists
+ scroll = this.convertLists(scroll);
+
+ // Handle images
+ scroll = this.convertImages(scroll);
+
+ // Handle citations and references
+ scroll = this.convertCitations(scroll);
+
+ // Clean up extra whitespace
+ scroll = this.cleanupWhitespace(scroll);
+
+ return scroll;
+ }
+
+ convertEnvironments(text) {
+ let result = text;
+
+ // Match begin/end environment blocks
+ const envRegex = /\\begin\{(\w+)\}([\s\S]*?)\\end\{\1\}/g;
+
+ result = result.replace(envRegex, (match, env, content) => {
+ const prefix = this.blockCommands.begin[env] || "";
+
+ if (env === "itemize" || env === "enumerate") {
+ return this.convertListItems(content, env);
+ } else if (env === "verbatim") {
+ return `${prefix}${content.trim()}`;
+ } else if (env === "figure") {
+ return this.convertFigure(content);
+ }
+
+ // Indent content for environments that need it
+ const indentedContent = content
+ .trim()
+ .split("\n")
+ .map((line) => " " + line)
+ .join("\n");
+
+ return `${prefix}${indentedContent}\n`;
+ });
+
+ return result;
+ }
+
+ convertSections(text) {
+ let result = text;
+
+ // Convert section commands
+ Object.keys(this.blockCommands).forEach((cmd) => {
+ if (cmd === "begin") return;
+ const regex = new RegExp(`\\\\${cmd}{([^}]+)}`, "g");
+ result = result.replace(regex, (match, content) => {
+ return `${this.blockCommands[cmd]}${content.trim()}\n`;
+ });
+ });
+
+ return result;
+ }
+
+ convertInlineCommands(text) {
+ let result = text;
+
+ // Convert inline formatting commands
+ Object.keys(this.inlineCommands).forEach((cmd) => {
+ const regex = new RegExp(`\\\\${cmd}{([^}]+)}`, "g");
+ result = result.replace(regex, (match, content) => {
+ if (cmd === "href") {
+ const [url, text] = content.split("}{");
+ return `${text}\n link ${url} ${text}`;
+ }
+ const marker = this.inlineCommands[cmd];
+ return `${marker}${content}${marker}`;
+ });
+ });
+
+ return result;
+ }
+
+ convertSpecialCharacters(text) {
+ const charMap = {
+ "\\&": "&",
+ "\\%": "%",
+ "\\$": "$",
+ "\\#": "#",
+ "\\_": "_",
+ "\\{": "{",
+ "\\}": "}",
+ "~": " ",
+ "``": '"',
+ "''": '"',
+ };
+
+ let result = text;
+ Object.keys(charMap).forEach((char) => {
+ result = result.replace(
+ new RegExp(char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
+ charMap[char],
+ );
+ });
+
+ return result;
+ }
+
+ convertListItems(content, type) {
+ const marker = type === "itemize" ? "- " : "1. ";
+ const lines = content
+ .split("\\item")
+ .slice(1) // Skip first empty element
+ .map((item) => marker + item.trim())
+ .join("\n");
+ return lines + "\n";
+ }
+
+ convertFigure(content) {
+ // Extract image path and caption
+ const includegraphicsRegex = /\\includegraphics(?:\[.*?\])?\{([^}]+)\}/;
+ const captionRegex = /\\caption\{([^}]+)\}/;
+
+ const imagePath = content.match(includegraphicsRegex)?.[1] || "";
+ const caption = content.match(captionRegex)?.[1] || "";
+
+ return `image ${imagePath}\n caption ${caption}\n`;
+ }
+
+ convertCitations(text) {
+ let result = text;
+
+ // Convert \cite{key} to ^key
+ result = result.replace(/\\cite\{([^}]+)\}/g, "^$1");
+
+ // Convert \ref{key} to ^key
+ result = result.replace(/\\ref\{([^}]+)\}/g, "^$1");
+
+ return result;
+ }
+
+ cleanupWhitespace(text) {
+ return (
+ text
+ .replace(/\n\s*\n\s*\n/g, "\n\n") // Remove extra blank lines
+ .replace(/[ \t]+$/gm, "") // Remove trailing whitespace
+ .trim() + "\n"
+ ); // Ensure single newline at end
+ }
+ }
+
+ module.exports = LaTeXToScroll;
ffff:72.234.190.31
ffff:72.234.190.31
2 months ago
Updated latex.js
latex.js
root
root
2 months ago
initial blank_template template
.gitignore
Changed around line 1
+ .DS_Store
+ *.html
+ *.txt
+ *.xml
+ *.css
+ *.js
+ *.csv
+ requests.scroll
index.scroll
Changed around line 1
+ buildHtml
+ theme roboto
+
+ Hello World my name is