Семантика, стандарты и использование атрибута lang для исходного кода в разметке

Я не смог найти авторитетных объяснений, микроформатов или руководств для следующего, поэтому я открываю его. Если я что-то пропустил, говорите!

Допустим, у вас есть HTML-страница, содержащая пример некоторого исходного кода программирования внутри элемента <pre>:

<pre>
    # code...
</pre>

(Обновление: как указывает Пекка ниже, <code> может быть лучше, чем <pre>, но следующие примеры/обсуждения могут относиться к обоим. И, как указывает Брайан Кэмпбелл, оба элемента, конечно, следует использовать для предварительно отформатированный код)

А теперь: как семантически правильно и в соответствии со спецификацией объявить язык программирования содержимого блока <pre>?

Эту информацию было бы полезно включить в разметку семантически непротиворечивым образом.

Очевидным выбором с семантической точки зрения было бы использование атрибута lang:

<pre lang="ruby">

Но согласно спецификации HTML 4, раздел 8.1.1:

Значением атрибута lang является код языка, который идентифицирует естественный язык [...] Компьютерные языки явным образом исключаются из языковых кодов.

(выделено мной)

Кроме того, «ruby» в любом случае не является стандартным кодом языка.

Спецификация позволяет добавлять коды «экспериментального» или «частного использования» с использованием основного тега x. Пример из спецификации: lang="x-klingon".

Теоретически вы могли бы использовать x-ruby, x-java и так далее для объявления языка программирования, содержащегося в блоке <pre>, за исключением того, что спецификация не одобряет использование атрибута lang для языков программирования в целом.

спецификация HTML 5 по этой теме не соответствует внести ясность. В самой спецификации явно не упоминаются «естественные» и «программные» языки. Вместо этого он отсылает читателя к BCP 47, в котором говорится (снова):

Языковые теги помогают идентифицировать языки [...], но исключают языки, не предназначенные в первую очередь для человеческого общения, такие как языки программирования.

Однако далее упоминается (в разделе 4.1, стр. 56) вложенный тег основного языка zxx, который:

определяет контент, для которого языковая классификация не подходит или не применяется. Некоторые примеры могут включать инструментальную или электронную музыку [...] или исходный код программирования.

(выделено мной)

Опять же, спецификация кажется противоречащей самой себе, но она открывает возможность использования zxx-x-ruby (или аналогичного) как полностью соответствующего спецификации способа объявления чего-либо написанным на каком языке (только не на человеческий) и объявление конкретного (нечеловеческого) задействованного языка.

Итак, есть ли какое-то подобие стандарта/микроформата/микросинтаксиса/джентльменского соглашения/что-нибудь о том, что делать?

Лично мне нравится zxx-x-ruby как самый полный. x-ruby сам по себе короче и аккуратнее, конечно, но, если я не ошибаюсь, блок <pre> все равно наследует основной язык своего родителя (например, en или fr или аналогичный).


Приложение:

Как упоминает Пекка ниже, тег <code>, вероятно, был бы более подходящим, и семантически было бы очень просто сказать <code lang="...">. Однако тег <code> также является встроенным элементом, и я изначально думал только о более длинных прогонах исходного кода, т.е. об объявлении языка для всех элементов <code>, содержащихся в элементах <pre> блочного уровня.

К счастью, атрибут lang является глобальным и может применяться к любому элементу, поэтому любой из них будет работать.

Во-вторых: я случайно везде набрал «zzx» вместо правильного «zxx»! Это одна "z", две "x". Извиняюсь за путаницу.


person Flambino    schedule 27.02.2011    source источник
comment
BCP 47 упоминает zxx, а не zzx для неязыкового контента.   -  person Brian Campbell    schedule 27.02.2011
comment
@ Брайан Да, я знаю, я понял свою ошибку и исправил ее примерно в то же время, когда ты писал свой комментарий :)   -  person Flambino    schedule 27.02.2011
comment
Почему блок pre по-прежнему наследует основной язык? @lang specifies the language for the element's contents and text attributes из html.spec.whatwg. org/multipage/, кажется, не согласен, и x- кажется идеально подходящим, поскольку он предназначен для Non-linguistic языков, включая machine-readable data (который включает программы, поскольку программы являются данными для машин Тьюринга).   -  person Xenos    schedule 16.10.2019


Ответы (2)


