Skip to content

Commit

Permalink
Adds .header
Browse files Browse the repository at this point in the history
Provides a document level `.header` method passing its
block a header object having essentially the same
functionality as a table cell but rendering as a document
header.

It writes content to a document level header_content object
rendered separately as `word/header.xml`.

This means you can write

```
docx.header do |header|
  header.p 'hello there'
end
```

or

```
docx.header do |header|
  header.table [[one cell]]
end
```
  • Loading branch information
Ben Ketron committed Jan 9, 2020
1 parent cd015cc commit 5895814
Show file tree
Hide file tree
Showing 16 changed files with 283 additions and 44 deletions.
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ docx.page # starts a new page.

Page numbers can be added to the footer via the `page_numbers` method. The method accepts optional parameters for controlling the alignment, label and size of the text.

*Page numbers are turned off by default, but they supercede the `.footer` when turned on.*
*Page numbers are turned off by default.*

```ruby
docx.page_numbers true do
Expand All @@ -316,24 +316,32 @@ end

The `size` option and the `label_size` and `number_size` options are mutually exclusive.


### Footer

A footer appearing on every page can be added via the `footer` method. Its block takes a footer object that supports text and table methods.

*This is superceded by `page_numbers`, but can be used instead to provide a more complext page number footer.*
_This is superceded by `page_numbers`, but can be used instead to provide a more complex page number footer._

```ruby
docx.footer do |footer|
footer.p do
text 'Pages '
text 'Pages '
field :page
text ' of '
field :numpages
end
end
```

### Header

A header appearing on every page can be added via the `header` method. Its block takes a header object that supports text and table methods.

```ruby
docx.header do |header|
header.p 'hello there'
end
```

### Fonts

Expand Down Expand Up @@ -456,11 +464,10 @@ PAGE and NUMPAGES fields can be added to runs using the `field` method
docx.p do
text 'Pages '
field :page
text ' to '
text ' to '
field :numpages
```


### Links

