Rambler's Top100
ГлавнаяО себеФоткиРазбиралкиМарафон
Карта

DML2

Jared Krinke

Перевод: Олег Токарев (otokarev@ngs.ru)


Простой, объектно-ориентированный язык для форматирования документов и сохранения контента (A simple, object-oriented content storage and document formatting language)

Оглавление:

  1. Введение в DML2.
  2. С чего начать?
  3. Файлы и директории.
  4. Теги для собственных нужд.
  5. Вывод файлов.
  6. Создание объектов.
  7. Действие.
  8. Выполнение объекта.
  9. Массивы.
  10. Действия с массивами.
  11. Конструкторы.
  12. Включение файлов.
  13. Автоматические тэги.
  14. dml2build.
  15. Про DML2.
  16. Замечания по версии.

Введение в DML2

Поддерживали ли вы статический веб-сайт и не удручало ли вас, как много времени вы тратите на открывание и закрывание файлов с необходимостью делать одни и те же изменения в каждом? DML создан для решения этой проблемы. DML позволяет пользователям определять собственные HTML-подобные теги, которые могут использоваться на всех страницах сайта. Таким образом изменение одного повторяющегося блока кода сводится к редактированию одного файла с шаблоном и выполнению одной команды, обновляющей сайт. Но что если вы захотели перепланировать весь сайт, используя совершенно другую разметку? Что если вы захотели отформатировать ваш контент используя совсем другой язык?

DML2 обязан рождением именно решению этих проблем. DML2 не просто система реализующая тривиальные шаблоны, это *объектно-ориентированная система форматирования и сохранения контента, работающая из командной строки*. Если вас не возбудила эта навороченная фраза, возможно возбудит тот факт, что *эта документация создана в формате текста и HTML из одного и того же контента*, следовало изменить только сравнительно небольшие файлы, содержащие шаблоны. DML2 нет никакого дела, что текстовый файл состоит из единственного файла, а HTML-документ многостраничный!

Если вы раньше использовали DML2, вы обнаружите, что DML2 нечто подобное, однако *DML2 не совместим в обратную сторону с DML*.

[Top]

С чего начать?

Поскольку вы читаете эту документацию, вы вероятно уже были на сайте посвященном DML2 и успешно скачали версию программы, которая подходит для вашей системы (например: Виндовс, или i386 Linux).

Если вас интересует, как инсталлировать один из бинарных релизов (то есть не исходники), то собственно никакой инсталляции не требуется. Все что необходимо - это поместить программу "dml2build" тода, где она будет легко доступна (вполне достаточно иметь ее на своем пути =) ). ЗАМЕТКА: Если вы пользователь Windows, вам придется использовать командную строку MS DOS'а (или специально подготовленный батч-файл), чтобы использовать DML2. Все что вам нужно знать - это то, что команда "cd" меняет текущую папку (это чтобы попасть к вашим исходным файлам). Если это все звучит слишком сложно, то вероятно DML2 не для вас.

[Top]

Файлы и директории.

При работе DML2 читает исходные файлы (как повелось, исходные файлы для DML2 имеют расширение ".dml2"). Исходные файлы DML2 (буду их называть просто DML2 файлами) могут определять теги и объекты пользователя, участвующие в генерации выходых файлов. Единственный DML2-файл может явится источником любого количества файлов, даже вообще отсутствия оных.

