diff --git a/README.md b/README.md index 8b391a4..88dc1ab 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ The following options may be passed to the `highlight` function. string: '\x1b[32m', // Strings special: '\x1b[33m', // Special characters bracket: '\x1b[33m', // Brackets (parentheses) + comment: '\x1b[2m\x1b[90m', // Comments clear: '\x1b[0m' // Clear (inserted after each match) } ``` diff --git a/lib/index.d.ts b/lib/index.d.ts index 8f1f7a1..28a3cfd 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -10,6 +10,7 @@ declare module 'sql-highlight' { string: string; special: string; bracket: string; + comment: string; clear: string; }; } diff --git a/lib/index.js b/lib/index.js index 353c7ae..ba2d539 100644 --- a/lib/index.js +++ b/lib/index.js @@ -14,6 +14,7 @@ const DEFAULT_OPTIONS = { string: '\x1b[32m', special: '\x1b[33m', bracket: '\x1b[33m', + comment: '\x1b[2m\x1b[90m', clear: '\x1b[0m' } } @@ -26,6 +27,9 @@ const highlighters = [ // Note: Repeating string escapes like 'sql''server' will also work as they are just repeating strings /(?'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*`)/, + /(?--[^\n\r]*|#[^\n\r]*|\/\*(?:[^*]|\*(?!\/))*\*\/)/, + + // Future improvement: Comments should be allowed between the function name and the opening parenthesis /\b(?\w+)(?=\s*\()/, /(?[()])/, diff --git a/test/debug.js b/test/debug.js index bbd096c..10610d8 100644 --- a/test/debug.js +++ b/test/debug.js @@ -26,4 +26,6 @@ console.log(highlight('DROP PROCEDURE IF EXISTS `some-database`.`some-table`;')) console.log(highlight('SELECT * FROM a;SELECT * FROM b;')) +console.log(highlight('SELECT foo /* comment, not "keyword" WHERE GROUP */ FROM bar; -- comment\nSELECT * FROM baz;')) + console.log(highlight("select * from a where b = 'array>';", { html: true })) diff --git a/test/index.test.js b/test/index.test.js index 775d5a0..a208a3a 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -8,6 +8,7 @@ const OPTIONS = { string: '[string]', special: '[special]', bracket: '[bracket]', + comment: '[comment]', clear: '[clear]' } } @@ -114,6 +115,26 @@ describe('unicode', () => { expect(hlUni('SELECT * FROM a;SELECT * FROM b;')) .toBe('[keyword]SELECT[clear] [special]*[clear] [keyword]FROM[clear] a[special];[clear][keyword]SELECT[clear] [special]*[clear] [keyword]FROM[clear] b[special];[clear]') }) + + it('comment single line', () => { + expect(hlUni('-- comment 1 "comment" /* still */ comment 2\nSELECT `not comment`; -- comment 3')) + .toBe('[comment]-- comment 1 "comment" /* still */ comment 2[clear]\n[keyword]SELECT[clear] [string]`not comment`[clear][special];[clear] [comment]-- comment 3[clear]') + }) + + it('comment mysql', () => { + expect(hlUni('# comment 1 "comment" /* still */ comment 2\nSELECT `not comment`; # comment 3')) + .toBe('[comment]# comment 1 "comment" /* still */ comment 2[clear]\n[keyword]SELECT[clear] [string]`not comment`[clear][special];[clear] [comment]# comment 3[clear]') + }) + + it('comment multiline', () => { + expect(hlUni('SELECT /* this is, a "comment" */ "not /*comment*/" /***also*comment***/')) + .toBe('[keyword]SELECT[clear] [comment]/* this is, a "comment" */[clear] [string]"not /*comment*/"[clear] [comment]/***also*comment***/[clear]') + }) + + it('not a comment', () => { + expect(hlUni('"id -- not comment /* still */ not"')) + .toBe('[string]"id -- not comment /* still */ not"[clear]') + }) }) describe('html', () => { @@ -211,6 +232,26 @@ describe('html', () => { expect(hlHtml("select * from a where b = 'array>';")) .toBe('select * from a where b = 'array<map<string,string>>';') }) + + it('comment single line', () => { + expect(hlHtml('-- comment 1 "comment" /* still */ comment 2\nSELECT `not comment`; -- comment 3')) + .toBe('-- comment 1 "comment" /* still */ comment 2\nSELECT `not comment`; -- comment 3') + }) + + it('comment mysql', () => { + expect(hlHtml('# comment 1 "comment" /* still */ comment 2\nSELECT `not comment`; # comment 3')) + .toBe('# comment 1 "comment" /* still */ comment 2\nSELECT `not comment`; # comment 3') + }) + + it('comment multiline', () => { + expect(hlHtml('SELECT /* this is, a "comment" */ "not /*comment*/" /***also*comment***/')) + .toBe('SELECT /* this is, a "comment" */ "not /*comment*/" /***also*comment***/') + }) + + it('not a comment', () => { + expect(hlHtml('"id -- not comment /* still */ not"')) + .toBe('"id -- not comment /* still */ not"') + }) }) describe('getSegments', () => {