Генерация по шаблонам

Связи
  • jandcode.jc.GspScript (class)

В jc имеется возможность генерировать произвольные наборы файлов по шаблонам gsp.

Пример:

// сюда будем генерировать
def outDir = wd("temp/gendir1")

// ощищаем каталог, он будет пустым и существующим
ut.cleandir(outDir)

// создаем скрипт генератор по gsp-файлу
GspScript gs = create("my-templates/template1.gsp")

// запускаем генерацию, указывая куда генерировать и с какими аргументами
gs.generate("${outDir}/result1.txt", [a1: 1, a2: 2])

Пример шаблона:

<%@ page import="jandcode.jc.*" %>
<%
  // содержимое gsp - это тело метода jandcode.jc.GspScript#onGenerate
  // поэтому можно получить типизированную ссылку
  GspScript th = this

  def s = "Текст1"
%>
Текст
Переменная ${s}
Аргументы ${th.args['a1']}, ${th.args.a2}
<% out("Текст") %>
<% out(s) %>

Аргументы для генерации

Аргументы для генерации передаются в виде Map в методе genеrate и доступны в момент генерации через свойство: args типа IVariantMap.

Эти аргументы существуют в процессе генерации в единственном экземпляре и разделяются между вложенными шаблонами.

Вложенные шаблоны

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

<%@ page import="jandcode.jc.*" %>
<%
  GspScript th = this

  // создаем экземпляры скриптов
  // важно, что бы они были созданы внутри шаблона, откуда будут выводится
  GspScript child1 = th.create('lib/child1.gsp')
  GspScript child2 = th.create('lib/child2.gsp')
%>
Первый шаблон:
${child1}
Второй шаблон:
<% out(child2) %>

Это простейший способ использования вложенных шаблонов.

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

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

Так определяются функции во вложенном шаблоне:

<%@ page import="jandcode.jc.*" %>
<%
  GspScript th = this

  // функции объявляем как Closure и записываем в vars

  th.vars.func1 = { a ->
    out("A=${a}")
  }

%>

Весь вывод вне функций будет проигнорирован!

<% th.vars.func2 = { b -> %>
B=${b}
<% } %>

Так они используются:

<%@ page import="jandcode.jc.*" %>
<%
  GspScript th = this

  // создаем экземпляр скрипта, содержащего функции
  GspScript lib = th.create('lib/lib1.gsp')

  // выполняем функции
  lib.vars.func1(1)
  lib.vars.func2(2)
%>

Генерация нескольких файлов

При запуске генерации в методе generate мы указываем в какой файл генерировать. Каталог с указанным файлом будет рассматриватся как базовый каталог генерации. В процессе генерации можно изменять текущий файл, в который будет осуществляется дальнейшая генерация.

Допустим мы запускаем генерацию так:

// создаем скрипт генератор по gsp-файлу
GspScript gs = create("my-templates/template1.gsp")

// запускаем генерацию, указывая файл, куда генерировать
// каталог с этим файлом будет базовым каталогом генерации
gs.generate("temp/gendir/result1.txt", [a1: 1, a2: 2])

Тогда в шаблоне можно делать так:

<%@ page import="jandcode.jc.*" %>
<%
  GspScript th = this

  // текущий файл для вывода: temp/gendir/result1.txt
  def curFile = th.currentFile

  // базовый каталог для вывода: temp/gendir
  def outDir = th.outDir

  // вывод в файл temp/gendir/result1.txt
  th.out('1')

  // меняем файл на temp/gendir/f2.txt, указывая имя относительно outDir
  th.changeFile("f2.txt")

  // вывод в файл temp/gendir/f2.txt
  th.out('2')

  // меняем файл на ранее используемый temp/gendir/result1.txt
  // и указывая параметр append=true, открываем его в режиме добавления
  th.changeFile("result1.txt", true)

  // добавляем данные в файл temp/gendir/result1.txt
  th.out('3')

  // меняем файл на temp/gendir/f3.txt, предыдущий temp/gendir/result1.txt
  // остается открытым
  th.pushFile("f3.txt")

  // выводим в файл temp/gendir/f3.txt
  th.out('4')

  // возвращаемся к файлу temp/gendir/result1.txt
  th.popFile()

  // выводим в файл temp/gendir/result1.txt
  th.out('5')

%>

При смене файла методами changeFile и pushFile файл физически не создается и не открывается, пока не было никакого вывода. Поэтому при запуске генерации можно указать какой либо фиктивный файл (он нужен для определения базового каталога генерации), а уже в теле шаблона указать смену файла на нужный.

Допустим для вышеуказанного вызова в шаблоне можно написать так:

<%@ page import="jandcode.jc.*" %>
<%
  GspScript th = this

  // текущий файл для вывода temp/gendir/result1.txt, однако он еще не создан,
  // так как вывода еще не было
  def curFile = th.currentFile

  // выводим в набор файлов
  for (i in 1..3) {
    th.changeFile("f-${i}.txt")
    th.out(i)
  }

  // будут созданы файлы:
  // temp/gendir/f-1.txt
  // temp/gendir/f-2.txt
  // temp/gendir/f-3.txt
%>

Ресурсы для генерации

Скрипт jandcode.jc.GspScript является наследником от jandcode.jc.ProjectScript и обладает всеми его свойствами. Например, свойство scriptDir указывает на каталог, из которого был загружен скрипт. Это позволяет хранить ресурсы рядом со скриптом и в процессе генерации копировать их в каталог вывода.

Допустим, мы генерируем html-файл и ему нужны css, js, картинки. Можно сделать так:

<%@ page import="jandcode.jc.*" %>
<%
  GspScript th = this

  // каталог в котором лежит скрипт
  def scrdir = th.scriptDir

  // копируем все ресурсы
  th.ant.copy(todir: th.outDir) {
    fileset(dir: srcdir) {
      include(name: '**/*.js')
      include(name: '**/*.css')
      include(name: '**/*.jpg')
    }
  }

  // генерируем html
%>
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
text
</body>
</html>