Да, я знаю, что такое синтаксический анализ. И знаю много разных библиотек для подсветки чего угодно. Только это всё не то, когда надо подсветить простенький примерчик, не содержащий всяких кодоизвращений. И уж совсем негоже тянуть для этого много-много байт _правильно_ разбирающих _любой_ код.
Для случаев без кодоизврата (а их большинство) можно использовать такой код:

Обратите внимание на баг в последней строке. Об этом разговор далее
Данный код заточен на javascript, о чём можно судить по ключевым словам. Сделать код понимающим любой Си-подобный язык не представляет труда.
Возиться с многострочными комментариями я не стал, как и с многострочными строками, ибо не так уж частно многострочные комменты используются в примерах, а к многострочным строкам в javascript я как-то не привык.
Еще чем плох данный подход — текст «плоский», то есть этот, с позволения сказать, анализатор, считает слово for внутри строки или комментария таким же ключевым словом, как и все их. Нас это не устраивает, поэтому используются css правила .str span и .comm span, дабы возложить на плечи CSS распознавание блочной структуры кода. Одна проблема возникает — когда строка содержит комментарий, который содержит ключевое слово или пользовательскую функцию. В этом случае мы не взирая на окончание строки всё считаем строкой (до символа перевода строки).
И ещё, двойных кавычек не существует. Можно добавить еще один replace:
Но меня от этого что-то удерживает.
chainable, multiple
upd: учтя исправления и дополнения, получил скрипт сам себя подсвечивающий, а вот версия от etcdema: dema.ru/syntax
Для случаев без кодоизврата (а их большинство) можно использовать такой код:
code = code // ключевые слова (список неполон, написал, что в голову пришло) .replace(/(var|function|typeof|new|return|if|for|in|while|break|do|continue|switch|case)([^a-z0-9\$_])/gi, '<span class="kwrd">$1</span>$2') // всякие скобочки .replace(/(\{|\}|\]|\[|\|)/gi,'<span class="kwrd">$1</span>') // однострочные комментарии .replace(/(\/\/[^\n\r]*(\n|\r\n))/g,'<span class="comm">$1</span>') // строки .replace(/('.*?')/g,'<span class="str">$1</span>') // функции (когда после идентификатора идет скобка) .replace(/([a-z\_\$][a-z0-9_]*)\(/gi,'<span class="func">$1</span>(') // не люблю восьмизначные табы, пусть лучше будет 4 пробела .replace(/\t/g,' ');
CSS
.str{color:red}/* Строки красные */ .func{color:blue}/* Юзер-функции синие */ .comm{color:orange}/* Комменты оранжевые */ .kwrd{font-weight:bold}/* Ключевые слова полужирные */ .str span{color:red;font-weight:normal}/* Всё внутри строки — строка */ .comm span{color:orange;font-weight:normal}/* Всё внутри комментария — комментарий */
Пример

Обратите внимание на баг в последней строке. Об этом разговор далее
Область применения, баги
Данный код заточен на javascript, о чём можно судить по ключевым словам. Сделать код понимающим любой Си-подобный язык не представляет труда.
Возиться с многострочными комментариями я не стал, как и с многострочными строками, ибо не так уж частно многострочные комменты используются в примерах, а к многострочным строкам в javascript я как-то не привык.
Еще чем плох данный подход — текст «плоский», то есть этот, с позволения сказать, анализатор, считает слово for внутри строки или комментария таким же ключевым словом, как и все их. Нас это не устраивает, поэтому используются css правила .str span и .comm span, дабы возложить на плечи CSS распознавание блочной структуры кода. Одна проблема возникает — когда строка содержит комментарий, который содержит ключевое слово или пользовательскую функцию. В этом случае мы не взирая на окончание строки всё считаем строкой (до символа перевода строки).
И ещё, двойных кавычек не существует. Можно добавить еще один replace:
.replace(/(".*?")/g,'<span class="str">$1</span>')
Но меня от этого что-то удерживает.
Бонус: плагин для jQuery
chainable, multiple
(function($){ $.fn.syntax = function(){ return this.each(function(){ var jqCode = $(this); var code = jqCode.text(); code = code .replace(/(var|function|typeof|new|return|if|for|in|while|break|do|continue|case|switch)([^a-z0-9\$_])/gi,'<span class="kwrd">$1</span>$2') .replace(/(\{|\}|\]|\[|\|)/gi,'<span class="kwrd">$1</span>') .replace(/(\/\/[^\n\r]*(\n|\r\n))/g,'<span class="comm">$1</span>') .replace(/('.*?')/g,'<span class="str">$1</span>') .replace(/([a-z\_\$][a-z0-9_]*)\(/gi,'<span class="func">$1</span>(') .replace(/\t/g,' '); jqCode.html(code); }); } })(jQuery); // пример вызова $('pre#code').syntax(); // подсветка конкретного блока pre с id=code $('pre').syntax(); // подсветка всех pre
Усовершенствованный вариант от etcdema
function Syntax(code){ var comments = []; // Тут собираем все каменты var strings = []; // Тут собираем все строки var res = []; // Тут собираем все RegExp var all = { 'C': comments, 'S': strings, 'R': res }; var safe = { '<': '<', '>': '>', '&': '&' }; return code // Маскируем HTML .replace(/[<>&]/g, function (m) { return safe[m]; }) // Убираем каменты .replace(/\/\*[\s\S]*\*\//g, function(m) { var l=comments.length; comments.push(m); return '~~~C'+l+'~~~'; }) .replace(/([^\\])\/\/[^\n]*\n/g, function(m, f) { var l=comments.length; comments.push(m); return f+'~~~C'+l+'~~~'; }) // Убираем regexp .replace(/\/(\\\/|[^\/\n])*\/[gim]{0,3}/g, function(m) { var l=res.length; res.push(m); return '~~~R'+l+'~~~'; }) // Убираем строки .replace(/([^\\])((?:'(?:\\'|[^'])*')|(?:"(?:\\"|[^"])*"))/g, function(m, f, s) { var l=strings.length; strings.push(s); return f+'~~~S'+l+'~~~'; }) // Выделяем ключевые слова .replace(/(var|function|typeof|new|return|if|for|in|while|break|do|continue|switch|case)([^a-z0-9\$_])/gi, '<span class="kwrd">$1</span>$2') // Выделяем скобки .replace(/(\{|\}|\]|\[|\|)/gi, '<span class="gly">$1</span>') // Выделяем имена функций .replace(/([a-z\_\$][a-z0-9_]*)[\s]*\(/gi, '<span class="func">$1</span>(') // Возвращаем на место каменты, строки, RegExp .replace(/~~~([CSR])(\d+)~~~/g, function(m, t, i) { return '<span class="'+t+'">'+all[t][i]+'</span>'; }) // Выставляем переводы строк .replace(/\n/g, '<br/>') // Табуляцию заменяем неразрывными пробелами .replace(/\t/g, ' '); }Тут понадобятся другие стили:
.S{color:red}/* Строки красные */ .func{color:blue}/* Юзер-функции синие */ .C{color:orange}/* Комменты оранжевые */ .kwrd{font-weight:bold}/* Ключевые слова полужирные */ .R{color:gray} /*Серые регвыражения */
upd: учтя исправления и дополнения, получил скрипт сам себя подсвечивающий, а вот версия от etcdema: dema.ru/syntax