The Bit&Black IDML-Creator generates InDesign documents (.idml files) straight from PHP. Version 5.7 is one of those releases that feels like a milestone: it adds the XML layer of an InDesign document, introduces enums for almost every style value, simplifies the whole package around the Factory, sorts your styles the way InDesign does, and makes the generator considerably faster.
Tags — the XML structure of an InDesign document
Adobe InDesign documents carry two parallel structures. On the one hand there is the layout: pages, frames, tables, styles. On the other hand there is the XML structure: the content that InDesign can export to XML or import from XML, while the tag-to-style mapping keeps the formatting intact. Up to now the IDML-Creator only spoke the language of the layout. With version 5.7 it now also speaks the XML language.
A tag is defined with the new XMLTag class and registered on the factory:
<?php
use BitAndBlack\IdmlCreator\Content\Enum\Color;
use BitAndBlack\IdmlCreator\Factory;
$factory = new Factory();
$xmlTag = $factory->createXmlTag('Body');
$xmlTag->setTagColor(Color::ORANGE);
Every tag gets a color so it can be told apart from other tags in InDesign. A default root tag is created automatically; every custom tag is placed below it in the XML structure.
A tag itself is empty — it becomes meaningful when it is combined with content. The new XMLElement class connects a tag with the tagged part of the document:
<?php
use BitAndBlack\IdmlCreator\Content\Xml\XMLElement;
$xmlElement = new XMLElement($xmlTag, $paragraphStyleRange);
An XMLElement accepts paragraphs, runs of text, tables and cells, other XMLElements — the tags can be nested into a hierarchy — and other page elements like text frames. Because the XML elements have to stay in the same order as the laid-out content, an XMLElement can also be inserted directly into the content of a paragraph or character style range. That makes inline tags possible, for example to tag a single word inside a paragraph:
<?php
use BitAndBlack\IdmlCreator\Content\Story\CharacterStyleRange;
use BitAndBlack\IdmlCreator\Content\Story\Text;
new CharacterStyleRange(
null,
new XMLElement(
$xmlTagInline,
new CharacterStyleRange(
$boldRed,
new Text('IDML-Creator'),
),
),
);
Elements can be dressed up with XML attributes, comments and processing instructions:
<?php
use BitAndBlack\IdmlCreator\Content\Xml\XMLAttribute;
use BitAndBlack\IdmlCreator\Content\Xml\XMLComment;
use BitAndBlack\IdmlCreator\Content\Xml\XMLInstruction;
$xmlElement
->addXmlAttribute(new XMLAttribute('Class', 'headline'))
->addXmlComment(new XMLComment('Generated by IDML-Creator'))
->addXmlInstruction(new XMLInstruction('xml-stylesheet', 'type="text/xsl" href="structure.xsl"'))
;
Tables, cells and page items (rectangles, ovals, polygons, graphic lines, text frames) can be tagged as well. Tables and cells do not have marker characters in the laid-out document, so their XMLElement sets the NoTextMarker attribute automatically. And since every tag that shares its name with a paragraph or character style is matched to it automatically, the XMLExportMap and the matching import map are written to the optional XML/Mapping.xml file for you.
The XML structure is written to XML/BackingStory.xml — and you don't have to create the BackingStory or the Container manually anymore, the Content object takes care of it.
To see every situation in context, have a look at the new example using-xml-tags.php.
Enums instead of magic strings
The attribute values of the content classes are now covered by enums: colors, gradients, content types, frame types, strokes, the page setup and the character, paragraph, object and table styles all live in the namespace \BitAndBlack\IdmlCreator\Content\Enum.
<?php
use BitAndBlack\IdmlCreator\Content\Enum\Color\Model;
use BitAndBlack\IdmlCreator\Content\Enum\Styles\Capitalization;
$color->setModel(Model::PROCESS);
$characterStyle->setCapitalization(Capitalization::SMALL_CAPS);
The setters accept both the enum and the former string value, so existing code keeps working — calling a setter with a string now emits an E_USER_DEPRECATED notice and will be removed in v6.0. A new InDesignVersionAwareInterface marks every object that carries the InDesign version it was built for.
The factory does the heavy lifting
With the automatic creation of the BackingStory and the Container, and the new getDesignMap() and getPreference() getters, the singleton setup of the document is gone — you only talk to the Factory. Object styles are created through it as well:
<?php
$objectStyle = $factory->createObjectStyle('Fancy Frame');
All examples have been refactored to use this pattern, and the documentation has been restructured with new chapters about the enums, the quickstart, shapes, text frames, tables, styling text and styling objects.
The order your styles get in InDesign
Until now, styles were handed to InDesign in the order you created them. Version 5.7 sorts the way InDesign itself does: styles, colors, tints, mixed inks and the graphic XML entries are now sorted case-insensitively and alphabetically. Accented characters like umlauts sort with their base letters, so "Öffnungszeiten" appears between the "N" and the "P" instead of at the end of the list, and numbers keep their natural order — "Body 2" comes before "Body 10". Tints are placed directly after their base color, ordered from dark to light: "Red", "Red 80%", "Red 20%".
Under the hood the locale-aware Unicode collation of ICU is used when the intl extension is available; otherwise an equivalent pure-PHP comparison kicks in as a fallback, so the result is the same on every setup.
Faster generation, especially for tables
The generator is faster, and table-heavy documents benefit the most. The property schema of a class — its property names and their annotations — is parsed only once per class and then cached, instead of on every rendered object.
In the test benchmark the rendering of a story with 5000 table cells is about 3.7× faster, and 100 paragraph styles render about 5.2× faster (the measurements are kept in benchmarks/performance.md, so the effect can be reproduced and compared).
What you should know when upgrading
The release also cleans up. The former Tag class and Factory::createTag() are deprecated in favor of XMLTag and Factory::createXmlTag(); Content::setTag() gives way to Content::addXmlTag(). Creating the Preference, DesignMap and BackingStory manually is deprecated — use the factory getters, or simply let the Content object create them. The style enums moved into the common namespace \BitAndBlack\IdmlCreator\Content\Enum\Styles, with the old locations remaining as aliases until v6.0.
Most of the deprecations can be resolved by simply deleting the now-redundant calls: an existing Tag "can simply be removed", and the manual BackingStory and Container setup can be deleted as well.
Summary
Version 5.7 prepares the library for the future in three ways: it speaks the XML side of InDesign, it replaces strings with enums everywhere, and it makes the whole package more convenient and faster. Everything is built around a single Factory, so getting started with tags has never been easier.