Чтобы ответить на этот вопрос, мы должны рассмотреть две вещи; любые потенциально важные спецификации и то, что на самом деле делается в реальном мире. Вы уже упомянули, что говорится в соответствующих спецификациях об атрибуте lang; обычно он используется для обозначения человеческого языка упоминаемого контента, а не языка программирования. Хотя в BCP 47 упоминается тег zxx для неязыкового контента, я не думаю, что действительно уместно использовать атрибут lang и вложенный тег zxx для указания языка программирования. Причина в том, что большая часть исходного кода на самом деле имеет некоторый лингвистический контент, написанный на естественном языке; комментарии, имена переменных, строки и т.п. Вероятно, для их указания следует использовать атрибут lang, особенно в таких случаях, как использование символов CJK, когда выбор шрифта может основываться на атрибуте lang. Язык программирования, содержащийся в примере кода, на самом деле ортогонален содержащемуся в нем человеческому языку; объединение этих двух вещей, скорее всего, приведет к путанице, а не к ясности.

Итак, давайте проверим спецификации на наличие альтернативы атрибуту lang. Как указывает Пекка в другом ответе, элемент <code> более семантически значим для разметки исходного кода, чем элемент <pre>, поэтому давайте проверим его. Согласно спецификации HTML5:

Элемент code представляет собой фрагмент компьютерного кода. Это может быть имя элемента XML, имя файла, компьютерная программа или любая другая строка, распознаваемая компьютером.

Хотя не существует формального способа указать язык размечаемого компьютерного кода, авторы, желающие пометить code элементов с помощью используемого языка, т.е. чтобы сценарии подсветки синтаксиса могли использовать правильные правила, можно сделать это, добавив к элементу класс с префиксом «language-».

...

В следующем примере показано, как можно разметить блок кода с помощью элементов pre и code.

<pre><code class="language-pascal">var i: Integer;
begin
   i := 1;
end.</code></pre>

В этом примере используется класс для указания используемого языка.

Теперь это не формальная спецификация, а просто неформальная рекомендация о том, как вы можете использовать класс для указания представляемого языка. В примере также показано, как использовать теги <pre> и <code> для разметки блока кода.

Мы можем поискать какие-либо стандарты в других местах, но я их не нашел; нет микроформатов для форматирования кода, и я не нашел других спецификаций, в которых это упоминается. Итак, мы переходим к тому, что люди на самом деле делают. Лучший способ узнать это — посмотреть, что делают библиотеки подсветки синтаксиса HTML, поскольку они являются основными производителями и потребителями кода, встроенного в веб-страницы, в которых язык действительно имеет значение.

Существует два основных типа подсветки синтаксиса HTML; те, которые работают на сервере или в автономном режиме, на Ruby, Python или PHP и создают статический HTML и CSS для отображения в браузере, и те, которые написаны на JavaScript, которые находят и выделяют <pre> или <code> элементов на стороне клиента. Вторая категория более интересна, так как им нужно определить язык из предоставленного им HTML; в первой категории вы обычно указываете язык вручную через API или с помощью какого-либо механизма, характерного для вашей вики, блога или синтаксиса CMS, и поэтому нет фактического потребителя какой-либо языковой информации, которая может быть встроена в HTML. Мы рассмотрим обе категории для полноты картины.

Для подсветки синтаксиса JavaScript я нашел следующее с примерами их синтаксиса для указания блока кода и его языка:

  • SyntaxHighliger: <pre class="brush: html">...</pre>. Похоже, что полностью игнорирует то, как следует использовать class, вводя собственный синтаксис для атрибутов class на основе синтаксиса CSS с ключевым словом brush, используемым для указания языка. Также есть возможность использовать тег <script>, чтобы упростить копирование и вставку кода без экранирования <, используя тот же синтаксис class.
  • Highlight.js: <pre><code class="html">...</code></pre> или class="language-html" или то же самое на <pre>. Это дает вам несколько вариантов, один из которых соответствует рекомендации спецификации HTML5, а другой просто использует чистое имя языка в качестве имени класса.
  • SHJS: <pre class="sh_html">...</pre>. Использует собственный префикс для имен языков в классе и работает только с <pre>, но не с другими элементами.
  • beautyOfCode: <pre class="code"><code class="html">...</code></pre>. Основан на SyntaxHighlighter, но с менее странным синтаксисом. Требуется тег <pre> с классом code и тег code с классом, указывающим язык.
  • Чили: <code class="html">...</code>. Использует только тег <code> и использует голый язык в качестве имени класса.
  • Lighter.js: <pre class="html">...</code>. Использует голый язык в качестве имени класса. Вы выбираете элементы, к которым он будет применяться, используя API, но пример демонстрирует это на тегах <pre>.
  • DlHighlight: <pre name="code" class="html">...</pre>. Использует голый язык в качестве имени класса. Вы выбираете через API, какой тип элемента выделить (в примере используется pre) и значение атрибута name, которое нужно искать, чтобы указать, что вы хотите подсветку синтаксиса. Я считаю, что это злоупотребление атрибутом name.
  • google-code-prettify: <pre class="prettyprint lang-html">. Использует имена классов с префиксом lang-, чтобы указать язык, и класс prettyprint, чтобы указать, что вы хотите подсветку синтаксиса. Языковой класс является необязательным; он попытается автоматически определить язык, если он не указан.
  • JUSH: <code class="jush-html">...</code> или <code class="language-html">...</code>. Использует тег code с языками в классе с префиксом jush- или language-.
  • Rainbow: <pre><code data-language="javascript">...</code></pre> использует пользовательский атрибут data-language, применяемый либо к элементу <code>, либо к элементу <pre>, чтобы для поддержки таких сайтов, как Tumblr, которые удаляют <code> элементов.
  • Prism: <pre><code class="language-css">...</code></pre> соответствует спецификации HTML5 для вложенных <pre> и <code>, а также рекомендации по имени класса.

