eterps-publishing-grf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Erik Terpstra
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = publishing-grf
2
+
3
+ Description goes here.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Erik Terpstra. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "publishing-grf"
8
+ gem.summary = %Q{TODO}
9
+ gem.email = "erik@ruby-lang.nl"
10
+ gem.homepage = "http://github.com/eterps/publishing-grf"
11
+ gem.authors = ["Erik Terpstra"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'spec/rake/spectask'
20
+ Spec::Rake::SpecTask.new(:spec) do |spec|
21
+ spec.libs << 'lib' << 'spec'
22
+ spec.spec_files = FileList['spec/**/*_spec.rb']
23
+ spec.spec_opts = ['-fs -c']
24
+ end
25
+
26
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
27
+ spec.libs << 'lib' << 'spec'
28
+ spec.pattern = 'spec/**/*_spec.rb'
29
+ spec.rcov = true
30
+ end
31
+
32
+
33
+ task :default => :spec
34
+
35
+ require 'rake/rdoctask'
36
+ Rake::RDocTask.new do |rdoc|
37
+ if File.exist?('VERSION.yml')
38
+ config = YAML.load(File.read('VERSION.yml'))
39
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
40
+ else
41
+ version = ""
42
+ end
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "publishing-grf #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
49
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,10 @@
1
+ $: << "#{File.dirname __FILE__}"
2
+
3
+ module Publishing
4
+ module GRF
5
+ def self.open(path); Publishing::GRF::Document.new(IO.read(path)) end
6
+ end
7
+ end
8
+
9
+ require 'grf/core'
10
+ require 'grf/reader'
@@ -0,0 +1,104 @@
1
+ require 'rubygems'
2
+ require 'facets/dictionary'
3
+
4
+ module Enumerable
5
+ def group_by(h = Hash)
6
+ r = h.new
7
+ each{|e| (r[yield(e)] ||= []) << e}
8
+ r
9
+ end
10
+ end
11
+
12
+ module Publishing
13
+ module GRF
14
+ module Node
15
+ def content; children.map{|n| n.content} end
16
+ end
17
+ end
18
+ end
19
+
20
+ class Publishing::GRF::Block
21
+ attr_reader :parent, :id, :parts, :fontsizes
22
+ attr_accessor :top, :right, :bottom, :left, :width, :height
23
+
24
+ def initialize(params = {})
25
+ @parent = params[:parent]
26
+ @id = params[:id]
27
+ @fontsizes = params[:fontsizes].to_s.split(/\s*,\s*/)
28
+ @parts = []
29
+ end
30
+
31
+ def top; @top or parts.min{|a, b| a.top <=> b.top }.top end
32
+ def left; @left or parts.min{|a, b| a.left <=> b.left}.left end
33
+ def bottom; @bottom or parts.max{|a, b| a.bottom <=> b.bottom}.bottom end
34
+ def right; @right or parts.max{|a, b| a.right <=> b.left}.right end
35
+ def width; @width or right - left end
36
+ def height; @height or bottom - top end
37
+
38
+ def fontsize; @fontsizes.first end
39
+ end
40
+
41
+ class Publishing::GRF::Element
42
+ attr_reader :parent, :id, :uri
43
+ attr_accessor :content
44
+
45
+ def initialize(params = {})
46
+ @parent = params[:parent]
47
+ @id = params[:id]
48
+ @uri = params[:uri]
49
+ end
50
+ end
51
+
52
+ class Publishing::GRF::Frame
53
+ include Publishing::GRF::Node
54
+
55
+ attr_reader :parent, :elements, :blocks, :number
56
+
57
+ def initialize(params = {})
58
+ @parent = params[:parent]
59
+ @number = params[:number]
60
+ @elements = []
61
+ @blocks = []
62
+ end
63
+
64
+ def images; @elements.select{|n| n.image?} end
65
+
66
+ alias :children :elements
67
+ end
68
+
69
+ class Publishing::GRF::Page
70
+ include Publishing::GRF::Node
71
+
72
+ attr_reader :frames, :id, :number, :section_name
73
+ attr_accessor :parent
74
+
75
+ def initialize(params = {})
76
+ @frames = []
77
+ @id = params[:id]
78
+ @number = params[:number]
79
+ @section_name = params[:section_name]
80
+ end
81
+
82
+ def elements; @frames.map{|n| n.elements}.flatten end
83
+
84
+ alias :children :frames
85
+ end
86
+
87
+ class Publishing::GRF::Document
88
+ include Publishing::GRF::Node
89
+
90
+ attr_reader :pages
91
+
92
+ def initialize(source = nil)
93
+ @pages = []
94
+ populate source if source
95
+ end
96
+
97
+ def elements; @pages.map{|n| n.elements}.flatten end
98
+
99
+ def sections
100
+ @pages.group_by(Dictionary){|n| n.section_name}
101
+ end
102
+
103
+ alias :children :pages
104
+ end
@@ -0,0 +1,75 @@
1
+ require 'cgi'
2
+ require 'rexml/document'
3
+ require 'rexml/streamlistener'
4
+
5
+ class Publishing::GRF::Reader
6
+ include REXML::StreamListener
7
+
8
+ attr_reader :pages
9
+
10
+ def initialize
11
+ @pages = []
12
+ end
13
+
14
+ def tag_start(name, attributes)
15
+ @in_element = false
16
+
17
+ if name == 'div'
18
+ if attributes['class'] == 'page'
19
+ @pages << Publishing::GRF::Page.new(
20
+ :id => attributes['data-page-id'],
21
+ :number => attributes['data-page-number'],
22
+ :section_name => CGI.unescapeHTML(attributes['data-section-name'])
23
+ )
24
+ elsif attributes['class'] == 'frame'
25
+ @pages.last.frames << Publishing::GRF::Frame.new(
26
+ :parent => @pages.last
27
+ )
28
+ elsif attributes['class'].split.include?('element')
29
+ @in_element = true
30
+ @pages.last.frames.last.elements << Publishing::GRF::Element.new(
31
+ :parent => @pages.last.frames.last,
32
+ :id => attributes['class'].sub(/\s*element\s*/, '')
33
+ )
34
+ elsif attributes['class'].split.include?('block')
35
+ @in_element = true
36
+ @pages.last.frames.last.blocks << Publishing::GRF::Block.new(
37
+ :parent => @pages.last.frames.last,
38
+ :id => attributes['class'].sub(/block\s*element\s*/, ''),
39
+ :fontsizes => attributes['data-fontsizes']
40
+ )
41
+ end
42
+ elsif name == 'img'
43
+ @pages.last.frames.last.elements << Publishing::GRF::Element.new(
44
+ :parent => @pages.last.frames.last,
45
+ :id => 'image',
46
+ :uri => attributes['src']
47
+ )
48
+ elsif %w[em b i span].include?(name)
49
+ @in_element = true
50
+ tag = attributes['class'] ? %{<#{name} class="#{attributes['class']}">} : "<#{name}>"
51
+ (@pages.last.frames.last.elements.last.content ||= '') << tag
52
+ end
53
+ end
54
+
55
+ def tag_end(name)
56
+ if %w[em b i span].include?(name)
57
+ @pages.last.frames.last.elements.last.content << "</#{name}>"
58
+ end
59
+ end
60
+
61
+ def text(str)
62
+ (@pages.last.frames.last.elements.last.content ||= '') << str.gsub("\n", ' ') if @in_element and str =~ /\S/
63
+ end
64
+ end
65
+
66
+ class Publishing::GRF::Document
67
+ private
68
+
69
+ def populate(source)
70
+ listener = Publishing::GRF::Reader.new
71
+ REXML::Parsers::StreamParser.new(source, listener).parse
72
+ @pages = listener.pages
73
+ @pages.each{|n| n.parent = self}
74
+ end
75
+ end
@@ -0,0 +1,50 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{publishing-grf}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Erik Terpstra"]
9
+ s.date = %q{2009-06-16}
10
+ s.email = %q{erik@ruby-lang.nl}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "lib/publishing/grf.rb",
23
+ "lib/publishing/grf/core.rb",
24
+ "lib/publishing/grf/reader.rb",
25
+ "publishing-grf.gemspec",
26
+ "spec/fixtures/sample.html",
27
+ "spec/publishing-grf_spec.rb",
28
+ "spec/spec_helper.rb"
29
+ ]
30
+ s.has_rdoc = true
31
+ s.homepage = %q{http://github.com/eterps/publishing-grf}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.1}
35
+ s.summary = %q{TODO}
36
+ s.test_files = [
37
+ "spec/spec_helper.rb",
38
+ "spec/publishing-grf_spec.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 2
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ else
47
+ end
48
+ else
49
+ end
50
+ end
@@ -0,0 +1,86 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <body>
4
+ <div class="page" data-page-number="1" data-page-id="1_1" data-section-name="Frontpage">
5
+ <div class="frame" data-reference="article1" data-source="nitf">
6
+ <div class="blocks">
7
+ <div data-x2="51.887" class="block element1" data-x="44.972" data-y="10.857" data-y2="13.972"/>
8
+ <div data-x2="49.105" class="block element2" data-x="44.972" data-y="16.759" data-y2="17.292"/>
9
+ <div data-x2="44.593" class="block element0" data-x="36.263" data-y="10.785" data-y2="17.195"/>
10
+ </div>
11
+ <div class="element hl1">This is headline 1.1</div>
12
+ <div class="element p">This is paragraph 1.1</div>
13
+ <div class="element bibliography">This is bibliography 1.1</div>
14
+ <img src="images/section1_page1_article1_1.jpg"/>
15
+ </div>
16
+ <div class="frame" data-reference="article2" data-source="nitf">
17
+ <div class="blocks">
18
+ <div data-x2="40.847" class="block element1" data-x="10.172" data-y="70.263" data-y2="72.458"/>
19
+ <div data-x2="25.639" class="block element3" data-x="10.172" data-y="73.562" data-y2="75.783"/>
20
+ <div data-x2="18.134" class="block element7" data-x="10.171" data-y="77.319" data-y2="81.602"/>
21
+ <div data-x2="26.861" class="block element2" data-x="18.871" data-y="77.316" data-y2="95.333"/>
22
+ <div data-x2="18.138" class="block element2" data-x="10.171" data-y="82.262" data-y2="96.432"/>
23
+ </div>
24
+ <div class="element hl1">This is headline 1.2</div>
25
+ <div class="element hl2">This is subheadline 1.2.1</div>
26
+ <div class="element hl2">This is subheadline 1.2.2</div>
27
+ <div class="element byline">By our correspondent <span class="person">Person 1.1</span></div>
28
+ <div class="element dateline">This is headline 1.2</div>
29
+ <div class="element p">This is paragraph 1.2.1</div>
30
+ <div class="element p">This is paragraph 1.2.2</div>
31
+ <div class="element p">This is paragraph 1.2.3</div>
32
+ <div class="element p">This is paragraph 1.2.4</div>
33
+ <div class="element p">This is paragraph 1.2.5</div>
34
+ <div class="element p">This is paragraph 1.2.6</div>
35
+ <div class="element p">This is paragraph 1.2.7</div>
36
+ <div class="element p">This is paragraph 1.2.8</div>
37
+ <div class="element media-caption">This is caption 1.2</div>
38
+ <div class="element bibliography">This is bibliography 1.2</div>
39
+ </div>
40
+ </div>
41
+ <div class="page" data-page-number="2" data-page-id="1_2" data-section-name="Page 2">
42
+ <div class="frame" data-reference="article3" data-source="nitf">
43
+ <div class="blocks">
44
+ <div data-x2="68.002" class="block element1" data-x="10.17" data-y="76.906" data-y2="78.88"/>
45
+ <div data-x2="17.92" class="block element7" data-x="10.171" data-y="80.128" data-y2="85.162"/>
46
+ <div data-x2="26.839" class="block element2" data-x="18.871" data-y="80.125" data-y2="96.494"/>
47
+ <div data-x2="35.539" class="block element2" data-x="27.572" data-y="80.125" data-y2="85.502"/>
48
+ <div data-x2="44.239" class="block element2" data-x="36.272" data-y="80.125" data-y2="96.494"/>
49
+ <div data-x2="18.138" class="block element2" data-x="10.171" data-y="86.171" data-y2="96.494"/>
50
+ <div data-x2="52.94" class="block element2" data-x="44.973" data-y="89.468" data-y2="96.494"/>
51
+ <div data-x2="61.64" class="block element2" data-x="53.672" data-y="89.468" data-y2="96.494"/>
52
+ <div data-x2="70.339" class="block element2" data-x="62.373" data-y="89.468" data-y2="94.845"/>
53
+ <div data-x2="35.539" class="block element2" data-x="27.572" data-y="92.766" data-y2="96.494"/>
54
+ <div data-x2="68.915" class="block element2" data-x="63.538" data-y="95.49" data-y2="96.517"/>
55
+ <div data-x2="52.626" class="block element8" data-x="44.973" data-y="87.27" data-y2="88.822"/>
56
+ <div data-x2="61.549" class="block element12" data-x="54.039" data-y="81.751" data-y2="86.625"/>
57
+ <div data-x2="69.154" class="block element12" data-x="62.373" data-y="81.751" data-y2="84.976"/>
58
+ <div data-x2="64.832" class="block element12" data-x="62.373" data-y="85.598" data-y2="86.075"/>
59
+ <div data-x2="61.253" class="block element12" data-x="54.039" data-y="87.247" data-y2="88.274"/>
60
+ <div data-x2="59.91" class="block element11" data-x="54.039" data-y="80.619" data-y2="81.3"/>
61
+ <div data-x2="52.924" class="block element0" data-x="44.961" data-y="80.078" data-y2="87.037"/>
62
+ <div data-x2="35.518" class="block element0" data-x="27.565" data-y="86.121" data-y2="91.87"/>
63
+ </div>
64
+ <div class="element hl1">This is headline 2.1</div>
65
+ <div class="element byline">By our editor <span class="person">Person 2.1</span></div>
66
+ <div class="element dateline">This is dateline 2.1</div>
67
+ <div class="element p">This is paragraph 2.1.1</div>
68
+ <div class="element p">This is paragraph 2.1.2</div>
69
+ <div class="element p">This is paragraph 2.1.3</div>
70
+ <div class="element p">This is paragraph 2.1.4</div>
71
+ <div class="element p">This is paragraph 2.1.5</div>
72
+ <div class="element p">This is paragraph 2.1.6</div>
73
+ <div class="element p">This is paragraph 2.1.7</div>
74
+ <div class="element p">This is paragraph 2.1.8</div>
75
+ <div class="element p">This is paragraph 2.1.9</div>
76
+ <div class="element p">This is paragraph 2.1.10</div>
77
+ <div class="element p">This is paragraph 2.1.11</div>
78
+ <div class="element p">This is paragraph 2.1.12</div>
79
+ <div class="element media-caption">This is caption 2.1</div>
80
+ <div class="element bibliography">This bibliography 2.1</div>
81
+ <img src="images/section1_page2_article1_1.jpg"/>
82
+ <img src="images/section1_page2_article1_2.jpg"/>
83
+ </div>
84
+ </div>
85
+ </body>
86
+ </html>
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe 'an opened GRF document', :shared => true do
4
+ before do
5
+ filename = "#{File.dirname __FILE__}/fixtures/sample.html"
6
+ @@document ||= Publishing::GRF.open(filename)
7
+ end
8
+ end
9
+
10
+ describe 'A document' do
11
+ it_should_behave_like 'an opened GRF document'
12
+ before{ @it = @@document }
13
+
14
+ it 'has pages' do
15
+ @it.pages.length > 0
16
+ end
17
+
18
+ it 'has sections' do
19
+ @it.sections.length > 0
20
+ end
21
+
22
+ it 'has elements' do
23
+ @it.elements.length > 0
24
+ end
25
+ end
26
+
27
+ describe 'A page' do
28
+ it_should_behave_like 'an opened GRF document'
29
+ before{ @it = @@document.pages.first }
30
+
31
+ it 'has frames' do
32
+ @it.frames.length.should > 0
33
+ end
34
+
35
+ it 'has elements' do
36
+ @it.elements.length > 0
37
+ end
38
+ end
39
+
40
+ describe 'A frame' do
41
+ it_should_behave_like 'an opened GRF document'
42
+ before{ @it = @@document.pages.first.frames.first }
43
+
44
+ it 'has elements' do
45
+ @it.elements.length.should > 0
46
+ end
47
+
48
+ it 'has blocks' do
49
+ @it.blocks.length.should > 0
50
+ end
51
+ end
52
+
53
+ describe 'An element' do
54
+ it_should_behave_like 'an opened GRF document'
55
+ before{ @page = @@document.pages.first; @it = @page.elements.first }
56
+ end
57
+
58
+ describe 'A block' do
59
+ it_should_behave_like 'an opened GRF document'
60
+ before{ @frame = @@document.pages.first.frames.first; @it = @frame.blocks.first }
61
+
62
+ it 'has fontsizes' do
63
+ @it.fontsizes.length.should >= 0
64
+ end
65
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ require 'publishing/grf'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eterps-publishing-grf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Erik Terpstra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: erik@ruby-lang.nl
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - lib/publishing/grf.rb
33
+ - lib/publishing/grf/core.rb
34
+ - lib/publishing/grf/reader.rb
35
+ - publishing-grf.gemspec
36
+ - spec/fixtures/sample.html
37
+ - spec/publishing-grf_spec.rb
38
+ - spec/spec_helper.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/eterps/publishing-grf
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.2.0
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: TODO
65
+ test_files:
66
+ - spec/spec_helper.rb
67
+ - spec/publishing-grf_spec.rb