Вам следует поместить все ваши DML2-файлы в одну директорию (обычно называемую dml2). Выходные файлы будут помещаться в директорию, в которой помещается ваша "dml2". Преодолеть это правило вы можете используя параметр "-o" (таким образом файлы на выходе будут помещаться туда, куда вы укажете). ЗАМЕТКА: Если вы используете Windows, стандартным разделителем директорий является обратная косая черта ("\"). Тем не менее, для того, чтобы DML2 функционировала правильно, вы должны использовать только прямую косую черту (например: "docs/file.html"). Если вы веб-разработчик, то этот синтаксис должен быть вам близок.

Внутри DML2-файла каждая строка интерпретируется как команда DML2. Если вам угодно включить комментарии внутрь ваших исходных файлов, просто начните строку с "//" или "#". Также вы можете найти удобным использовать отступы в стиле языка С внутри DML2-файлов (это тот стиль, который будет использоваться в этой документации).

Если вы находите сложным изучение DML2, попробуйте взглянуть в директорию "docs/dml2", там куда распаковали DML2. Эта директория содержит все исходные тексты, которые использовались при генерации документа, который вы сейчас читаете.

[Top]

Теги для собственных нужд

Предшественник DML2 - DML по большей части обладал одним хорошим свойством - определяемыми пользователем тегами. Эти теги подобны по своей структуре тегам HTML, но могут представлять любую произвольную строку (которая может содержать как другие теги, так и параметры). Чтобы вызвать тег без параметров, вы должны просто написать знак меньше, потом открывающуюся круглую скобку, имя тега, закрывающуюся круглую скобку и знак больше. Как пример: <(aDML2Tag)>.

Определение тега достаточно прозрачно (в особенности если использовать синтаксис С). Просто укажите внутри вашего DML2-файла что-нибудь типа:

tag nameOfTag {
Здесь находится содержание тега. 
Этот текст будет вставлен, 
когда вы вызовете тег.
}

Вы можете так же создать теги, которые работают подобно тегам HTML/XML, умеющим охватывать блок текста. Если вам не знакомы эти языки, тут есть пример: Допустим вы имеете блок текста, который хочется поместить в некую рамку. Вы бы могли создать один тег для начала блока, а другой для конца, но тогда это не будет работать, если написать этот текс дважды.

Для разрешения этой проблемы DML2 имеет "параметры для тегов". Они определяются путем добавления слэша, к концу имени тега. Внутри определения, когда вы хотите вызвать текст заключенный между открывающим и закрывающим тегами, просто наберите DML2-тег с именем "@". Вот пример:

tag aTagWithATagParameter/ {
Этот тег окружает следующий текст: <(@)>
}

И наконец, DML2-теги могут принимать параметры. Эти параметры задаются в С-подобной нотации. После имени тега (и все еще внутри тэга), поместите открывающуюся круглую скобку, далее, через запятую, поместите заключенные в кавычки параметры, и, в конце, закрывающуюся круглую скобку. Доступ к параметру из определения тэга происходит при помощи тэга с именем состоящим из символа "@", и следующим за ним номером, который соответствует номеру позиции параметра. Позиция первого параметра - нуль. Далее следуют два примера, демонстрирующие и определение, и использование тэгов с параметрами.

tag parameterTag {
Первый параметр этого тэга: "<(@0)>"
А тут второй: "<(@1)>"
}

Теперь, коль определили тэг, почему бы его не вызвать? <(parameterTag("Parameter #1", "Parameter #2"))> Предыдущая строка вызовет тэг, тот в свою очередь произведет текст с параметрами подставленными в соответствующие места. ЗАМЕТКА: Поскольку параметры тэгов заключены в кавычки, вы не можете так запросто использовать символ двойных кавычек (""") внутри параметров. Обойти это можно, просто поместите обратную косую черту перед кавычкой ("\""). Так или иначе, внутри DML2-тэгов вы *должны* использовать только символ двойных кавычек. ЗАМЕТКА: DML также поддерживал другой тип параметров, известный как "именованный параметр". Этот тип позволял пользователям обойтись без необходимости помнить последовательность параметров, вместо чего полагаясь на определенное пользователем имя для нахождения данных. DML2 не имеет в этом необходимости благодаря своим объектам (тема, которая будет обсуждена позже).

[Top]

Вывод файлов

В DML2 не было бы смысла, если бы весь ваш контент содержался только в файлах DML2, так что вывод файлов является одной из основных функций, которая поддерживается DML2.

Определение вывода - тоже самое, что и определение тэга, тот же С-подобный синтаксис. Просто наберите "output", за которым следует имя файла в двойных кавычках и, далее, открывающаяся фигурная скобка ("{"). Внутри двойных кавычек для имени файла *могут* быть использованы тэги. Это весьма полезно, если вам надо вывести файл в одну директорию, а потом в другую. Пример:

output "<(directoryPrefix)>/doc1.html" {
Этот текст магически перенесется 
в файл указанный выше!
}

DML2 также предоставляет ограниченный набор параметров вывода, привязанных к определенным задачам, которые контролируют то, как файл записывается (в случае если требуется сделать изменения). Для того, чтобы задать опцию, напишите слово ее определяющее непосредственно за именем файла (в кавычках). Если вам надо задать значение опции (как например для максимальной длины строки) просто напишите "wordwrap=80" или что-нибудь подобное тому (Заметьте, что тут нет пустых мест между опцией знаком равенства и значением!).

Опция "wordwrap" принимает целое значение, которое являются максимальной длиной строки (в символах) в итоговом файле. Это бывает полезно в генерации чисто текстовых файлов (подобно "docs/README.txt"). Строки при использовании этой опции рвутся по символам табуляции и пробела, не по словам.

Опция "html" работает с задачами связанными с разработкой статических HTML сайтов. В настоящий момент существует только одна функция (хотя и весьма мощная), которая может транслировать относительные ссылки между страницами. То есть, если вы имеете картинку в "img/" и ваш файл в "pages/", будет правильным использовать ссылку "img/image.png" вместо "../img/image.png". Сейчас это работает для атрибутов "src", "href" и "background" (Я считаю, это все что надо поддерживать). ЗАМЕТКА: Если вы планируете использовать трансляцию ссылок (опция "html"), вы должны так разрабатывать *все* ссылки на страницы и картинки в своих тэгах, как если бы файл находился в корневой директории сайта. Тем не менее, возникают небольшие неудобства, кагда требуется перемещать файлы между директориями.

[Top]

Создание объектов

Теперь, зная как создавать тэги и выводить фалы, вы находитесь на уровне классического DML-умельца. Эта как раз вся функциональность, которой обладает DML. Используя то, что уже знаете, вы сможете создавать странички быстрее и изменять дизайн (слегка) без утомительного редактирования в ручную HTML-файла. Но что если вы захотите переместить панель управления с края в нижнюю часть страницы? Или ради первоапрельской шутки вывести ваш сайт целиком в ASCII кодировке? Это уже за гранью возможного для DML. К счастью DML2 добавляет эти идеи и позволяет выводить вам контент в каком захотите формате, каждый из которых будет иметь свою собственную структуру и строение.

Объект может объединять в себе свойства (описываемые с помощью ключевого слова "val"), так же как и другие объекты и массивы свойств/объектов. Определение объекта начинается с "object", за которым следует пробел (или табуляция), потом имя типа объекта. Завершает строку открывающаяся фигурная скобка ("{"). Между строкой, которая содержит только закрывающуюся фигурную скобку ("}"), и первой строкой содержатся определения членов объекта. Определение члена состоит из имени типа члена, за которым следует идентификатор (имя) самого члена. Как раз члены и содержат данные внутри DML2-объектов. Если что-то еще не совсем ясно, пример прояснит все вышесказанное.

object Date {
        val month
        val day
        val year
        Time timestamp
}

Поскольку объекты самый сложный (и самый мощный) аспект в DML2, проследим этот пример строка за строкой. Первая строка начинает определение типа объектов "Date". Вторая строка определяет свойство "month". Свойство - простейший тип в DML2, который может содержать блок текста (который может содержать в себе и тэги DML2). Третья и четвертая строки подобны второй за исключение имен свойств. Пятая строка определяет член типа "Time". Тип "Time" - тип заранее определенный в том же файле или во включенном файле (чуть позже поговорим поподробнее о файлах). Последняя строка, очевидно, завершает определение. ЗАМЕТКА: Вы вероятно заметили отступы от начала строки в определении членов. Этот синтаксис рекомендуется, но не является обязательным.

Замечательно, мы определили тип. Само по себе это совершенно бесполезно. "Date" всего лишь общий тип, объекты которого могут содержать определенные члены. Для получения реального объект, необходимо его определить (т.е. получить новый экземпляр типа "Date"). Здесь приведено, как это сделать.

Date someDate

Хух, это было тяжко. К счастью вы все еще со мной ;). Теперь, когда мы имеем объект типа "Date", мы можем начать присваивать ему значения. Для доступа к членам объекта достаточно написать имя родительского объекта и точку, за которыми следует имя свойства объекта. Заметьте, что это рекурсивный процесс, так что запись "object.aMember.aMembersMember" будет траверсироваться от родителя к потомку, пока не будет найден нужный объект. Для того, чтобы присвоить значение свойству объекта, просто напишите имя свойства за которым следуют пробел, знак равенства, еще один пробел и, наконец, новое значение свойства, окруженное двойными кавычками. (Обратите внимание, правило касающееся "\"" здесь тоже работает.)

someDate.month = "January"
someDate.day = "6"
someDate.year = "2002"

Вы также можете присвоить значение всего объекта объекту того же типа. Это работает так:

Date anotherDate
anotherDate = someDate

В этом примере все члены "anotherDate" принимают значения тех же членов объекта "someDate". ЗАМЕТКА: Когда вы присваиваете объект другому объекту, все члены первого копируются во второй. После этого *они никоим образом не связаны*. Это значит, что, если *после* операции присвоения вы сделали изменения в одном из этих объектов, второй останется неизменным.

Если вы еще не заметили, весь контент сконцентрируется внутри свойств DML2. Объекты всего лишь удобные хранилища данных, которые содержатся в свойствах. Чтобы подчеркнуть это, тип свойства - "val".

[Top]

Действие

Сейчас вы уже знакомы с тегами DML2, когда вы вызываете их (подобно: <(someTag)>), вместо тэга вставляется определенный вами код. С объектами и их членами тоже можно обращаться подобным образом. Если вы вызвали значение подобно <(someDate.month)>, оно вернет значение текста заключенного в свойстве (с учетом всех тэгов и объектов находящихся в нем).

Вам вероятно интересно знать, а что будет, если вызвать весь объект, не просто его член. Это как раз то место, когда в игру вступает определение действия. Определение действия определяет, что будет возвращено, после того, как вы наберете нечто подобное <(someDate)>. Вы можете определить действие написав "render", за которым следуют: пробел, тип объекта, пробел и открывающаяся фигурная скобка ("{"). Очень похоже на определение тэга.

render Date {
Date: <(month)> <(day)>, <(year)>
}

Первое, что вам следовало заметить, это то, что я не написал ничего подобного <(someDate.day)>. Причина этого кроется, в том что каждый объект имеет область видимости. Когда вы внутри объекта "Date" вы можете обращаться к его членам как к локальным. Тем не менее, если я захочу обратиться к члену объекта "Time", который в свою очередь является членом "Date", мне придется написать что-то типа <(timestamp.seconds)>, поскольку члены объекта "Time" нелокальны.

Возвращаемся к определению действия. Теперь, когда я напишу <(someDate)>, текст определенный выше будет вставлен в это место, с использованием значений своих членов. И все потому, что типом "someDate" является "Date".

[Top]

Выполнение объекта

Определение выполнения объекта очень похоже на определение действия, только вместо "render" пишем "execute". Внутри же определения выполнения вся схожесть заканчивается. Определение выполнения - это блок команд DML2, которые вы хотите исполнить для данного объекта. Необходимость выполнять объект обусловлена наличием массивов объектов. Допустим вы имеете массив объектов "Page", и каждый представляет собой то, что на выходе DML2 будет отдельным файлом. Вместо того,чтобы обрабатывать (render) каждый отдельный объект по отдельности, вы можете "выполнить" весь массив.

object Page {
        val title
        val content
}

execute Page {
        output "<(title)>.html" {
<(title)>
<(content)>

Hosted by uCoz
} } Page index Page news # Инициализируем index и news

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

Вопреки, возможно, вашим ожиданиям, что выполнение вызывается автоматом, DML2 требует вызова выполнение объекта. Тем не менее это достаточно просто:

execute index
execute news

В будущем (то есть после того как вы прочитаете несколько параграфов), вы познакомитесь с таким понятие в DML2 как массив. Так вот, вы можете выполнить за раз весь массив (что мне кажется ну *очень* полезным). Советую опять обратить внимание на этот момент после того, как прочитаете про массивы.

execute pages[]
[Top]

Массивы

Если вы сталкивались с массивами до этого, этот параграф будет весьма прост в прочтении. Если нет, приготовьтесь к жесткой поездке =). Массивы - это, как правило, ряды однотипных объектов. Допустим, вам нужен объект, который бы содержал члены представляющие собой список строк. Вместо того, чтобы определять и именовать каждый член объекта, проще описать один объект содержащий одну строку и работать уже с массивом таких объектов. Полезным свойством использования массивов является отсутствие необходимости строго задавать размер массива: DML2 задействует столько элементов массива сколько вам нужно. Вот как определяется массив:

Date[] arrayOfDates

Подобно другим определениям, за исключением пары квадратных скобок ("[]"). Теперь, когда вам понадобится элемент массива, просто наберите имя массива и номер элемента заключенный в квадратные скобки (все без пробелов). Обратите внимание: нумерация в массивах начинается с нуля. Так что у третьего элемента будет номер 2. Думаю, вы с таким сталкивались раньше в программировании, и такое положение вещей вас сильно не напряжет. Резюмируем, написав <(arrayOfDates[2])>, мы получим доступ к третьему элементу в массиве объектов типа "Date" описанного ранее.

Когда мы работаем с элементом массива, он себя ведет точно так же как любой другой объект того же типа. Так что набирая <(arrayOfDates[5])> внутри значения свойства или в определении выполнения, вы тем самым подставляете текст определенный в действии.

Вы также можете присвоить объекту в массиве значение другого объекта того же типа. Таким образом, чтобы скопировать "someDate" во второй элемент массива "arrayOfDates", вы можете просто набрать:

arrayOfDates[1] = someDate

Если хотите добавить элемент к массиву, все что вам следует сделать - присвоить этому элементу какое-нибудь значение. В языках программирования, как правило, вам необходимо в начале определить сколько элементов будет в массиве. В DML2 элементы массива добавляются автоматом по первому обращению. Это удобно, но уверьтесь в том, что не написали случайно большое число в квадратных скобках, или DML2 потратит кучу времени добавляя тонны элементов. Если вы чуть чего из последнего не поняли, не волнуйтесь, это не столь важно =).

Добавлять элементы также можно, используя специальную сокращенную нотацию. Просто поместите знак фунта ("#") между квадратными скобками и это автоматически будет показывать на конец массива. Точно также, если требуется добавить элемент в середину, вам нет необходимости перенумеровывать остальные.

[Top]

Действия с массивами

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

Здесь все элементы типа Date массива arrayOfDates:
<(arrayOfDates[])>

Это просто чудо, что вам не придется обращаться к 50 различным элементам в ручную, но что если вы захотите поместить разрыв строки ("
") между ними всеми? Вы могли бы вставить разрыв строки в определении действия, в начале или в конце, однако, тогда вам пришлось бы иметь дело с одним лишним разрывом.

К счастью, DML2 имеет решение этой проблемы: разделители массива. Чтобы добавить некий произвольный код между элементами массива, непосредственно за ссылкой на массив разместите тэг <(&spacer)>, за ним напишите текст, который, вы хотели бы, чтобы появился между элементами и, наконец, завершите все <(/&spacer)>.

Тут мы получим на выходе все элементы типа Date массива 
arrayOfDates разделенные двумя разрывами строки:
<(arrayOfDates[])><(&spacer)>

<(/&spacer)>

Обратимся к другой проблеме: новости на вашем сайте хранятся в массиве объектов DML2, но (ради сохранения размера страницы) вы хотите выводить только пять последних новостных статей. Для этих целей используйте диапазон элементов. Внутри квадратных скобок, где бы вы обычно поместили номер элемента для выполнения над ним действия, просто напишите номер первого элемента диапазона, затем запятую и, затем, последний элемент диапазона, над которым необходимо выполнить действие. К примеру, что бы выполнить действия над элементами с первого по пятый, вам просто необходимо написать: <(arrayOfDates[0,4])>. Так же как и для действия над всем массивом в данном случае тоже можно использовать разделитель массива.

А что если вы хотите добиться вывода последних пяти элементов массива? Вы не всегда можете знать количество элементов в массиве, и, значите, не можете явно указать номера элементов. Вместо этого используйте знак фунта ("#") в указании диапазона. Знак фунта означает количество элементов в массиве. ЗАМЕТКА: Помните, что первый элемент массива имеет позицию "0". Следовательно, знак фунта (который возвращает количество элементов в массиве) в действительности указывает на объект вне границ массива. Иными словами, если вы имеете 5 элементов, последний элемент имеет индекс "4", но знак фунта преобразуется в "5".

Конечно же я еще не разрешил проблему обращения *только* к последним 5-ти элементам массива. Все это достигается путем простых математических вычислений (сложений и вычитаний) при задании диапазона. Конечный результат выглядит несколько шифрованно, но если сильно не усердствовать, то он может быть не плохим.

Здесь пять последних элементов массива arrayOfDates:
<(arrayOfDates[#-5,#-1])>

Здесь пять первых:
<(arrayOfDates[0,5])>
ЗАМЕТКА: DML2 ничего не предпримет, если вы выйдете за пределы массива. Это очень полезно, если вы делаете что-нибудь типа ChangeLog'а, у вас пока в нем одна запись, а код ваш должен обрабатывать пять записей. Ваш код обрабатывает ровно столько записей сколько есть, пока их количество меньше шести.
[Top]

Конструкторы

Можете расслабиться, коли добрались до этого места, поскольку самый тяжелый материал остался позади. Конструкторы - это более простой способ создания/инициализации *так же как и* присваивания значения, и все это за один шаг.

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

Конструкторы (поскольку они созданы для удобства) можно использовать на той же строке, что и определение переменной. Просто добавьте пробел, знак равенства, еще один пробел и, наконец, сам конструктор. Как использовать конструктор, понятно интуитивно, так или иначе пример:

val someProperty = "Объявляем и определяем!"
val anotherProperty = someProperty
ЗАМЕТКА: Не забывайте использовать "\"", когда необходимо использовать двойные кавычки внутри конструктора свойства.

Вторая строка в действительности не является конструктором, а просто демонстрирует, как вы можете присваивать значение переменной на той же строке, где и ее определение. Фактически вы можете выполнять операцию присваивания на любой строке, где вы могли бы использовать конструктор.

Следующий тип конструкторов - конструктор массива. Такие конструкторы могут быстро стать недоступными, однако они весьма удобны, если вам надо определить несколько строк текста за одно присваивание. Просто используйте список строк разделенных запятыми внутри фигурных скобок ("{}"). Здесь помог бы пример:

val[] arrayOfProps = {"First", "Second", someProp}
val[] moreProps = arrayOfProps

Последний тип конструкторов, который вы можете использовать в DML2 - это конструктор объекта. Помните, когда вы изучали как определять объекты, вы писали члены объекта каждый на своей строке? В этом теперь появился смысл. Чтобы изобразить конструктор объекта, просто напишите ключевое слово "new", потом пробел, потом тип объекта, который вы собираетесь создать (e.g. "Date"). Затем допишите набор разделенных запятыми конструкторов заключенный в круглые скобки ("()"). Для облегчения понимания, приведу расширенный пример, заключающий в себе все три типа конструкторов.

object TextContent {
        val[] lines
}

object Page {
        val title
        TextContent content
}

Page hello = new Page("Hello World",
new TextContent({"If this makes sense, 
you're a master of constructors!", 
"Oh yeah, forgot...", "Hello World!"}))

В целяых облегчить понимание этого примера, разобьем его на более мелкие части. К примеру, взгляните только внутрь конструктора "new Page", и вы увидете два конструктора внутри него, первый - конструктор свойства, второй - конструктор другого объекта. Потом, приглядимся только к конструктору "new TextContent", вы увидете еще один конструктор и конструктор массива. Внутри конструктора массива (который соответствует "Page.TextContent.lines") находятся несколько конструкторов свойств, определяющих каждую индивидуальную строку.

Наконец, вы можете использовать конструкторы, чтобы задать значения по умолчанию для объектов. Пример: большинство страниц в этом документе называются "doc#", где "#" - номер строки. Вместо того, чтобы набирать эти названия каждый раз для каждой главы, я просто написал простой конструктор, типа этого:

object Section {
        val title = "New Section"
        val file = "doc<(&index)>.html"
        val[] content = {"Content will go here"}
}

С конструкторами по умолчанию, мне не пришлось устанавливать значение "file", оно устанавливалось равным значению по умолчанию "doc<(&index)>.html" автоматически. И конечно, для первой страницы документа имя файла - "index.html". Чтобы переопределить значение установленное конструктором по умолчанию, просто присвойте значение, которое вам нужно. ЗАМЕТКА: <(&index)> - автоматический тэг, который подставляет текущую позицию элемента в массиве (начиная с 1, а не нуля). Все об автоматических тэгах будет в параграфе специально им посвященном.

[Top]

Включение файлов

Простейшим способом в DML2 быстро экспортировать один и тот же контент в другой или новый формат является разделение контента и его представления по разным файлам. DML2 позволяет вам элементарным образом определить объекты и контент в одном файле, а исполнения и действия этих объектов в другом.

Где бы в файле DML2 вам не понадобился доступ к другому файлу, просто используйте конструкцию включения файлов:

include "content.dml2"

Теперь текущий файл имеет доступ ко всему что было определено в "content.dml2". Если вам необходимо, можете использовать эту конструкцию несколько раз для различных файлов и в различных файлах. Файлы, к которым вы обратились при помощи "include" из другого файла, не являются источниками новых файлов (конструкция "output"). Для этого вам необходимо явно вызвать "dml2build" для них. ЗАМЕТКА: Когда вы манипулируете объектами внутри включенного файла, в действительности вы изменяете объекты во включающем его файле. Это вопрос скорости: изменение самих объектов много быстрее чем редактирование копий. Если у вас много файлов, которые включают один другого, будте осторожны, изменения сделанные во включенных файлах постоянны. (пер.: что за муть?!?!)

[Top]

Автоматические тэги

DML2 представляет некоторые автоматически создаваемые тэги, которые могут быть использованы для вещей не поддерживаемых текущей спецификацией DML2. Эти тэги защищены от перекрывания имен тем, что начинаются с запрещенного (для обычных тэгов) символа амперсанда ("&"). Просто используйте их как обычные тэги.

&index - Этот тэг подставляет текущую позицию в массиве (если данный элемент находится в массиве). Обратите внимание на то, что первый элемент имеет позицию 1, а не нуль. Хороший пример использования этого тэга находится на странице посвященной конструкторам.

&day - Возвращает день месяца.

&monthName - Возвращает название текущего месяца.

&month - Возвращает номер текущего месяца.

&year - Возвращает текущий год.

&second - Возвращает текущую секунду.

&minute - Возвращает текущую минуту часа.

&12hour - Возвращает текущий час (от 0 до 11) дня.

&24hour - Возвращает текущий час (от 0 до 23) дня.

&m - Возвращает AM или PM.

&version - Возвращает версию DML2, которую вы сейчас используете (*1.0.1*).

&website - Возвращает URL текущего веб-сайта DML2.

&build - Возвращает текущее имя версии DML2 (*Revolution*).

Тут пример, как можно использовать предопределенные тэги DML2:

Generated <(&monthName)> <(&day)>, <(&year)> 
by DML2 ( <(&website)> )
[Top]

dml2build

Мои поздравления, вы справились с языком DML2! По всей видимости, вам будет теперь интересно узнать, как генерировать свои файлы, используя "dml2build". Находясь в своей "dml2/" директории (та самая, где вы держите свои DML2-файлы), просто запустите "dml2build" со списком параметров. Список параметров - список файлов DML2, которые вы бы хотели обработать и которые определяют, что генерировать. Вы можете указать параметром "all". Тогда "dml2build" обработает все файлы с суффиксом ".dml2" в текущей директории.

dml2build file1.dml2 file2.dml2 content.dml2
dml2build all

При выполнении DML2 выдаст на терминал некую дружески расположенную к вам диагностику (в том числе и описания ошибок, если где что не так). Если вы захотите по новой сгенерировать эту документацию, зайдите в директорию "docs/dml2/" и выполните команду:

dml2build html_template.dml2\
text_template.dml2 man_template.dml2

Вы можете также запускать "dml2build" из директории не содержащей DML2-файлы (все include'ы при этом обрабатываются относительно текущей директории). Однако, если вы не в директории содержащей DML2-файлы, вы не можете использовать "all" для чтения всех DML2-файлов.

Вы также можете использовать параметр "-o", чтобы указать куда ложить сгенерированные файлы. По умолчанию они сохраняются в директории "../", поскольку в штатной ситуации "dml2" запускается из "dml2/". К примеру, следующая команда записывает выходные файлы "/files/html_template.dml2" в директорию "/files/output".

dml2build /files/html_template.dml2 -o /files/output
ЗАМЕТКА: Значительно эффективнее запускать DML2 единожды с несколькими файлами на входе, нежели несколько раз с одним файлом. Это объясняется необходимостью проводить синтаксический анализ включенных файлов один раз в первом случае и несколько раз во втором.
[Top]

Про DML2

DML2 является опенсорсовыми (т.е. распространяем под лицензией GNU GPL) потугами Deraj DeZine. Как ясно из введения, цель DML2 - разделить контент сайта и его структуру, путем сохранения их в отличных объектах DML2. Объектно-ориентированный подход делает такое разделение более чем простым, поскольку вы должны думать только о логических типах объектов.

Перед тем как что-нибудь скажите - да, я слышал о XML. К сожалению, мне кажется, что XML слишком раздут, так как является универсальным и создан для решения весьма большого круга задач, чем может смутить среднего пользователя, которому не важна поддержка миллиона языков, кодировок и т.п.. К тому же я до сих пор сомневаюсь в объектно-ориентированности XML. Может это только я такой, но мне не понятно, как определить новый тип объекта в XML (подобно тому как это делается в DML2), а потом его инициализировать.

Из того что я слышал, XSLT-трансформации (пер.: XSLT transformations - не знаю, что это такое, и как это переводить) могут выполнять задачи схожие с функциональностью действий (пер.: render) в DML2, но я не смог отыскать реализацию, которая бы генерировала статические страницы (примерно такие как в этом руководстве). Все что нашлось - это модули к Апачу или что-то типа того.

Неважно, являются ли истиной предыдущие заявления, так или иначе XML меня отпугнул. Отпугнул на столько, что я решил сделать что-нибудь свое. Тешу себя мыслью, что сделал полезный язык, только время и комментарии пользователей скажут, так ли это на самом деле. В будущем, возможно, я сделаю конвертер из DML2 в XML, однако не уверен в том, на сколько это будет полезно.

Если у вас имеются вопросы, комментарии или предложения обратитесь к сайду Deraj DeZine и найдите там мой email (вероятно, это *deraj* на сервере *submail.net*, но лучше проверить).

Надеюсь, что DML2 так же полезен вам как и мне!

Наконец, отмазка (disclaimer): DML2 не гарантирует решения каких-либо проблем и выполнения какихлибо задач. Если DML2 сама вызовет какие-либо проблемы (такие как: уничтожение файлов и/или директорий), я не несу никакой ответственности.

[Top]

Замечания по версии

В настоящий момент никаких известных багов (пер.: bug - программерский ляп) в DML2 нет, но могут быть неизвестные. Если вы обнаружите, как вам кажется, баг, обратитесь на Deraj DeZine и найдите мой email. Постарайтесь отправить мне письмом и проблемный код, чтобы я мог исправить ошибку.

DML2 v1.0.1 был тщательно протестирован и хорошо описан в документации (мне так кажется), но вам может так не показаться. Если вы знаете способ улучшить DML2, не откладывайте связаться со мной, я получаю удивительно малое количество писем =).

Вы можете посетить страничку разработчика DML2 на Deraj DeZine для дополнительной информации. Так же на SourceForge есть страничка проекта, если вам интересны исходники.

Что нового в v1.0.1:

  • Конструкторы по умолчанию - удобный способ давать объекту значения по умолчанию, которые можно переопределить.
  • Тэг <(&index)> - Автоматический тэг возвращающий текущую позицию в массиве (начиная с 1).
  • Опционная директория вывода - можно теперь установить в какую директорию записывать файлы.
  • Маны (Man Pages) - Возможность использовать документацию в виде манов Линукса.
  • Исправление ошибок - Многочисленные исправления ошибок и чистка кода (в основном связанная с иерархией объектов).
[Top]
Смотри еще:
ГлавнаяО себеФоткиРазбиралкиМарафон
Карта

Обратная связь: otokarev@ngs.ru

Rambler's Top100

Hosted by uCoz