diff --git a/Changes b/Changes index 82f0c82..5fdb20b 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,9 @@ {{$NEXT}} + - Fix setting of DOCTYPE in external Dtd 0.1.16 2023-11-15T10:09:02+13:00 - - Always wrap XML content with 0 or root elements in a DocumentFragment + - Always wrap XML content with 0 or many root elements in a + DocumentFragment to ensure validity - Handle 'Artifact' tags in the structure tree 0.1.15 2023-11-10T08:07:05+13:00 diff --git a/docs/PDF/Tags/XML-Writer.md b/docs/PDF/Tags/XML-Writer.md index 7135a57..5cb4bb1 100644 --- a/docs/PDF/Tags/XML-Writer.md +++ b/docs/PDF/Tags/XML-Writer.md @@ -16,7 +16,7 @@ Synopsis use PDF::Tags::XML-Writer; my PDF::Class $pdf .= open: "t/write-tags.pdf"; my PDF::Tags::Reader $tags .= read: :$pdf; - my PDF::Tags::XML-Writer $xml-writer .= new: :debug, :root-tag; + my PDF::Tags::XML-Writer $xml-writer .= new: :debug; # atomic write say $xml-writer.Str($tags); # streamed write diff --git a/docs/index.md b/docs/index.md index cdef8b9..2682ba7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -298,7 +298,7 @@ text is being inserted as a paragraph in the structure tree. This tag may be used in the structure tree, or at the content level to defined attributes of a graphics sequence. Its usage is similar to the XHTML `span` tag. ```raku -$gfx.tag: Span, :Lang, { +$gfx.tag: Span: :Lang, { .say('Hasta la vista', :position[50, 80]); } ``` @@ -342,6 +342,51 @@ $page.graphics: -> $gfx { ``` +### Content Continuation + +Content sometimes needs to be continued across graphics objects, such as a paragraph that +spans multiple pages. The `mark` method may be called repeatably to achieve this: + +```raku +use PDF::Class; +use PDF::Tags; +use PDF::Tags::Elem; +use PDF::Page; +use PDF::Content::FontObj; + +my PDF::Class $pdf .= new; +my PDF::Tags $tags .= create: :$pdf; +my PDF::Tags::Elem $doc = $tags.Document; +my PDF::Page $page = $pdf.add-page; +my PDF::Content::FontObj $font = $pdf.core-font: :family; +my PDF::Tags::Elem $para = $doc.Paragraph; + +$page.graphics: -> $gfx { + + $para.mark: $gfx, { + .say('This paragraph starts on first page...', + :$font, + :font-size(15), + :position[50, 600]); + }; + +} + +$page = $pdf.add-page; +$page.graphics: -> $gfx { + + $para.mark: $gfx, { + .say('...and finishes on the second page', + :$font, + :font-size(15), + :position[50, 600]); + }; + +} + +$pdf.save-as: "span.pdf"; +``` + ### Tagging and Metadata If a PDF document is tagged for accessibility, additional metadata usually also needs to be set-up; typically `Title`, `Author`, `Subject`, `Keywords` and language. For example: diff --git a/lib/PDF/Tags/Node.rakumod b/lib/PDF/Tags/Node.rakumod index 478bf89..ac6b06b 100644 --- a/lib/PDF/Tags/Node.rakumod +++ b/lib/PDF/Tags/Node.rakumod @@ -15,7 +15,7 @@ class PDF::Tags::Node { my subset TagName of Str is export(:TagName) where Str:U | /^$/; - has PDF::Tags::Node::Root $.root is required handles; + has PDF::Tags::Node::Root $.root is required handles; has PDF::Page $.Pg; # current page scope has $.cos is required; method set-cos($!cos) { } diff --git a/lib/PDF/Tags/XML-Writer.rakumod b/lib/PDF/Tags/XML-Writer.rakumod index d61fdda..a1066a0 100644 --- a/lib/PDF/Tags/XML-Writer.rakumod +++ b/lib/PDF/Tags/XML-Writer.rakumod @@ -92,6 +92,7 @@ method say(IO::Handle $fh, PDF::Tags::Node $item, :$depth = 0) { multi method stream-xml(PDF::Tags::Node::Root $_, UInt :$depth is copy = 0) { self!line(''); + $!root-tag //= 'DocumentFragment' if .elems != 1; if $!dtd && $!valid { my $doctype = $!root-tag; $doctype //= .name with .kids.head; @@ -99,7 +100,6 @@ multi method stream-xml(PDF::Tags::Node::Root $_, UInt :$depth is copy = 0) { self!frag: qq{}; } self!line($!css) if $!style; - $!root-tag //= 'DocumentFragment' if .elems != 1; self!line('<' ~ $_ ~ '>', $depth++) with $!root-tag; @@ -211,9 +211,6 @@ multi method stream-xml(PDF::Tags::Elem $node, UInt :$depth is copy = 0) { if $role { %attributes:delete; } - if $!marks { - %attributes = $_ with $actual-text; - } %attributes = $_ with $node.Lang; if $name eq 'Link' { @@ -303,7 +300,7 @@ method !marked-content(PDF::Tags::Mark $node, :$depth!) { my $text = $node.actual-text // do { my @text = $node.kids.map: { when PDF::Tags::Mark { - my $text = self!marked-content($_, :$depth); + self!marked-content($_, :$depth); } when PDF::Tags::Text { xml-escape(.Str) } default { die "unhandled tagged content: {.WHAT.raku}"; } @@ -338,7 +335,7 @@ method !marked-content(PDF::Tags::Mark $node, :$depth!) { use PDF::Tags::XML-Writer; my PDF::Class $pdf .= open: "t/write-tags.pdf"; my PDF::Tags::Reader $tags .= read: :$pdf; - my PDF::Tags::XML-Writer $xml-writer .= new: :debug, :root-tag; + my PDF::Tags::XML-Writer $xml-writer .= new: :debug; # atomic write say $xml-writer.Str($tags); # streamed write