Для серверной и автономной подсветки синтаксиса большинство (CodeRay, UltraViolet, пигменты, Highlight) вообще не встраивают какую-либо информацию о языке в HTML-код, который они выводят. GeSHi — единственный, который я нашел, который включает язык, как <pre class="html">...</pre>, тег <pre> с голым названием языка как класс.

Из этого списка, похоже, нет реального консенсуса. Самый популярный вариант — просто использовать имя языка в качестве класса. Следующим по популярности является использование некоторой формы имени языка с префиксом, либо с префиксом имени библиотеки, либо lang-, либо language-. Есть несколько, которые имеют свои собственные странные соглашения или вообще не указывают язык в HTML.

Хотя единственное, что достаточно распространено, чтобы быть стандартом де-факто, — это использование имени языка в качестве класса, я бы рекомендовал использовать то, что рекомендует спецификация HTML5, имя класса language-, за которым следует имя языка. Это поддерживается несколькими подсветчиками синтаксиса, остальные, вероятно, могут быть легко изменены для его поддержки. Оно менее двусмысленно и с меньшей вероятностью конфликтует с другими классами, чем просто имя языка как класса. И, даже если формально не указано, то хотя бы упоминается в спецификации.

Я бы также использовал тег <code> для обозначения исходного кода, голого или встроенного в тег <pre>; комбинация тега <code> и класса с префиксом language- может использоваться, чтобы указать, что у вас есть исходный код на определенном языке, и может использоваться, чтобы указать, что вы хотите, чтобы он был выделен, и более четкий и лучше соответствует семантике элементов, чем некоторые другие индикаторы, используемые библиотеками подсветки синтаксиса. В случаях, когда тег <code> нельзя использовать, например, для встраивания в сайты, которые принимают только ограниченное подмножество HTML, такое как Tumblr, вероятно, лучше всего использовать тег <pre> с тем же соглашением о классах.

