Craft Language Parser

Two collaborating layers convert a .craft file into a loom node tree (see About Docraft): a generic, engine-agnostic XML parser (docraft::craft), and a loom-specific bridge that builds DocraftLoomNodes from its output.

DocraftLoomCraftLanguageParser

The top-level driver — the only piece that understands <Document> structure itself (<Header>/<Body>/<Footer>/<Settings>/ <Metadata>). Parses each section with DocraftCraftLanguageParser, builds it into loom nodes via DocraftLoomTreeBuilder, and wraps the result in a DocraftLoomPdfCreator (see Orchestrator) retrievable via edit_creator().

class DocraftLoomCraftLanguageParser

Top-level driver that turns a full Craft-language document (<Document> with a required <Body> and optional <Header>/<Footer> siblings) into a fully wired docraft::loom::DocraftLoomPdfCreator.

This is the only component that needs to know about the <Document> structure itself: docraft::craft::DocraftCraftLanguageParser has no per-tag registration for Document/Settings/Metadata/Foreach/NewPage, so this class walks the <Document> element directly via pugixml, picks out its Header/Body/Footer children (each parsed generically from that point on via DocraftCraftLanguageParser::parse_node), and applies a <Settings> sibling’s <Page>/<SectionRatios>/<Fonts> sub-tags (if present) to the resulting creator (each <Fonts><Font> variant is registered via DocraftLoomPdfCreator:: register_font()). A <Metadata> sibling’s simple string subtags (DocumentTitle/ Author/Creator/Producer/Subject/Keywords) are applied via DocraftLoomPdfCreator::set_metadata(); CreationDate/ModificationDate/ Trapped/GtsPdfx/AutoKeywords are still unrecognized (silently skipped). ${variable}/${data(...)} templating (Text/Title/Subtitle content, Image src, <Foreach>’s own model) is resolved by the docraft::loom::craft::DocraftLoomTreeBuilder this class drives internally, using whatever engine was given via set_template_engine().

Public Functions

DocraftLoomCraftLanguageParser() = default
~DocraftLoomCraftLanguageParser() = default
void set_template_engine(std::shared_ptr<docraft::templating::DocraftTemplateEngine> template_engine)

Sets the template engine used to resolve ${variable}/${data(...)} expressions during the next parse()/load_from_file() call.