Links can be added inside paragraphs using the `link` method. The method accepts several optional parameters for controlling the style and behavior of the rule.
Expand Down Expand Up @@ -867,4 +874,4 @@ A tip of the hat to the wonderful PDF generation library [Prawn](https://github.

Copyright (c) 2014 Trade Informatics, Inc

[MIT License](https://github.com/trade-informatics/caracal/blob/master/LICENSE.txt)
[MIT License](https://github.com/trade-informatics/caracal/blob/master/LICENSE.txt)
8 changes: 8 additions & 0 deletions lib/caracal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,12 @@ def self.root
include Caracal::Core::Rules
include Caracal::Core::Tables
include Caracal::Core::Text
end

Caracal::Core::Models::HeaderModel.class_eval do
include Caracal::Core::Images
include Caracal::Core::Lists
include Caracal::Core::Rules
include Caracal::Core::Tables
include Caracal::Core::Text
end
5 changes: 2 additions & 3 deletions lib/caracal/core/footer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
module Caracal
module Core

# This module encapsulates all the functionality related to adding tables
# to the document.
# This module encapsulates all the functionality related to adding a
# footer on every page of the document.
#
module Footer
def self.included(base)
Expand All @@ -29,6 +29,5 @@ def footer(*args, &block)
end
end
end

end
end
32 changes: 32 additions & 0 deletions lib/caracal/core/header.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'caracal/core/models/header_model'
require 'caracal/errors'


module Caracal
module Core

# This module encapsulates all the functionality related to adding a header
# to every page of the document.
#
module Header
def self.included(base)
base.class_eval do

#-------------------------------------------------------------
# Public Methods
#-------------------------------------------------------------

def header(*args, &block)
options = Caracal::Utilities.extract_options!(args)

model = Caracal::Core::Models::HeaderModel.new(options, &block)

@header_content = model

model
end
end
end
end
end
end
42 changes: 42 additions & 0 deletions lib/caracal/core/models/header_model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'caracal/core/models/base_model'
require 'caracal/core/models/margin_model'
require 'caracal/core/models/paragraph_model'


module Caracal
module Core
module Models

# This class handles block options passed to tables via their data
# collections.
#
class HeaderModel < BaseModel

#-------------------------------------------------------------
# Configuration
#-------------------------------------------------------------

# initialization
def initialize(options={}, &block)
super options, &block
end

#-------------------------------------------------------------
# Public Methods
#-------------------------------------------------------------

#=============== DATA ACCESSORS =======================

def contents
@contents ||= []
end

#=============== VALIDATION ===========================

def valid?
contents.size > 0
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/caracal/core/models/relationship_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class RelationshipModel < BaseModel
TYPE_MAP = {
font: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable',
footer: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer',
header: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/header',
image: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
link: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
numbering: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering',
Expand Down
45 changes: 23 additions & 22 deletions lib/caracal/core/relationships.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,43 @@

module Caracal
module Core

# This module encapsulates all the functionality related to registering and
# This module encapsulates all the functionality related to registering and
# retrieving relationships.
#
module Relationships
def self.included(base)
base.class_eval do

#-------------------------------------------------------------
# Configuration
#-------------------------------------------------------------

attr_reader :relationship_counter


#-------------------------------------------------------------
# Class Methods
#-------------------------------------------------------------

def self.default_relationships
[
{ target: 'fontTable.xml', type: :font },
{ target: 'footer1.xml', type: :footer },
{ target: 'header1.xml', type: :header },
{ target: 'numbering.xml', type: :numbering },
{ target: 'settings.xml', type: :setting },
{ target: 'styles.xml', type: :style }
]
]
end


#-------------------------------------------------------------
# Public Methods
#-------------------------------------------------------------

#============== ATTRIBUTES ==========================

def relationship(options={}, &block)
id = relationship_counter.to_i + 1
options.merge!({ id: id })
Expand All @@ -53,38 +54,38 @@ def relationship(options={}, &block)
end
rel
end


#============== GETTERS =============================

def relationships
@relationships ||= []
end

def find_relationship(target)
relationships.find { |r| r.matches?(target) }
end


#============== REGISTRATION ========================

def register_relationship(model)
unless r = find_relationship(model.relationship_target)
relationships << model
r = model
end
r
end

def unregister_relationship(target)
if r = find_relationship(target)
relationships.delete(r)
end
end

end
end
end

end
end
11 changes: 11 additions & 0 deletions lib/caracal/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'caracal/core/file_name'
require 'caracal/core/fonts'
require 'caracal/core/footer'
require 'caracal/core/header'
require 'caracal/core/iframes'
require 'caracal/core/ignorables'
require 'caracal/core/images'
Expand All @@ -28,6 +29,7 @@
require 'caracal/renderers/document_renderer'
require 'caracal/renderers/fonts_renderer'
require 'caracal/renderers/footer_renderer'
require 'caracal/renderers/header_renderer'
require 'caracal/renderers/numbering_renderer'
require 'caracal/renderers/package_relationships_renderer'
require 'caracal/renderers/relationships_renderer'
Expand Down Expand Up @@ -65,6 +67,7 @@ class Document
include Caracal::Core::Text

include Caracal::Core::Footer
include Caracal::Core::Header


#------------------------------------------------------
Expand Down Expand Up @@ -153,6 +156,7 @@ def render
render_custom(zip)
render_fonts(zip)
render_footer(zip)
render_header(zip)
render_settings(zip)
render_styles(zip)
render_document(zip)
Expand Down Expand Up @@ -228,6 +232,13 @@ def render_footer(zip)
zip.write(content)
end

def render_header(zip)
content = ::Caracal::Renderers::HeaderRenderer.render(self)

zip.put_next_entry('word/header1.xml')
zip.write(content)
end

def render_media(zip)
images = relationships.select { |r| r.relationship_type == :image }
images.each do |rel|
Expand Down
1 change: 1 addition & 0 deletions lib/caracal/renderers/content_types_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def to_xml
xml.send 'Override', { 'PartName' => '/docProps/custom.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.custom-properties+xml' }
xml.send 'Override', { 'PartName' => '/word/document.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml' }
xml.send 'Override', { 'PartName' => '/word/footer1.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml' }
xml.send 'Override', { 'PartName' => '/word/header1.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml' }
xml.send 'Override', { 'PartName' => '/word/fontTable.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml' }
xml.send 'Override', { 'PartName' => '/word/numbering.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml' }
xml.send 'Override', { 'PartName' => '/word/settings.xml', 'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml' }
Expand Down
3 changes: 3 additions & 0 deletions lib/caracal/renderers/document_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ def to_xml
if rel = document.find_relationship('footer1.xml')
xml['w'].footerReference({ 'r:id' => rel.formatted_id, 'w:type' => 'default' })
end
if rel = document.find_relationship('header1.xml')
xml['w'].headerReference({ 'r:id' => rel.formatted_id, 'w:type' => 'default' })
end
xml['w'].pgSz page_size_options
xml['w'].pgMar page_margin_options
end
Expand Down
2 changes: 1 addition & 1 deletion lib/caracal/renderers/footer_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class FooterRenderer < DocumentRenderer
# Public Methods
#-------------------------------------------------------------

# This method produces the xml required for the `word/settings.xml`
# This method produces the xml required for the `word/footer1.xml`
# sub-document.
#
def to_xml
Expand Down
Loading

0 comments on commit 5895814

Please sign in to comment.