изменить, чтобы добавить: спецификация CommonMark, которая пытается стандартизировать Markdown, чтобы реализации могут быть совместимы, создавая один и тот же HTML-код при одних и тех же входных данных, также принял это предлагаемое соглашение. Он добавляет в Markdown изолированные блоки кода, окруженные ``` или ~~~, которые могут быть проще в использовании, чем блоки кода на основе отступов. Сразу за открывающимся забором может быть информационная строка, которая определяется как:

Информационная строка может быть предоставлена ​​после ограждения кода открытия. Открывающие и закрывающие пробелы будут удалены, а первое слово с префиксом language- будет использоваться в качестве значения атрибута class элемента code внутри окружающего элемента pre.

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

  • вскрытие, черная пятница, уценка haskell: <pre><code class="python">...</code></pre>
  • отмечен: <pre><code class="lang-python">...</code></pre>
  • общая метка, синтаксический разбор, cebe/уценка: <pre><code class="language-python">...</code></pre>
  • скряга, минимум: <pre class="python">...</pre>
  • pandoc: <div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">...</code></pre></div> (совсем перебор)
  • Маруку: <pre class="python"><code class="python">...</code></pre>

Глядя на другие языки разметки документов, которые конвертируются в HTML и имеют некоторое представление о блоках кода:

  • AsciiDoc: <pre>...</pre>; просто использует Pygments для выделения и не включает информацию о языке в HTML.
  • rst2html дал мне <pre class="code python literal-block">...</pre>, выделил пигментами.
  • Сфинкс: <div class="highlight-python"><div class="highlight"><pre>...</pre></div></div>, также выделенный пигментами.

Итак, в целом довольно большое разнообразие вариантов выбора в разных проектах, но, похоже, есть некоторое движение к стандартизации <pre><code class="language-python">...</code></pre>.

person Brian Campbell    schedule 27.02.2011
comment
Я не мог бы попросить лучшего или более полного ответа - спасибо! Ваша точка зрения об исходном коде, содержащем естественный язык, хорошо принята. С этой точки зрения, я предполагаю, что тег zxx предназначен для кода, который может быть прочитан только компьютером (например, скомпилированный код). Вместо этого использование имен классов также было бы решением, которое я бы выбрал вместо чего-то лучшего (на что я надеялся, что представлен тег zxx). Наконец, несмотря на то, что мой вопрос сосредоточен на <pre>, элемент <code>, конечно же, тоже будет использоваться, как в примере со спецификацией HTML 5. Еще раз спасибо! - person Flambino; 27.02.2011
comment
Меня все еще интересует одна вещь: если не учитывать тег zxx, можно ли использовать lang="x-ruby"? Насколько я понимаю, это было бы правильно, хотя и столь же неформально, как использование имен классов, поскольку это был бы закрытый (x) тег. - person Flambino; 27.02.2011
comment
@Flambino Я думаю, что у него та же проблема, что и у zxx; тег lang и языковые коды BCP 47 предназначены для представления естественного языка, а не языка программирования. В HTML 4 это прямо указано, HTML5 ссылается на BCP 47, в котором говорится: «Языковые теги используются для идентификации языков, будь то разговорный, письменный, подписанный или иным образом сигнализированный, для целей общения». Сюда входят сконструированные и искусственные языки, но исключаются языки, не предназначенные в первую очередь для человеческого общения, такие как языки программирования. - person Brian Campbell; 28.02.2011
comment
@Flambino Да, я думаю, что zxx - это тег, который в основном полезен для случаев, когда требуется языковой тег, но в содержании нет заметного человеческого языка, например, изображение без письменного языка, фильм без письменного языка. или разговорный язык, скомпилированный, запутанный или минимизированный образец кода и т.п. В случаях, когда языковой тег не требуется, например HTML, я обычно просто опускаю любой языковой тег, а не использую zxx. - person Brian Campbell; 28.02.2011
comment
Имеет смысл, но я думаю, что здесь есть серая зона. Да, было бы против духа спецификации использовать что-то вроде x-ruby. Тем не менее, x-... определяется исключительно по частному соглашению (см. BCP47) и сам по себе не затеняет какие-либо предыдущие теги основного языка, поэтому это было бы нормально, просто не совсем кошерно. Насколько я понимаю, это будет то же самое, что написать en-x-ruby в документе, который уже en. Без атрибута lang текст будет неявно восприниматься как обычный en, что тоже не совсем правильно. (Кстати, это чисто академическое обсуждение - я использую имена классов :) - person Flambino; 28.02.2011
comment
После того, как я сузил свой выбор JS-подсветчика до Prism или Rainbow, я сначала выбрал последний из-за того, что, как я думал, было разумным использованием атрибута data- (эээ… и бесчисленное количество тем CSS). Прочитав больше (включая этот пост), я теперь возвращаюсь к синтаксически правильной Prism с именами классов. - person Dave Everitt; 18.08.2015
comment
Как указать lang/style для C# в github <pre><code> для выделения? - person Shimmy Weitzhandler; 23.08.2017

Кажется, нет лучшего способа, чем неправильно использовать атрибут lang с префиксом zzx, который вы упомянули (кстати, интересная находка!). Атрибут type может быть подходит немного больше, но он, конечно, недействителен в элементах pre.

Кстати, <code> (ссылка W3C здесь) может быть более подходящим, чем <pre>:

Элемент кода HTML (<code>) представляет собой фрагмент компьютерного кода. По умолчанию он отображается моноширинным шрифтом браузера по умолчанию.

person Pekka    schedule 27.02.2011
comment
Да, <code lang="..."> было бы очень точным с точки зрения семантики. Но это также встроенный элемент, поэтому для более длинных прогонов исходного кода (это было единственное, о чем я думал, когда писал вопрос), я думаю, я все равно использовал бы <pre>. Я обновил свой вопрос примечанием обо всем этом — большое спасибо! - person Flambino; 27.02.2011