7 changed files with 312 additions and 10 deletions
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
import { describe, it, expect } from 'vitest'; |
||||
import { parseBasicmarkup } from '../../src/lib/utils/markup/basicMarkupParser'; |
||||
import { parseAdvancedmarkup } from '../../src/lib/utils/markup/advancedMarkupParser'; |
||||
import { readFileSync } from 'fs'; |
||||
import { join } from 'path'; |
||||
|
||||
const testFilePath = join(__dirname, './markupTestfile.md'); |
||||
const md = readFileSync(testFilePath, 'utf-8'); |
||||
|
||||
describe('Markup Integration Test', () => { |
||||
it('parses markupTestfile.md with the basic parser', async () => { |
||||
const output = await parseBasicmarkup(md); |
||||
// Headers (should be present as text, not <h1> tags)
|
||||
expect(output).toContain('This is a test'); |
||||
expect(output).toContain('============'); |
||||
expect(output).toContain('### Disclaimer'); |
||||
// Unordered list
|
||||
expect(output).toContain('<ul'); |
||||
expect(output).toContain('but'); |
||||
// Ordered list
|
||||
expect(output).toContain('<ol'); |
||||
expect(output).toContain('first'); |
||||
// Nested lists
|
||||
expect(output).toMatch(/<ul[^>]*>.*<ul[^>]*>/s); |
||||
// Blockquotes
|
||||
expect(output).toContain('<blockquote'); |
||||
expect(output).toContain('This is important information'); |
||||
// Inline code
|
||||
expect(output).toContain('<div class="leather min-h-full w-full flex flex-col items-center">'); |
||||
// Images
|
||||
expect(output).toMatch(/<img[^>]+src="https:\/\/upload\.wikimedia\.org\/wikipedia\/commons\/f\/f1\/Heart_coraz%C3%B3n\.svg"/); |
||||
// Links
|
||||
expect(output).toMatch(/<a[^>]+href="https:\/\/github.com\/nostrability\/nostrability\/issues\/146"/); |
||||
// Hashtags
|
||||
expect(output).toContain('text-primary-600'); |
||||
// Nostr identifiers (should be njump.me links)
|
||||
expect(output).toContain('https://njump.me/npub1l5sga6xg72phsz5422ykujprejwud075ggrr3z2hwyrfgr7eylqstegx9z'); |
||||
// Wikilinks
|
||||
expect(output).toContain('wikilink'); |
||||
// YouTube iframe
|
||||
expect(output).toMatch(/<iframe[^>]+youtube/); |
||||
// Tracking token removal: should not contain utm_, fbclid, or gclid in any link
|
||||
expect(output).not.toMatch(/utm_/); |
||||
expect(output).not.toMatch(/fbclid/); |
||||
expect(output).not.toMatch(/gclid/); |
||||
// Horizontal rule (should be present as --- in basic)
|
||||
expect(output).toContain('---'); |
||||
// Footnote references (should be present as [^1] in basic)
|
||||
expect(output).toContain('[^1]'); |
||||
// Table (should be present as | Syntax | Description | in basic)
|
||||
expect(output).toContain('| Syntax | Description |'); |
||||
}); |
||||
|
||||
it('parses markupTestfile.md with the advanced parser', async () => { |
||||
const output = await parseAdvancedmarkup(md); |
||||
// Headers
|
||||
expect(output).toContain('<h1'); |
||||
expect(output).toContain('<h2'); |
||||
expect(output).toContain('Disclaimer'); |
||||
// Unordered list
|
||||
expect(output).toContain('<ul'); |
||||
expect(output).toContain('but'); |
||||
// Ordered list
|
||||
expect(output).toContain('<ol'); |
||||
expect(output).toContain('first'); |
||||
// Nested lists
|
||||
expect(output).toMatch(/<ul[^>]*>.*<ul[^>]*>/s); |
||||
// Blockquotes
|
||||
expect(output).toContain('<blockquote'); |
||||
expect(output).toContain('This is important information'); |
||||
// Inline code
|
||||
expect(output).toMatch(/<code[^>]*>.*leather min-h-full w-full flex flex-col items-center.*<\/code>/s); |
||||
// Images
|
||||
expect(output).toMatch(/<img[^>]+src="https:\/\/upload\.wikimedia\.org\/wikipedia\/commons\/f\/f1\/Heart_coraz%C3%B3n\.svg"/); |
||||
// Links
|
||||
expect(output).toMatch(/<a[^>]+href="https:\/\/github.com\/nostrability\/nostrability\/issues\/146"/); |
||||
// Hashtags
|
||||
expect(output).toContain('text-primary-600'); |
||||
// Nostr identifiers (should be njump.me links)
|
||||
expect(output).toContain('https://njump.me/npub1l5sga6xg72phsz5422ykujprejwud075ggrr3z2hwyrfgr7eylqstegx9z'); |
||||
// Wikilinks
|
||||
expect(output).toContain('wikilink'); |
||||
// YouTube iframe
|
||||
expect(output).toMatch(/<iframe[^>]+youtube/); |
||||
// Tracking token removal: should not contain utm_, fbclid, or gclid in any link
|
||||
expect(output).not.toMatch(/utm_/); |
||||
expect(output).not.toMatch(/fbclid/); |
||||
expect(output).not.toMatch(/gclid/); |
||||
// Horizontal rule
|
||||
expect(output).toContain('<hr'); |
||||
// Footnote references and section
|
||||
expect(output).toContain('Footnotes'); |
||||
expect(output).toMatch(/<li id=\"fn-1\">/); |
||||
// Table
|
||||
expect(output).toContain('<table'); |
||||
// Code blocks
|
||||
expect(output).toContain('<pre'); |
||||
}); |
||||
});
|
||||
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
import { describe, it, expect } from 'vitest'; |
||||
import { parseAdvancedmarkup } from '../../src/lib/utils/markup/advancedMarkupParser'; |
||||
|
||||
function stripWS(str: string) { |
||||
return str.replace(/\s+/g, ' ').trim(); |
||||
} |
||||
|
||||
describe('Advanced Markup Parser', () => { |
||||
it('parses headers (ATX and Setext)', async () => { |
||||
const input = '# H1\nText\n\nH2\n====\n'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(stripWS(output)).toContain('H1'); |
||||
expect(stripWS(output)).toContain('H2'); |
||||
}); |
||||
|
||||
it('parses bold, italic, and strikethrough', async () => { |
||||
const input = '*bold* **bold** _italic_ __italic__ ~strikethrough~ ~~strikethrough~~'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<strong>bold</strong>'); |
||||
expect(output).toContain('<em>italic</em>'); |
||||
expect(output).toContain('<del class="line-through">strikethrough</del>'); |
||||
}); |
||||
|
||||
it('parses blockquotes', async () => { |
||||
const input = '> quote'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<blockquote'); |
||||
expect(output).toContain('quote'); |
||||
}); |
||||
|
||||
it('parses multi-line blockquotes', async () => { |
||||
const input = '> quote\n> quote'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<blockquote'); |
||||
expect(output).toContain('quote'); |
||||
expect(output).toContain('quote'); |
||||
}); |
||||
|
||||
it('parses unordered lists', async () => { |
||||
const input = '* a\n* b'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<ul'); |
||||
expect(output).toContain('a'); |
||||
expect(output).toContain('b'); |
||||
}); |
||||
|
||||
it('parses ordered lists', async () => { |
||||
const input = '1. one\n2. two'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<ol'); |
||||
expect(output).toContain('one'); |
||||
expect(output).toContain('two'); |
||||
}); |
||||
|
||||
it('parses links and images', async () => { |
||||
const input = '[link](https://example.com) '; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<a'); |
||||
expect(output).toContain('<img'); |
||||
}); |
||||
|
||||
it('parses hashtags', async () => { |
||||
const input = '#hashtag'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('text-primary-600'); |
||||
expect(output).toContain('#hashtag'); |
||||
}); |
||||
|
||||
it('parses nostr identifiers', async () => { |
||||
const input = 'npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('https://njump.me/npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'); |
||||
}); |
||||
|
||||
it('parses emoji shortcodes', async () => { |
||||
const input = 'hello :smile:'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toMatch(/😄|:smile:/); |
||||
}); |
||||
|
||||
it('parses wikilinks', async () => { |
||||
const input = '[[Test Page|display]]'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('wikilink'); |
||||
expect(output).toContain('display'); |
||||
}); |
||||
|
||||
it('parses tables (with and without headers)', async () => { |
||||
const input = `| Syntax | Description |\n|--------|-------------|\n| Header | Title |\n| Paragraph | Text |\n\n| a | b |\n| c | d |`; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<table'); |
||||
expect(output).toContain('Header'); |
||||
expect(output).toContain('a'); |
||||
}); |
||||
|
||||
it('parses code blocks (with and without language)', async () => { |
||||
const input = '```js\nconsole.log(1);\n```\n```\nno lang\n```'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
const textOnly = output.replace(/<[^>]+>/g, ''); |
||||
expect(output).toContain('<pre'); |
||||
expect(textOnly).toContain('console.log(1);'); |
||||
expect(textOnly).toContain('no lang'); |
||||
}); |
||||
|
||||
it('parses horizontal rules', async () => { |
||||
const input = '---'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('<hr'); |
||||
}); |
||||
|
||||
it('parses footnotes (references and section)', async () => { |
||||
const input = 'Here is a footnote[^1].\n\n[^1]: This is the footnote.'; |
||||
const output = await parseAdvancedmarkup(input); |
||||
expect(output).toContain('Footnotes'); |
||||
expect(output).toContain('This is the footnote'); |
||||
expect(output).toContain('fn-1'); |
||||
}); |
||||
});
|
||||
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
import { describe, it, expect } from 'vitest'; |
||||
import { parseBasicmarkup } from '../../src/lib/utils/markup/basicMarkupParser'; |
||||
|
||||
// Helper to strip whitespace for easier comparison
|
||||
function stripWS(str: string) { |
||||
return str.replace(/\s+/g, ' ').trim(); |
||||
} |
||||
|
||||
describe('Basic Markup Parser', () => { |
||||
it('parses ATX and Setext headers', async () => { |
||||
const input = '# H1\nText\n\nH2\n====\n'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(stripWS(output)).toContain('H1'); |
||||
expect(stripWS(output)).toContain('H2'); |
||||
}); |
||||
|
||||
it('parses bold, italic, and strikethrough', async () => { |
||||
const input = '*bold* **bold** _italic_ __italic__ ~strikethrough~ ~~strikethrough~~'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('<strong>bold</strong>'); |
||||
expect(output).toContain('<em>italic</em>'); |
||||
expect(output).toContain('<del class="line-through">strikethrough</del>'); |
||||
}); |
||||
|
||||
it('parses blockquotes', async () => { |
||||
const input = '> quote'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('<blockquote'); |
||||
expect(output).toContain('quote'); |
||||
}); |
||||
|
||||
it('parses multi-line blockquotes', async () => { |
||||
const input = '> quote\n> quote'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('<blockquote'); |
||||
expect(output).toContain('quote'); |
||||
expect(output).toContain('quote'); |
||||
}); |
||||
|
||||
it('parses unordered lists', async () => { |
||||
const input = '* a\n* b'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('<ul'); |
||||
expect(output).toContain('a'); |
||||
expect(output).toContain('b'); |
||||
}); |
||||
|
||||
it('parses ordered lists', async () => { |
||||
const input = '1. one\n2. two'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('<ol'); |
||||
expect(output).toContain('one'); |
||||
expect(output).toContain('two'); |
||||
}); |
||||
|
||||
it('parses links and images', async () => { |
||||
const input = '[link](https://example.com) '; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('<a'); |
||||
expect(output).toContain('<img'); |
||||
}); |
||||
|
||||
it('parses hashtags', async () => { |
||||
const input = '#hashtag'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('text-primary-600'); |
||||
expect(output).toContain('#hashtag'); |
||||
}); |
||||
|
||||
it('parses nostr identifiers', async () => { |
||||
const input = 'npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('https://njump.me/npub1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq'); |
||||
}); |
||||
|
||||
it('parses emoji shortcodes', async () => { |
||||
const input = 'hello :smile:'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toMatch(/😄|:smile:/); |
||||
}); |
||||
|
||||
it('parses wikilinks', async () => { |
||||
const input = '[[Test Page|display]]'; |
||||
const output = await parseBasicmarkup(input); |
||||
expect(output).toContain('wikilink'); |
||||
expect(output).toContain('display'); |
||||
}); |
||||
});
|
||||
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
export function sum(a, b) { |
||||
return a + b |
||||
} |
||||
@ -1,6 +0,0 @@
@@ -1,6 +0,0 @@
|
||||
import { expect, test } from 'vitest' |
||||
import { sum } from './example.js' |
||||
|
||||
test('adds 1 + 2 to equal 3', () => { |
||||
expect(sum(1, 2)).toBe(3) |
||||
}) |
||||
Loading…
Reference in new issue