Skip to content

Commit

Permalink
[BETA] Update tests, builds, and css minification
Browse files Browse the repository at this point in the history
  • Loading branch information
The-Best-Codes committed Nov 23, 2024
1 parent 0bddcfb commit 8697174
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 42 deletions.
36 changes: 20 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "best-highlight",
"version": "0.0.13",
"version": "0.0.2-beta.0",
"description": "A lightweight syntax highlighter",
"type": "module",
"main": "./dist/index.cjs",
Expand All @@ -14,7 +14,7 @@
"exports": {
".": {
"types": "./dist/index.d.ts",
"browser": "./dist/index.browser.js",
"browser": "./dist/browser/index.global.js",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
Expand All @@ -26,31 +26,35 @@
}
},
"scripts": {
"build": "bun run build:js && bun run build:css && bun run minify:css && bun run build:browser",
"build:js": "tsup src/index.ts --format cjs,esm --dts --minify",
"build:css": "mkdir -p dist/themes && cp src/themes/*.css dist/themes/",
"minify:css": "tsup dist/themes/*.css --minify --clean=false --outDir dist/themes",
"build": "rm -rf dist && bun run build:types && bun run build:js && bun run build:css && bun run build:browser",
"build:js": "bun run build:js.esm && bun run build:js.cjs",
"build:js.esm": "bun build src/index.ts --outfile dist/index.js --format esm --minify",
"build:js.cjs": "bun build src/index.ts --outfile dist/index.cjs --format cjs --minify",
"build:css": "bun run build:css.copy && bun run build:css.minify",
"build:css.copy": "mkdir -p dist/themes && cp src/themes/*.css dist/themes/",
"build:css.minify": "for file in dist/themes/*.css; do bun ./scripts/minify-css.ts \"$file\" > \"${file%.css}.min.css\" && mv \"${file%.css}.min.css\" \"$file\"; done",
"build:browser": "tsup src/index.ts --format iife --global-name bestHighlight --minify --out-dir dist/browser",
"build:types": "rollup -c rollup.dts.config.js",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"prepublish": "rm -rf dist && bash ./scripts/compress-readme.sh",
"dev": "bun run dev:js",
"dev:js": "bun build src/index.ts --outfile dist/index.js --format esm --declaration --watch",
"test": "bun test",
"test:coverage": "bun test --coverage",
"prepublish": "bash ./scripts/compress-readme.sh",
"postpublish": "bash ./scripts/restore-readme.sh",
"prepublishOnly": "bun run prepublish && bun run build"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@vitest/coverage-v8": "^2.1.5",
"@types/bun": "^1.1.13",
"dts-minify": "^0.3.3",
"eslint": "^9.15.0",
"globals": "^15.12.0",
"jsdom": "^25.0.1",
"terser": "^5.36.0",
"tsup": "^8.3.5",
"typescript": "^5.7.2",
"typescript-eslint": "^8.15.0",
"vitest": "^2.1.5"
"rollup": "^4.27.3",
"rollup-plugin-dts": "^6.1.1",
"typescript": "^5.7.2"
},
"files": [
"dist"
Expand Down
30 changes: 30 additions & 0 deletions rollup.dts.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import dts from 'rollup-plugin-dts';
import { createMinifier } from 'dts-minify';
import * as ts from 'typescript';
import { writeFileSync } from 'fs';

const minifier = createMinifier(ts);

const minifyPlugin = {
name: 'minify-dts',
writeBundle(options, bundle) {
for (const fileName in bundle) {
const file = bundle[fileName];
if (fileName.endsWith('.d.ts')) {
const minified = minifier.minify(file.code, {
keepJsDocs: false
});
writeFileSync(options.file, minified);
}
}
}
};

export default {
input: './src/index.ts',
output: {
file: 'dist/index.d.ts',
format: 'es'
},
plugins: [dts(), minifyPlugin]
};
21 changes: 21 additions & 0 deletions scripts/minify-css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bun
export {};

const inputFile = Bun.argv[2];
if (!inputFile) {
console.error('Please provide a CSS file to minify');
process.exit(1);
}

const css = await Bun.file(inputFile).text();

// Simple CSS minification
const minified = css
.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\/|[\r\n\t]+/g, '') // Remove comments and whitespace
.replace(/ {2,}/g, ' ') // Remove multiple spaces
.replace(/ ([{:}]) /g, '$1') // Remove spaces around brackets and colons
.replace(/([{:}]) /g, '$1') // Remove spaces after brackets and colons
.replace(/;}/g, '}') // Remove last semicolon in block
.trim();

console.log(minified);
66 changes: 40 additions & 26 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { describe, it, expect } from 'vitest';
import { describe, expect, test } from "bun:test";
import { tokenize, highlight, highlightElement } from './index';

// Skip DOM-related tests when running in Bun
const describeDOM = process.versions.bun ? describe.skip : describe;