If never called, an empty engine is used (no registered variables &#8212; ${...} expressions pass through unresolved).

void parse(const std::string &xml_string)

Parses a full Craft-language document from a string and builds/stores the resulting DocraftLoomPdfCreator, retrievable via edit_creator().

Parameters:

xml_string – XML source as string.

Throws:

docraft::exception::DataFormatException – on malformed XML or a missing required <Body> element.

void load_from_file(const std::filesystem::path &path)

Loads and parses a full Craft-language document from file, same as parse().

Parameters:

path – Path to the .craft XML file.

std::shared_ptr<loom::DocraftLoomPdfCreator> edit_creator()

Returns the fully-wired creator built by the last parse()/ load_from_file() call.

Mirrors DocraftLoomNode::edit_layout_box()’s non-const-accessor-for-mutable-access convention.

DocraftLoomTreeBuilder

The only component depending on both docraft::craft and docraft::loom — converts a generic DocraftParsedElement tree into a typed DocraftLoomNode tree, resolving ${...}/<Foreach> templating per node as it builds (see Templating).

class DocraftLoomTreeBuilder

Translates a generic docraft::craft::DocraftParsedElement tree (produced by docraft::craft::DocraftCraftLanguageParser, which has zero knowledge of loom) into an actual tree of docraft::loom::nodes::DocraftLoomNode.

This is the only component depending on both docraft::craft and docraft::loom &#8212; keeping the craft parser itself fully engine-agnostic (see the plan’s “Craft parser: generic + a separate loom builder layer”).

Public Functions

explicit DocraftLoomTreeBuilder(std::shared_ptr<docraft::templating::DocraftTemplateEngine> template_engine = nullptr)

Constructs the builder.

Parameters:

template_engine – Resolves ${variable}/${data("field")} in Text/Title/ Subtitle content, Image src, and <Foreach>’s own model attribute. Defaults to a fresh, empty engine (no variables registered) if not given, so ${...} expressions simply pass through unresolved rather than requiring a caller to always supply one.

std::shared_ptr<nodes::DocraftLoomNode> build(const std::shared_ptr<docraft::craft::DocraftParsedElement> &element)

Builds a loom node (and, recursively, its subtree) from a parsed element.

Parameters:

element – The parsed element to translate. May be null (returns nullptr).

Throws:

docraft::exception::DataFormatException – if element->tag_name is not a tag this builder recognizes.

Returns:

The built node, or nullptr if element is null or element->common.visible is explicitly false (the subtree is simply not constructed, per the plan’s “visible is resolved by the builder” design).

void set_default_font_family(const std::string &font_family)

Sets the font family applied to Text/Title/Subtitle/PageNumber/table-cell nodes built afterwards that don’t carry their own font_name attribute (from <Settings><Fonts default="...">).

Unset by default, in which case such nodes keep DocraftLoomText’s own hardcoded fallback.

DocraftCraftLanguageParser

Generic, engine-agnostic XML parser (pugixml-based). Holds one IDocraftParser per recognized tag and produces a tag-agnostic DocraftParsedElement tree with zero knowledge of layout or rendering.

class DocraftCraftLanguageParser

Parses the Craft Language into a generic DocraftParsedElement tree.

Fully engine-agnostic: zero dependency on any rendering/layout engine (in particular, no docraft::loom include anywhere). For each XML element, the registered IDocraftParser produces the tag-specific payload, common attributes are parsed once generically, and children are recursed into &#8212; except <Table>, whose row/cell structure is parsed entirely inside DocraftTableParser itself (see ParsedTableData), so it is not recursed into generically.

Turning a parsed tree into actual loom nodes is the job of the separate docraft::loom::craft::DocraftLoomTreeBuilder, not this class.

Public Functions

DocraftCraftLanguageParser()

Constructs a parser and registers the default tag parsers.

~DocraftCraftLanguageParser() = default
std::shared_ptr<DocraftParsedElement> parse(const std::string &craft_language_source)

Parses craft language source (a single root element) as a string.

Parameters:

craft_language_source – XML source as string.

Returns:

The parsed tree rooted at the document’s root element.

std::shared_ptr<DocraftParsedElement> load_from_file(const std::string &file_path)

Loads and parses craft language source from file.

Parameters:

file_path – Path to XML file.

Returns:

The parsed tree rooted at the document’s root element.

std::shared_ptr<DocraftParsedElement> parse_node(const pugi::xml_node &xml_node)

Parses a single XML element (and, generically, its subtree) into a DocraftParsedElement.

Parameters:

xml_node – XML node.

Throws:
  • docraft::exception::DataFormatException – if no parser is registered for the element’s tag name.

  • docraft::exception::InvalidInputException – on structurally invalid nesting (e.g. a Text-like tag containing another Text-like child, or a non-Text child of a List).

Returns:

The parsed element.

IDocraftParser

Interface for single-tag parsers.

class IDocraftParser

Interface for Craft language tag parsers.

Implementations translate a single XML element into a tag-specific, plain data-transfer struct (e.g. ParsedRectangleData), returned type-erased via std::any. This interface has no dependency on any rendering/layout engine &#8212; common attributes (x/y/width/height/…) and child recursion are handled once, generically, by DocraftCraftLanguageParser itself, not by individual parsers.

Subclassed by docraft::craft::parser::DocraftBlackLineParser, docraft::craft::parser::DocraftChartParser, docraft::craft::parser::DocraftCircleParser, docraft::craft::parser::DocraftForeachParser, docraft::craft::parser::DocraftImageParser, docraft::craft::parser::DocraftLayoutParser, docraft::craft::parser::DocraftLineParser, docraft::craft::parser::DocraftListParser, docraft::craft::parser::DocraftNewPageParser, docraft::craft::parser::DocraftPageNumberParser, docraft::craft::parser::DocraftParagraphParser, docraft::craft::parser::DocraftPolygonParser, docraft::craft::parser::DocraftRectangleParser, docraft::craft::parser::DocraftSectionParser, docraft::craft::parser::DocraftSeriesParser, docraft::craft::parser::DocraftTableParser, docraft::craft::parser::DocraftTextParser, docraft::craft::parser::DocraftTriangleParser, docraft::craft::parser::DocraftUListParser

Public Functions

virtual ~IDocraftParser() = default

Virtual destructor.

virtual std::any parse(const pugi::xml_node &craft_language_source) = 0

Parses an XML element into its tag-specific payload.

Parameters:

craft_language_source – XML node to parse.

Returns:

Type-erased Parsed<Tag>Data struct.

Element Parsers

Each parser translates one XML tag into a Parsed<Tag>Data payload attached to the corresponding DocraftParsedElement.

class DocraftTextParser : public docraft::craft::IDocraftParser

Parser for <Text>, <Title> and <Subtitle> elements (all produce a ParsedTextData, differing only in the tag-based defaults applied).

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a text-like XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedTextData.

class DocraftImageParser : public docraft::craft::IDocraftParser

Parser for image nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses an image XML node.

Parameters:

craft_language_source – XML node.

Throws:

docraft::exception::InvalidInputException – if both src and data are present, or if base64 data is missing/invalid dimensions.

Returns:

ParsedImageData.

class DocraftRectangleParser : public docraft::craft::IDocraftParser

Parser for rectangle nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a rectangle XML node into a ParsedRectangleData.

Parameters:

craft_language_source – XML node.

Returns:

ParsedRectangleData.

class DocraftCircleParser : public docraft::craft::IDocraftParser

Parser for circle nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a circle XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedCircleData.

class DocraftTriangleParser : public docraft::craft::IDocraftParser

Parser for triangle nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a triangle XML node.

Parameters:

craft_language_source – XML node.

Throws:

docraft::exception::InvalidInputException – if points is present but does not have exactly 3 entries.

Returns:

ParsedTriangleData.

class DocraftLineParser : public docraft::craft::IDocraftParser

Parser for line nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a line XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedLineData.

class DocraftPolygonParser : public docraft::craft::IDocraftParser

Parser for polygon nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a polygon XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedPolygonData.

class DocraftTableParser : public docraft::craft::IDocraftParser

Parser for table nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a table XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedTableData.

class DocraftListParser : public docraft::craft::IDocraftParser

Parser for ordered list nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a list XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedListData with kind = kOrdered.

class DocraftUListParser : public docraft::craft::IDocraftParser

Parser for unordered list nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses an unordered list XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedListData with kind = kUnordered.

class DocraftLayoutParser : public docraft::craft::IDocraftParser

Parser for layout nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a layout XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedLayoutData.

class DocraftParagraphParser : public docraft::craft::IDocraftParser

Parser for paragraph nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a paragraph XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedParagraphData.

class DocraftBlackLineParser : public docraft::craft::IDocraftParser

Parser for blank line nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a blank line XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedBlankLineData.

class DocraftNewPageParser : public docraft::craft::IDocraftParser

Parser for forced-page-break nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a <NewPage> XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedNewPageData.

class DocraftPageNumberParser : public docraft::craft::IDocraftParser

Parser for page number nodes.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a page number XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedPageNumberData.

class DocraftSectionParser : public docraft::craft::IDocraftParser

Parser for <Header>, <Body> and <Footer> elements (all produce a ParsedSectionData &#8212; there is no tag-based default distinction between them, unlike Text/Title/Subtitle).

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a section-like XML node.

Parameters:

craft_language_source – XML node.

Returns:

ParsedSectionData.

Note: <Header>/<Body>/<Footer> all parse through this single DocraftSectionParser (producing ParsedSectionData) rather than one class per tag; <Settings>/<Metadata> are not tag parsers at all — they’re read directly by DocraftLoomCraftLanguageParser above.

class DocraftForeachParser : public docraft::craft::IDocraftParser

Parser for <Foreach> elements.

Public Functions

virtual std::any parse(const pugi::xml_node &craft_language_source) override

Parses a <Foreach> XML node.

Parameters:

craft_language_source – XML node.

Throws:

docraft::exception::InvalidInputException – if both or neither of model/n are present, or if n is negative.

Returns:

ParsedForeachData.