diff --git a/Syntax.js b/Syntax.js index 7d41375..b3a1b5d 100644 --- a/Syntax.js +++ b/Syntax.js @@ -237,12 +237,12 @@ export class Syntax { } catch (error) { throw new LanguageLoadError(name, path, {cause: error}); } - + // If the module exports a register function, call it with this instance if (typeof module.default === 'function') { module.default(this); } - + // After calling register, aliases have been registered. Re-resolve the name: let resolvedName = this.#aliases[name] || name; return loader.get(resolvedName); diff --git a/Syntax/CodeElement.js b/Syntax/CodeElement.js index 57c5176..ea24b35 100644 --- a/Syntax/CodeElement.js +++ b/Syntax/CodeElement.js @@ -83,7 +83,7 @@ export class CodeElement extends HTMLElement { constructor() { super(); - + /** * A promise that resolves when the current highlighting attempt completes. * Check `highlighted` before using line measurement APIs. @@ -105,10 +105,7 @@ export class CodeElement extends HTMLElement { } get language() { - return ( - this.getAttribute('language') || - this.#detectLanguageFromClass() - ); + return this.getAttribute('language') || this.#detectLanguageFromClass(); } set language(value) { @@ -150,26 +147,26 @@ export class CodeElement extends HTMLElement { */ getLineBoundingClientRect(lineNumber) { if (!this.#shadow) return null; - + const code = this.#shadow.querySelector('code'); if (!code) return null; - + const lines = code.children; if (lineNumber < 1 || lineNumber > lines.length) return null; - + return lines[lineNumber - 1].getBoundingClientRect(); } - + /** * Get the total number of rendered lines. * @returns {number} The line count, or 0 if not yet rendered. */ get lineCount() { if (!this.#shadow) return 0; - + const code = this.#shadow.querySelector('code'); if (!code) return 0; - + return code.children.length; } @@ -180,7 +177,7 @@ export class CodeElement extends HTMLElement { get highlighted() { return this.#highlighted; } - + connectedCallback() { // Detect if we're inside a
 element and set wrap attribute
 		if (this.parentElement?.tagName === 'PRE') {
@@ -382,7 +379,8 @@ export function upgradeAll(selector, syntax = null) {
 		}
 
 		// Try to detect language from various sources
-		let language = element.getAttribute('lang') || element.getAttribute('language');
+		let language =
+			element.getAttribute('lang') || element.getAttribute('language');
 
 		if (!language) {
 			// Check class names
diff --git a/Syntax/Language/html.js b/Syntax/Language/html.js
index 6dbe834..e0ceac3 100644
--- a/Syntax/Language/html.js
+++ b/Syntax/Language/html.js
@@ -8,7 +8,10 @@ language.push({
 	pattern: /]*?)?>((.|\n)*?)<\/script>/im,
 	matches: Rule.extractConditionalMatch(1, 2, [
 		{pattern: /type\s*=\s*["']importmap["']/i, language: 'json'},
-		{pattern: /type\s*=\s*["'](?:text|application)\/javascript["']/i, language: 'javascript'},
+		{
+			pattern: /type\s*=\s*["'](?:text|application)\/javascript["']/i,
+			language: 'javascript'
+		},
 		{language: 'javascript'} // Fallback: no type or unknown type defaults to JavaScript (HTML5)
 	])
 });
diff --git a/Syntax/Language/javascript.js b/Syntax/Language/javascript.js
index 0298208..e70b370 100644
--- a/Syntax/Language/javascript.js
+++ b/Syntax/Language/javascript.js
@@ -50,9 +50,12 @@ language.push(
 );
 
 // Operators
-language.push(['+', '*', '/', '-', '&', '|', '~', '!', '%', '<', '=', '>', '...'], {
-	type: 'operator'
-});
+language.push(
+	['+', '*', '/', '-', '&', '|', '~', '!', '%', '<', '=', '>', '...'],
+	{
+		type: 'operator'
+	}
+);
 
 // Access modifiers
 language.push(
diff --git a/Syntax/Language/json.js b/Syntax/Language/json.js
index e3983f6..3ac08e8 100644
--- a/Syntax/Language/json.js
+++ b/Syntax/Language/json.js
@@ -21,11 +21,7 @@ language.push({
 // Object keys (strings followed by colon)
 language.push({
 	pattern: /("(?:[^"\\]|\\.)*")(\s*)(:)/,
-	matches: Rule.extractMatches(
-		{type: 'key'},
-		null,
-		{type: 'operator'}
-	)
+	matches: Rule.extractMatches({type: 'key'}, null, {type: 'operator'})
 });
 
 // Structural characters
diff --git a/Syntax/Language/ruby.js b/Syntax/Language/ruby.js
index d21c2ae..26171d0 100644
--- a/Syntax/Language/ruby.js
+++ b/Syntax/Language/ruby.js
@@ -64,7 +64,22 @@ const keywords = [
 	'block_given?'
 ];
 
-const operators = ['+', '*', '/', '-', '&', '|', '~', '!', '%', '<', '=', '>', '...', '..'];
+const operators = [
+	'+',
+	'*',
+	'/',
+	'-',
+	'&',
+	'|',
+	'~',
+	'!',
+	'%',
+	'<',
+	'=',
+	'>',
+	'...',
+	'..'
+];
 const values = ['self', 'super', 'true', 'false', 'nil'];
 const access = ['private', 'protected', 'public'];
 
diff --git a/Syntax/Match.js b/Syntax/Match.js
index 5b01f5f..d46905b 100644
--- a/Syntax/Match.js
+++ b/Syntax/Match.js
@@ -287,11 +287,7 @@ export class Match {
 
 			// Element-backed matches describe authored markup and must retain their
 			// original expression so reduction can recreate that element.
-			if (
-				this.expression &&
-				this.expression.owner &&
-				!match.expression.element
-			) {
+			if (this.expression && this.expression.owner && !match.expression.element) {
 				match.expression =
 					this.expression.owner.getRuleForType(match.expression.type) ||
 					match.expression;
diff --git a/Syntax/Rule.js b/Syntax/Rule.js
index 65619b6..35dd553 100644
--- a/Syntax/Rule.js
+++ b/Syntax/Rule.js
@@ -134,14 +134,14 @@ export class Rule {
 	 * Create a conditional matcher that selects a rule based on another capture group.
 	 * Tests a condition capture group against patterns to determine which rule to apply
 	 * to a content capture group.
-	 * 
+	 *
 	 * @param {number} conditionIndex - Capture group index to test against patterns
 	 * @param {number} contentIndex - Capture group index containing content to match
 	 * @param {Array<{pattern?: RegExp, ...rule}>} conditions - Array of condition objects. Each can have:
 	 *   - pattern: RegExp to test against the condition group (optional - if omitted, acts as fallback)
 	 *   - Any rule properties (language, type, etc.) to apply when pattern matches
 	 * @returns {Function} A matches function for use in language rules
-	 * 
+	 *
 	 * @example
 	 * // Script tags with type-based language selection
 	 * language.push({
@@ -152,7 +152,7 @@ export class Rule {
 	 *     {language: 'javascript'} // Fallback for no type or unknown types
 	 *   ])
 	 * });
-	 * 
+	 *
 	 * @example
 	 * // Code fence with language specifier
 	 * language.push({
@@ -163,7 +163,7 @@ export class Rule {
 	 *     {language: 'plaintext'} // Fallback
 	 *   ])
 	 * });
-	 * 
+	 *
 	 * @example
 	 * // Conditional type based on prefix
 	 * language.push({
@@ -201,7 +201,7 @@ export class Rule {
 
 			// Build syntax tree or create match based on rule properties
 			const offset = match.index + match[0].indexOf(content);
-			
+
 			if (ruleProps.language) {
 				return [
 					await Language.buildTree(
diff --git a/bin/syntax-ast.js b/bin/syntax-ast.js
index 9a55889..339b10f 100755
--- a/bin/syntax-ast.js
+++ b/bin/syntax-ast.js
@@ -4,35 +4,36 @@ import Syntax from '../Syntax.js';
 
 async function main() {
 	const args = process.argv.slice(2);
-	
+
 	if (args.length < 2) {
 		console.error('Usage: syntax-ast  ');
 		console.error('Example: syntax-ast javascript "const x = 1;"');
 		process.exit(1);
 	}
-	
+
 	const [languageName, code] = args;
-	
+
 	const syntax = new Syntax();
-	
+
 	try {
 		const language = await syntax.getLanguage(languageName);
 		const matches = await language.getMatches(syntax, code);
-		
+
 		console.log('Language:', languageName);
 		console.log('Code:', JSON.stringify(code));
 		console.log('\nMatches:', matches.length);
 		console.log('─'.repeat(80));
-		
+
 		for (const match of matches) {
 			const text = code.substring(match.offset, match.offset + match.length);
-			console.log(`[${match.type}] @${match.offset}..${match.offset + match.length} (${match.length} chars)`);
+			console.log(
+				`[${match.type}] @${match.offset}..${match.offset + match.length} (${match.length} chars)`
+			);
 			console.log(`  Text: ${JSON.stringify(text)}`);
 			if (match.children && match.children.length > 0) {
 				console.log(`  Children: ${match.children.length}`);
 			}
 		}
-		
 	} catch (error) {
 		console.error('Error:', error.message);
 		process.exit(1);
diff --git a/package.json b/package.json
index 42c597b..564cec9 100644
--- a/package.json
+++ b/package.json
@@ -20,8 +20,8 @@
 	],
 	"scripts": {
 		"test": "node --test 'test/**/*.js'",
-		"format": "prettier --write '**/*.{js,json,md}'",
-		"format:check": "prettier --check '**/*.{js,json,md}'"
+		"format": "prettier --write '**/*.{js,json}'",
+		"format:check": "prettier --check '**/*.{js,json}'"
 	},
 	"keywords": [
 		"syntax",
diff --git a/test/Syntax/CodeElement.js b/test/Syntax/CodeElement.js
index 7c3efef..92607fa 100644
--- a/test/Syntax/CodeElement.js
+++ b/test/Syntax/CodeElement.js
@@ -202,7 +202,7 @@ test('upgradeAll handles 
 blocks without double-nesting', async () =>
 		'const x = 1;',
 		'Code content should be preserved'
 	);
-	
+
 	// Verify wrap attribute is set (because it's inside 
)
 	// Note: This happens in connectedCallback, which may not fire in JSDOM
 	// We'll just verify structure for now
@@ -346,21 +346,25 @@ test('syntax-code behaves semantically like  when inline', async () => {
 	`;
 
 	const element = document.querySelector('syntax-code');
-	
+
 	// Wait for rendering to complete
 	await new Promise(resolve => setTimeout(resolve, 100));
 
 	// Verify it's inline (like ) by checking the shadow DOM structure
 	const shadowRoot = element.shadowRoot;
 	assert.ok(shadowRoot, 'Shadow root should exist');
-	
+
 	// Should contain a  element, not wrapped in 
 	const codeElement = shadowRoot.querySelector('code');
 	assert.ok(codeElement, 'Shadow DOM should contain  element');
-	
+
 	const preElement = shadowRoot.querySelector('pre');
-	assert.equal(preElement, null, 'Shadow DOM should NOT contain 
 wrapper for inline usage');
-	
+	assert.equal(
+		preElement,
+		null,
+		'Shadow DOM should NOT contain 
 wrapper for inline usage'
+	);
+
 	// The code element should be a direct child of shadow root
 	assert.ok(
 		Array.from(shadowRoot.children).includes(codeElement),
@@ -379,18 +383,21 @@ test('syntax-code behaves as block when inside 
', async () => {
 	`;
 
 	const element = document.querySelector('syntax-code');
-	
+
 	// Wait for rendering to complete
 	await new Promise(resolve => setTimeout(resolve, 100));
 
 	// Check that wrap attribute was set (because it's inside 
)
-	assert.ok(element.hasAttribute('wrap'), 'wrap attribute should be set when inside 
');
-	
+	assert.ok(
+		element.hasAttribute('wrap'),
+		'wrap attribute should be set when inside 
'
+	);
+
 	// After rendering, light DOM is cleared, so check shadow DOM
 	const shadowRoot = element.shadowRoot;
 	const codeElement = shadowRoot.querySelector('code');
 	assert.ok(codeElement, 'Shadow DOM should contain  element');
-	
+
 	// The  should be a direct child of shadow root (no 
 wrapper needed inside)
 	assert.ok(
 		Array.from(shadowRoot.children).includes(codeElement),
@@ -414,7 +421,10 @@ test('ready promise resolves after rendering completes', async () => {
 	// After ready resolves, the shadow root should exist and contain rendered content
 	const shadowRoot = element.shadowRoot;
 	assert.ok(shadowRoot, 'Shadow root should exist after ready');
-	assert.ok(shadowRoot.querySelector('code'), 'Shadow DOM should contain  after ready');
+	assert.ok(
+		shadowRoot.querySelector('code'),
+		'Shadow DOM should contain  after ready'
+	);
 });
 
 test('ready promise resets and re-resolves when language attribute changes', async () => {
@@ -431,11 +441,18 @@ test('ready promise resets and re-resolves when language attribute changes', asy
 	element.setAttribute('language', 'python');
 
 	// The promise should have been replaced
-	assert.notEqual(element.ready, firstReady, 'ready should be a new Promise after attribute change');
+	assert.notEqual(
+		element.ready,
+		firstReady,
+		'ready should be a new Promise after attribute change'
+	);
 
 	// The new promise should also resolve
 	await element.ready;
-	assert.ok(element.shadowRoot.querySelector('code'), 'Shadow DOM should be re-rendered');
+	assert.ok(
+		element.shadowRoot.querySelector('code'),
+		'Shadow DOM should be re-rendered'
+	);
 });
 
 test('lineCount returns 0 before element is connected', async () => {
@@ -454,14 +471,25 @@ test('lineCount returns the number of rendered lines after ready', async () => {
 	const element = document.querySelector('syntax-code');
 	await element.ready;
 
-	assert.ok(element.lineCount > 0, 'lineCount should be greater than 0 after rendering');
-	assert.equal(element.lineCount, element.shadowRoot.querySelector('code').children.length, 'lineCount should match actual child count');
+	assert.ok(
+		element.lineCount > 0,
+		'lineCount should be greater than 0 after rendering'
+	);
+	assert.equal(
+		element.lineCount,
+		element.shadowRoot.querySelector('code').children.length,
+		'lineCount should match actual child count'
+	);
 });
 
 test('getLineBoundingClientRect returns null before element is connected', async () => {
 	const {CodeElement} = await import('../../Syntax/CodeElement.js');
 	const element = new CodeElement();
-	assert.equal(element.getLineBoundingClientRect(1), null, 'Should return null before shadow DOM exists');
+	assert.equal(
+		element.getLineBoundingClientRect(1),
+		null,
+		'Should return null before shadow DOM exists'
+	);
 });
 
 test('getLineBoundingClientRect returns null for out-of-range line numbers', async () => {
@@ -472,11 +500,23 @@ test('getLineBoundingClientRect returns null for out-of-range line numbers', asy
 	const element = document.querySelector('syntax-code');
 	await element.ready;
 
-	assert.equal(element.getLineBoundingClientRect(0), null, 'Line 0 (below 1-based range) should return null');
-	assert.equal(element.getLineBoundingClientRect(-1), null, 'Negative line number should return null');
+	assert.equal(
+		element.getLineBoundingClientRect(0),
+		null,
+		'Line 0 (below 1-based range) should return null'
+	);
+	assert.equal(
+		element.getLineBoundingClientRect(-1),
+		null,
+		'Negative line number should return null'
+	);
 
 	const count = element.lineCount;
-	assert.equal(element.getLineBoundingClientRect(count + 1), null, 'Line beyond lineCount should return null');
+	assert.equal(
+		element.getLineBoundingClientRect(count + 1),
+		null,
+		'Line beyond lineCount should return null'
+	);
 });
 
 test('getLineBoundingClientRect returns a DOMRect for valid line numbers', async () => {
@@ -495,7 +535,13 @@ test('getLineBoundingClientRect returns a DOMRect for valid line numbers', async
 	for (let i = 1; i <= count; i++) {
 		const rect = element.getLineBoundingClientRect(i);
 		assert.ok(rect !== null, `Line ${i} should return a DOMRect, not null`);
-		assert.ok(typeof rect.top === 'number', 'DOMRect should have a numeric top property');
-		assert.ok(typeof rect.height === 'number', 'DOMRect should have a numeric height property');
+		assert.ok(
+			typeof rect.top === 'number',
+			'DOMRect should have a numeric top property'
+		);
+		assert.ok(
+			typeof rect.height === 'number',
+			'DOMRect should have a numeric height property'
+		);
 	}
 });
diff --git a/test/Syntax/Language/html.js b/test/Syntax/Language/html.js
index c72d19b..74293e9 100644
--- a/test/Syntax/Language/html.js
+++ b/test/Syntax/Language/html.js
@@ -56,7 +56,8 @@ test('HTML: embedded JavaScript in script tag without type', async () => {
 
 test('HTML: embedded JSON in importmap', async () => {
 	const language = await getLanguage();
-	const code = '';
+	const code =
+		'';
 	const matches = await language.getMatches(Syntax.default, code);
 	// Should have embedded JSON language
 	ok(matches.some(m => m.expression && m.expression.language === 'json'));
diff --git a/test/Syntax/Language/json.js b/test/Syntax/Language/json.js
index 395aa88..51c5f19 100644
--- a/test/Syntax/Language/json.js
+++ b/test/Syntax/Language/json.js
@@ -30,7 +30,9 @@ test('JSON: integer numbers', async () => {
 	const language = await getLanguage();
 	const code = '0 42 -17 999';
 	const matches = await language.getMatches(Syntax.default, code);
-	const numbers = matches.filter(m => m.expression.type === 'constant' && /^-?\d/.test(m.value));
+	const numbers = matches.filter(
+		m => m.expression.type === 'constant' && /^-?\d/.test(m.value)
+	);
 	ok(numbers.length >= 4);
 });
 
@@ -38,7 +40,9 @@ test('JSON: float numbers', async () => {
 	const language = await getLanguage();
 	const code = '3.14 -0.5 123.456';
 	const matches = await language.getMatches(Syntax.default, code);
-	const numbers = matches.filter(m => m.expression.type === 'constant' && m.value.includes('.'));
+	const numbers = matches.filter(
+		m => m.expression.type === 'constant' && m.value.includes('.')
+	);
 	ok(numbers.length >= 3);
 });
 
@@ -46,7 +50,9 @@ test('JSON: scientific notation', async () => {
 	const language = await getLanguage();
 	const code = '1e10 2.5e-3 -1.23E+5';
 	const matches = await language.getMatches(Syntax.default, code);
-	const numbers = matches.filter(m => m.expression.type === 'constant' && /e/i.test(m.value));
+	const numbers = matches.filter(
+		m => m.expression.type === 'constant' && /e/i.test(m.value)
+	);
 	ok(numbers.length >= 3);
 });
 
@@ -94,7 +100,8 @@ test('JSON: array', async () => {
 
 test('JSON: complex structure', async () => {
 	const language = await getLanguage();
-	const code = '{"items": [{"id": 1, "active": true}, {"id": 2, "active": false}]}';
+	const code =
+		'{"items": [{"id": 1, "active": true}, {"id": 2, "active": false}]}';
 	const matches = await language.getMatches(Syntax.default, code);
 	const keys = matches.filter(m => m.expression.type === 'key');
 	ok(keys.length >= 5);
diff --git a/test/Syntax/Language/markdown.js b/test/Syntax/Language/markdown.js
index 3c09c91..0e516a1 100644
--- a/test/Syntax/Language/markdown.js
+++ b/test/Syntax/Language/markdown.js
@@ -31,10 +31,10 @@ test('Markdown can match headers', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '# Heading 1';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'heading', '# Heading 1');
 });
 
@@ -42,10 +42,10 @@ test('Markdown can match bold text', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '**bold text**';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'strong', '**bold text**');
 });
 
@@ -53,10 +53,10 @@ test('Markdown can match italic text', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '*italic text*';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'emphasis', '*italic text*');
 });
 
@@ -64,10 +64,10 @@ test('Markdown can match inline code', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '`code here`';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'code', '`code here`');
 });
 
@@ -75,10 +75,10 @@ test('Markdown can match code blocks', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '```javascript\nconst x = 1;\n```';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'code', '```javascript\nconst x = 1;\n```');
 });
 
@@ -86,10 +86,10 @@ test('Markdown can match links', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '[text](http://example.com)';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	// Should match the link text and URL as separate tokens
 	assertToken(code, matches, 'string', 'text');
 	assertToken(code, matches, 'link', 'http://example.com');
@@ -99,10 +99,10 @@ test('Markdown can match images', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '![alt text](image.png)';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'link', '![alt text](image.png)');
 });
 
@@ -110,10 +110,10 @@ test('Markdown can match blockquotes', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '> This is a quote';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'quote', '> This is a quote');
 });
 
@@ -121,10 +121,10 @@ test('Markdown can match unordered lists', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '- List item';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'list-marker', '- ');
 });
 
@@ -132,10 +132,10 @@ test('Markdown can match ordered lists', async () => {
 	const syntax = new Syntax();
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
-	
+
 	const code = '1. List item';
 	const matches = await language.getMatches(syntax, code);
-	
+
 	assertToken(code, matches, 'list-marker', '1. ');
 });
 
@@ -144,7 +144,7 @@ test('Markdown: fenced block followed by inline code does not merge', async () =
 	registerMarkdown(syntax);
 	const language = await syntax.getLanguage('markdown');
 
-	const code = "```\nfoo\n```\n\n`project`";
+	const code = '```\nfoo\n```\n\n`project`';
 	const matches = await language.getMatches(syntax, code);
 
 	// Expect a fenced code block token:
@@ -155,9 +155,10 @@ test('Markdown: fenced block followed by inline code does not merge', async () =
 
 	// Ensure there is no token that incorrectly spans the fence backticks
 	// and the following inline backtick (e.g., "````" boundary merge):
-	const badSpan = matches.find(m =>
-		m.type === 'code' &&
-		code.substring(m.offset, m.offset + m.length).includes('````')
+	const badSpan = matches.find(
+		m =>
+			m.type === 'code' &&
+			code.substring(m.offset, m.offset + m.length).includes('````')
 	);
 	assert.strictEqual(badSpan, undefined);
 });
diff --git a/update-examples.js b/update-examples.js
index 958d94b..43ba5ee 100755
--- a/update-examples.js
+++ b/update-examples.js
@@ -1,7 +1,7 @@
 #!/usr/bin/env node
 
-import { readFileSync, writeFileSync, readdirSync } from 'fs';
-import { join } from 'path';
+import {readFileSync, writeFileSync, readdirSync} from 'fs';
+import {join} from 'path';
 
 const examplesDir = './examples';
 const excludeFiles = new Set([
@@ -20,44 +20,44 @@ const excludeFiles = new Set([
 
 // Language name mappings
 const languageNames = {
-	'apache': 'Apache',
-	'applescript': 'AppleScript',
-	'assembly': 'Assembly',
-	'bash': 'Bash',
-	'basic': 'BASIC/VB',
-	'c': 'C/C++',
-	'clang': 'C/C++',
-	'csharp': 'C#',
-	'diff': 'Diff/Patch',
-	'go': 'Go',
-	'haskell': 'Haskell',
-	'io': 'Io',
-	'json': 'JSON',
-	'lisp': 'Lisp',
-	'lua': 'Lua',
-	'mixed': 'Mixed Languages',
-	'nginx': 'Nginx',
-	'ocaml': 'OCaml',
-	'pascal': 'Pascal',
-	'perl5': 'Perl 5',
-	'php': 'PHP',
+	apache: 'Apache',
+	applescript: 'AppleScript',
+	assembly: 'Assembly',
+	bash: 'Bash',
+	basic: 'BASIC/VB',
+	c: 'C/C++',
+	clang: 'C/C++',
+	csharp: 'C#',
+	diff: 'Diff/Patch',
+	go: 'Go',
+	haskell: 'Haskell',
+	io: 'Io',
+	json: 'JSON',
+	lisp: 'Lisp',
+	lua: 'Lua',
+	mixed: 'Mixed Languages',
+	nginx: 'Nginx',
+	ocaml: 'OCaml',
+	pascal: 'Pascal',
+	perl5: 'Perl 5',
+	php: 'PHP',
 	'php-script': 'PHP Script',
-	'plain': 'Plain Text',
-	'protobuf': 'Protocol Buffers',
-	'scala': 'Scala',
-	'smalltalk': 'Smalltalk',
-	'sql': 'SQL',
+	plain: 'Plain Text',
+	protobuf: 'Protocol Buffers',
+	scala: 'Scala',
+	smalltalk: 'Smalltalk',
+	sql: 'SQL',
 	'super-collider': 'SuperCollider',
-	'swift': 'Swift',
+	swift: 'Swift',
 	'wrap-demo': 'Wrap Demo',
-	'xrb': 'XRB',
-	'xml': 'XML',
-	'yaml': 'YAML'
+	xrb: 'XRB',
+	xml: 'XML',
+	yaml: 'YAML'
 };
 
 // Process each file
-const files = readdirSync(examplesDir).filter(f => 
-	f.endsWith('.html') && !excludeFiles.has(f)
+const files = readdirSync(examplesDir).filter(
+	f => f.endsWith('.html') && !excludeFiles.has(f)
 );
 
 console.log(`Processing ${files.length} files...`);
@@ -65,18 +65,18 @@ console.log(`Processing ${files.length} files...`);
 files.forEach(file => {
 	const filePath = join(examplesDir, file);
 	let content = readFileSync(filePath, 'utf8');
-	
+
 	const baseName = file.replace('.html', '');
 	const langName = languageNames[baseName] || baseName;
-	
+
 	// Check if already updated
 	if (content.includes('examples.css')) {
 		console.log(`✓ ${file} already updated`);
 		return;
 	}
-	
+
 	console.log(`Updating ${file}...`);
-	
+
 	// Replace  with inline styles
 	content = content.replace(
 		/[\s\S]*?<\/head>/,
@@ -87,7 +87,7 @@ files.forEach(file => {
 	
 `
 	);
-	
+
 	// Add header if not present
 	if (!content.includes('
')) { content = content.replace( @@ -105,7 +105,7 @@ files.forEach(file => { ` ); } - + // Wrap examples in div.example if needed if (!content.includes('class="example"')) { // Simple wrapping for code blocks @@ -127,7 +127,7 @@ files.forEach(file => { '$1\n\t\n\t\n\t