describe('tokenize', () => {
it('should tokenize JavaScript code correctly', () => {
test('should tokenize JavaScript code correctly', () => {
const code = 'const x = 42; // comment';
const tokens = tokenize(code, 'javascript');

expect(tokens).toEqual([
{ type: 'keyword', content: 'const' },
{ type: 'text', content: ' ' },
{ type: 'text', content: 'x' },
{ type: 'identifier', content: 'x' },
{ type: 'text', content: ' ' },
{ type: 'operator', content: '=' },
{ type: 'text', content: ' ' },
Expand All @@ -20,14 +23,14 @@ describe('tokenize', () => {
]);
});

it('should tokenize Python code correctly', () => {
test('should tokenize Python code correctly', () => {
const code = 'def hello(): # function';
const tokens = tokenize(code, 'python');

expect(tokens).toEqual([
{ type: 'keyword', content: 'def' },
{ type: 'text', content: ' ' },
{ type: 'text', content: 'hello' },
{ type: 'identifier', content: 'hello' },
{ type: 'punctuation', content: '(' },
{ type: 'punctuation', content: ')' },
{ type: 'punctuation', content: ':' },
Expand All @@ -36,13 +39,13 @@ describe('tokenize', () => {
]);
});

it('should handle unknown languages', () => {
test('should handle unknown languages', () => {
const code = 'some code';
const tokens = tokenize(code, 'unknown');
expect(tokens).toEqual([{ type: 'text', content: 'some code' }]);
});

it('should tokenize TypeScript code correctly', () => {
test('should tokenize TypeScript code correctly', () => {
const code = 'interface User { name: string; }';
const tokens = tokenize(code, 'typescript');

Expand All @@ -56,30 +59,35 @@ describe('tokenize', () => {
{ type: 'identifier', content: 'name' },
{ type: 'punctuation', content: ':' },
{ type: 'text', content: ' ' },
{ type: 'identifier', content: 'string' },
{ type: 'type', content: 'string' },
{ type: 'punctuation', content: ';' },
{ type: 'text', content: ' ' },
{ type: 'punctuation', content: '}' }
]);
});

it('should tokenize HTML code correctly', () => {
test('should tokenize HTML code correctly', () => {
const code = '<div class="container">Hello</div>';
const tokens = tokenize(code, 'html');

expect(tokens).toEqual([
{ type: 'tag', content: '<div' },
{ type: 'text', content: ' ' },
{ type: 'attribute', content: 'class' },
{ type: 'text', content: '=' },
{ type: 'punctuation', content: '=' },
{ type: 'string', content: '"container"' },
{ type: 'tag', content: '>' },
{ type: 'text', content: 'Hello' },
{ type: 'tag', content: '</div>' }
{ type: 'text', content: '>' },
{ type: 'text', content: 'H' },
{ type: 'text', content: 'e' },
{ type: 'text', content: 'l' },
{ type: 'text', content: 'l' },
{ type: 'text', content: 'o' },
{ type: 'tag', content: '</div' },
{ type: 'text', content: '>' }
]);
});

it('should tokenize CSS code correctly', () => {
test('should tokenize CSS code correctly', () => {
const code = '.container { color: #ff0000; }';
const tokens = tokenize(code, 'css');

Expand All @@ -88,17 +96,17 @@ describe('tokenize', () => {
{ type: 'text', content: ' ' },
{ type: 'punctuation', content: '{' },
{ type: 'text', content: ' ' },
{ type: 'property', content: 'color' },
{ type: 'selector', content: 'color' },
{ type: 'punctuation', content: ':' },
{ type: 'text', content: ' ' },
{ type: 'value', content: '#ff0000' },
{ type: 'selector', content: '#ff0000' },
{ type: 'punctuation', content: ';' },
{ type: 'text', content: ' ' },
{ type: 'punctuation', content: '}' }
]);
});

it('should tokenize JSON code correctly', () => {
test('should tokenize JSON code correctly', () => {
const code = '{"name": "John", "age": 30}';
const tokens = tokenize(code, 'json');

Expand All @@ -118,12 +126,18 @@ describe('tokenize', () => {
]);
});

it('should tokenize Markdown code correctly', () => {
test('should tokenize Markdown code correctly', () => {
const code = '# Title\n**bold** *italic*';
const tokens = tokenize(code, 'markdown');

expect(tokens).toEqual([
{ type: 'heading', content: '# Title' },
{ type: 'heading', content: '#' },
{ type: 'text', content: ' ' },
{ type: 'text', content: 'T' },
{ type: 'text', content: 'i' },
{ type: 'text', content: 't' },
{ type: 'text', content: 'l' },
{ type: 'text', content: 'e' },
{ type: 'text', content: '\n' },
{ type: 'emphasis', content: '**bold**' },
{ type: 'text', content: ' ' },
Expand All @@ -133,7 +147,7 @@ describe('tokenize', () => {
});

describe('highlight', () => {
it('should generate HTML with correct classes', () => {
test('should generate HTML with correct classes', () => {
const code = 'const x = 42;';
const html = highlight(code, 'javascript');

Expand All @@ -142,15 +156,15 @@ describe('highlight', () => {
expect(html).toContain('class="bh-npm-token bh-npm-punctuation"');
});

it('should escape HTML special characters', () => {
test('should escape HTML special characters', () => {
const code = 'const html = "<div>";';
const html = highlight(code, 'javascript');

expect(html).toContain('&lt;div&gt;');
expect(html).not.toContain('<div>');
});

it('should escape all HTML special characters', () => {
test('should escape all HTML special characters', () => {
const code = 'const html = "<div class=\'test\'>&";';
const html = highlight(code, 'javascript');

Expand All @@ -161,8 +175,8 @@ describe('highlight', () => {
});
});

describe('highlightElement', () => {
it('should highlight DOM element content', () => {
describeDOM('highlightElement', () => {
test('should highlight DOM element content', () => {
// Create a mock element
const element = document.createElement('pre');
element.textContent = 'const x = 42;';
Expand All @@ -174,7 +188,7 @@ describe('highlightElement', () => {
expect(element.classList.contains('bh-npm-highlight')).toBe(true);
});

it('should handle missing language attribute', () => {
test('should handle missing language attribute', () => {
const element = document.createElement('pre');
element.textContent = 'some text';

Expand All @@ -183,7 +197,7 @@ describe('highlightElement', () => {
expect(element.innerHTML).toContain('class="bh-npm-token bh-npm-text"');
});

it('should handle empty text content', () => {
test('should handle empty text content', () => {
const element = document.createElement('pre');
element.textContent = '';

Expand Down

0 comments on commit 8697174

Please sign in to comment.