officedoc 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 433f8b39a4a7ce8011fe06a166effeb910d6947f
4
- data.tar.gz: 5823ce66d151beb15391e2a88a5aab8ca47fed35
3
+ metadata.gz: 34b7c7a92fb76a9d7393592087ba378fd022f018
4
+ data.tar.gz: ca9f2361b0e48c95e29667e26dfb126bc2888d66
5
5
  SHA512:
6
- metadata.gz: 48541c809c57543bd7d07042656861ebbba1fab06b5a2675bd1b33961dc59f14684b6c9040e550f9668bf9144551f49e4dee7756dac8adbcfa8ab1891cbd6b2a
7
- data.tar.gz: 1e972f0acbe8eefa166810443a2d4e684a8bb933abda97b1832677f3f2995ee360895a294cefdea112c7c4be87de8b214dcfe78e1c462b757d3f4bd960dce7fc
6
+ metadata.gz: 910f8dbfd5118d44fe66365cd3b17fc1c05d4db582ac573b36efd02ae9cb49c7781aef961e407b707f596637b339b359701cec21d357010e470dcf4c26992b64
7
+ data.tar.gz: a40568de299d516f11f2f176d32e26d1c07ab07ee21ee8cc68023049c3ab7c209556425f2a6a4d8d0e83b60639e6314fa0a75f8c575bc94a4b5a9a1610203533
@@ -0,0 +1,10 @@
1
+ *.docx binary
2
+ *.doc binary
3
+ *.xlsx binary
4
+ *.xls binary
5
+ *.pptx binary
6
+ *.ppt binary
7
+ *.odt binary
8
+ *.odp binary
9
+ *.ods binary
10
+ *.odg binary
data/.gitignore CHANGED
@@ -20,3 +20,4 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
+ **/.DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -1,3 +1,6 @@
1
+ branches:
2
+ only:
3
+ - master
1
4
  language: ruby
2
5
  rvm:
3
6
  - 2.1.0
@@ -5,3 +8,4 @@ rvm:
5
8
  env:
6
9
  global:
7
10
  secure: DzmZmBdrv+tIRNXyqAE1Z7/ksQOmBUThgpeKH2in2vzTZ8q5YAzeQat8YLTW+Z2UcIT7hQMUb+W11rUfPmDCBfcJFn5NaXNowoyHz+CeqJ5XjZtA05o96/8zu6wdh/3d8xfON703SgE7vFGOj3klIqVoBl2ABbk/p2A3sbS7mHs=
11
+ script: bundle exec rspec
File without changes
data/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # Officedoc
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/officedoc.svg)](http://badge.fury.io/rb/officedoc)
3
4
  [![GitHub version](https://badge.fury.io/gh/moonfly%2Fofficedoc.svg)](http://badge.fury.io/gh/moonfly%2Fofficedoc)
4
5
  [![Build Status](https://travis-ci.org/moonfly/officedoc.svg?branch=master)](https://travis-ci.org/moonfly/officedoc)
5
6
  [![Code Climate](https://codeclimate.com/github/moonfly/officedoc.png)](https://codeclimate.com/github/moonfly/officedoc)
7
+ [![Code Coverage](https://codeclimate.com/github/moonfly/officedoc/coverage.png)](https://codeclimate.com/github/moonfly/officedoc)
6
8
  [![Dependency Status](https://gemnasium.com/moonfly/officedoc.svg)](https://gemnasium.com/moonfly/officedoc)
7
9
 
8
10
  Parsing and constructing documents using XML-based Office formats: ODF and OOXML.
9
11
 
12
+ NOT FOR PUBLIC USE YET. ACTIVE INITIAL DEVELOPMENT IN PROGRESS.
13
+
10
14
  ## Installation
11
15
 
12
16
  Add this line to your application's Gemfile:
@@ -49,11 +53,13 @@ Semantic versioning (http://semver.org/spec/v2.0.0.html) is used.
49
53
  For a version number MAJOR.MINOR.PATCH, unless MAJOR is 0:
50
54
 
51
55
  1. MAJOR version is incremented when incompatible API changes are made,
52
- 2. MINOR version is incremented when functionality is added in a backwards-compatible manner, and
56
+ 2. MINOR version is incremented when functionality is added in a backwards-compatible manner,
53
57
  3. PATCH version is incremented when backwards-compatible bug fixes are made.
54
58
 
55
- Major version zero (0.y.z) is for initial development. Anything may change at any time.
56
- The public API should not be considered stable.
59
+ Major version "zero" (0.y.z) is for initial development. Anything may change at any time.
60
+ The public API should not be considered stable.
61
+ Furthermore, version "double-zero" (0.0.x) is not intended for public use,
62
+ as even minimal functionality is not guaranteed to be implemented yet.
57
63
 
58
64
  ## Dependencies
59
65
 
@@ -1,5 +1,9 @@
1
1
  require "officedoc/version"
2
+ require "officedoc/null_object"
3
+ require "officedoc/package"
2
4
 
3
5
  module Officedoc
4
- # Your code goes here...
6
+ def self.open(*args)
7
+ Officedoc::Package.new(*args)
8
+ end
5
9
  end
@@ -0,0 +1,12 @@
1
+ require "naught"
2
+
3
+ module Officedoc
4
+ private
5
+ NullObject = Naught.build do |config|
6
+ config.black_hole
7
+ config.traceable
8
+ end
9
+ def self.null
10
+ NullObject.get
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require "officedoc/package/raw"
2
+
3
+ module Officedoc
4
+ class Package
5
+
6
+ include NullObject::Conversions
7
+
8
+ attr_accessor :filename
9
+ attr_reader :raw
10
+
11
+ def initialize( filename: Officedoc.null, stream: Officedoc.null )
12
+ @filename = filename
13
+ unless Actual(stream)
14
+ stream = open( filename, "rb" ) if Actual(filename)
15
+ end
16
+ @raw = Raw.new( stream )
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ require "officedoc/package/raw/ruby_zip_engine"
2
+ require "officedoc/package/raw/parts"
3
+
4
+ module Officedoc
5
+ class Package
6
+ class Raw
7
+ attr_reader :zip_engine
8
+ attr_reader :stream
9
+
10
+ def initialize( stream, zip_engine: ::Officedoc::Package::Raw::RubyZipEngine )
11
+ @zip_engine = zip_engine
12
+ @stream = stream
13
+ end
14
+ private def zip_file
15
+ @zip_file ||= zip_engine.new(stream)
16
+ end
17
+
18
+ def file_names
19
+ zip_file.entries.map(&:name)
20
+ end
21
+ def parts
22
+ @parts ||= PartList.new zip_file
23
+ end
24
+ def document_type
25
+ @document_type ||= get_document_type
26
+ end
27
+ private def get_document_type
28
+ # Example: "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
29
+ main_doc_parts = parts.of_type "document.main+xml", partial: true
30
+ return "" if main_doc_parts.size != 1
31
+
32
+ match = /.*\.(.*)\.document\.main\+xml/.match(main_doc_parts[0].type)
33
+ match ? match[1] : ""
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,65 @@
1
+ require "nokogiri"
2
+ require "officedoc/package/raw/ruby_zip_engine"
3
+
4
+ module Officedoc
5
+ class Package
6
+ class Raw
7
+ class Part
8
+ attr_reader :name
9
+ attr_reader :type
10
+
11
+ def initialize(zip_file,xml_node)
12
+ @name = xml_node["PartName"]
13
+ @type = xml_node["ContentType"]
14
+ @zip_file = zip_file
15
+ end
16
+ private def file_name
17
+ name[1..-1]
18
+ end
19
+
20
+ def read_stream(&block)
21
+ @zip_file.entry_read_stream(file_name,&block)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ module Officedoc
29
+ class Package
30
+ class Raw
31
+ class PartList < SimpleDelegator
32
+ EntryName = '[Content_Types].xml'
33
+
34
+ def initialize(zip_file)
35
+ __setobj__([])
36
+ @zip_file = zip_file
37
+ read_from zip_file if zip_file
38
+ yield self if block_given?
39
+ end
40
+
41
+ def read_from(zip_file)
42
+ zip_file.entry_read_stream( EntryName ) do |stream|
43
+ doc = Nokogiri::XML(stream)
44
+ doc.css("Override[@PartName]").each do |node|
45
+ push Officedoc::Package::Raw::Part.new @zip_file, node
46
+ end
47
+ end
48
+ end
49
+
50
+ def of_type( type, regexp: false, partial: false )
51
+ select do |part|
52
+ if regexp
53
+ part.type.match(type)
54
+ elsif partial
55
+ part.type.include?(type)
56
+ else
57
+ part.type == type
58
+ end
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,36 @@
1
+ # Engine for RubyZip gem
2
+ require "zip"
3
+
4
+ module Officedoc
5
+ class Package
6
+ class Raw
7
+ class RubyZipEngine
8
+ def initialize(stream)
9
+ @f = ::Zip::File.new(stream, true, true)
10
+ @f.read_from_stream(stream)
11
+ end
12
+
13
+ def entries
14
+ @entries ||= get_entries
15
+ end
16
+ def entry(name)
17
+ @entries_by_name ||= {}
18
+ @entries_by_name.fetch(name) { get_entry(name) }
19
+ end
20
+ def entry_read_stream(name,&block)
21
+ entry(name).get_input_stream(&block)
22
+ end
23
+
24
+ private def get_entries
25
+ entries = []
26
+ @f.each { |entry| entries << entry }
27
+ entries
28
+ end
29
+ private def get_entry(name)
30
+ entries.find { |entry| entry.name == name } || Officedoc.null
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -1,3 +1,3 @@
1
1
  module Officedoc
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -5,22 +5,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'officedoc/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = "officedoc"
9
- spec.version = Officedoc::VERSION
10
- spec.authors = ["Andrey Pronin"]
11
- spec.email = ["moonfly.msk@gmail.com"]
12
- spec.summary = %q{Parsing and constructing ODF and OOXML documents}
13
- spec.description = %q{Parsing and constructing documents using XML-based Office formats: ODF and OOXML.}
14
- spec.homepage = "https://github.com/moonfly/officedoc"
15
- spec.license = "GPL-3"
8
+ spec.name = "officedoc"
9
+ spec.version = Officedoc::VERSION
10
+ spec.required_ruby_version = '>= 2.1.0'
11
+ spec.authors = ["Andrey Pronin"]
12
+ spec.email = ["moonfly.msk@gmail.com"]
13
+ spec.summary = %q{Parsing and constructing ODF and OOXML documents}
14
+ spec.description = %q{Parsing and constructing documents using XML-based Office formats: ODF and OOXML.}
15
+ spec.homepage = "https://github.com/moonfly/officedoc"
16
+ spec.license = "GPL-3"
16
17
 
17
- spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_development_dependency "bundler", "~> 1.6"
23
- spec.add_development_dependency "rake"
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_runtime_dependency "naught", "~> 1.0"
24
+ spec.add_runtime_dependency "rubyzip", "~> 1.1"
25
+ spec.add_runtime_dependency "nokogiri", "~> 1.6"
26
+
27
+ spec.add_development_dependency "bundler", ">= 1.5"
28
+ spec.add_development_dependency "rake", "~> 10.2"
24
29
  spec.add_development_dependency "rspec", "~> 3.0.0.beta2"
25
- spec.add_development_dependency "codeclimate-test-reporter"
30
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.3.0"
26
31
  end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Officedoc::Package::Raw::Part" do
4
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe "Officedoc::Package::Raw" do
4
+ def new_raw_for_file(name)
5
+ Officedoc::Package::Raw.new( file_stream(name) )
6
+ end
7
+
8
+ let(:raw_docx_sample_filename) { "samples/sample1.docx" }
9
+ let(:raw_docx_sample) { new_raw_for_file raw_docx_sample_filename }
10
+
11
+ it "should correctly count the number of files in package" do
12
+ expect(raw_docx_sample.file_names.count).to eq(count_files_in_zip raw_docx_sample_filename)
13
+ end
14
+ it "should correctly list the files in package" do
15
+ expect(raw_docx_sample.file_names).to match_array(list_files_in_zip raw_docx_sample_filename)
16
+ end
17
+
18
+ it "should list the parts" do
19
+ expect(raw_docx_sample.parts.count).to be > 0
20
+
21
+ expect(raw_docx_sample.parts.map(&:name)).to include "/word/document.xml"
22
+ expect(raw_docx_sample.parts.map(&:name)).to include "/docProps/core.xml"
23
+
24
+ expect(raw_docx_sample.parts.map(&:type)).to include "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
25
+ expect(raw_docx_sample.parts.map(&:type)).to include "application/vnd.openxmlformats-package.core-properties+xml"
26
+ end
27
+ it "should find the part by full type" do
28
+ parts = raw_docx_sample.parts.of_type "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
29
+ expect(parts.size).to eq 1
30
+ expect(parts[0].name).to eq "/word/document.xml"
31
+ end
32
+ it "should find the part by partial type" do
33
+ parts = raw_docx_sample.parts.of_type "wordprocessingml.document.main", partial: true
34
+ expect(parts.size).to eq 1
35
+ expect(parts[0].name).to eq "/word/document.xml"
36
+ end
37
+ it "should detect the document type" do
38
+ expect(raw_docx_sample.document_type).to eq "wordprocessingml"
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "Officedoc" do
4
+ it "should open OOXML package by filename" do
5
+ fn = rspec_file "samples/sample1.docx"
6
+ od = Officedoc.open( filename: fn )
7
+ expect(od).not_to be_nil
8
+ expect(od.filename).to eq(fn)
9
+ f = open(fn,"rb")
10
+ expect_identical_file_streams f, od.raw.stream
11
+ end
12
+ it "should open OOXML package from stream" do
13
+ fn = rspec_file "samples/sample1.docx"
14
+ f = open(fn,"rb")
15
+ od = Officedoc.open( stream: f )
16
+ expect(od).not_to be_nil
17
+ expect(od.raw.stream).not_to be_nil
18
+ expect(od.raw.stream).to eq(f)
19
+ end
20
+ end
Binary file
@@ -3,3 +3,25 @@ CodeClimate::TestReporter.start
3
3
 
4
4
  require 'officedoc'
5
5
 
6
+ Rspec_Root = Pathname(__FILE__).dirname
7
+ def rspec_file(tail)
8
+ Rspec_Root.join(tail)
9
+ end
10
+
11
+ Dir[rspec_file("support/**/*.rb")].each { |f| require f }
12
+ Dir[rspec_file("**/*_handlers.rb")].each { |f| require f }
13
+
14
+ RSpec.configure do |config|
15
+ config.order = "random"
16
+ config.filter_run focus: true
17
+ config.run_all_when_everything_filtered = true
18
+
19
+ config.include Support::FileHandlers
20
+ end
21
+
22
+
23
+
24
+
25
+
26
+
27
+
@@ -0,0 +1,25 @@
1
+ module Support
2
+ module FileHandlers
3
+ def expect_identical_file_streams(f1,f2)
4
+ f1.rewind
5
+ f2.rewind
6
+ expect(f1.read).to eq(f2.read)
7
+ end
8
+ def file_stream(name)
9
+ open( rspec_file(name), "rb" )
10
+ end
11
+ def count_files_in_zip(name)
12
+ `zipinfo -t #{rspec_file(name)} | sed -e "/ files.*/s///"`.to_i
13
+ end
14
+ def list_files_in_zip(name)
15
+ `zipinfo -1 #{rspec_file(name)}`.split
16
+ end
17
+ def output_file_from_zip(name,fname)
18
+ # unzip treats [ ] specially, so requires escaping for '[' and ']' in filenames like '[Content_Types].xml'
19
+ unzip_fname = fname
20
+ .gsub('[', '\\\\\[')
21
+ .gsub(']', '\\\\\]')
22
+ `unzip -p #{rspec_file(name)} #{unzip_fname}`
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,23 +1,51 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: officedoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Pronin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-10 00:00:00.000000000 Z
11
+ date: 2014-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: naught
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
15
43
  requirement: !ruby/object:Gem::Requirement
16
44
  requirements:
17
45
  - - "~>"
18
46
  - !ruby/object:Gem::Version
19
47
  version: '1.6'
20
- type: :development
48
+ type: :runtime
21
49
  prerelease: false
22
50
  version_requirements: !ruby/object:Gem::Requirement
23
51
  requirements:
@@ -25,19 +53,33 @@ dependencies:
25
53
  - !ruby/object:Gem::Version
26
54
  version: '1.6'
27
55
  - !ruby/object:Gem::Dependency
28
- name: rake
56
+ name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - ">="
32
60
  - !ruby/object:Gem::Version
33
- version: '0'
61
+ version: '1.5'
34
62
  type: :development
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
66
  - - ">="
39
67
  - !ruby/object:Gem::Version
40
- version: '0'
68
+ version: '1.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.2'
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: rspec
43
85
  requirement: !ruby/object:Gem::Requirement
@@ -56,16 +98,16 @@ dependencies:
56
98
  name: codeclimate-test-reporter
57
99
  requirement: !ruby/object:Gem::Requirement
58
100
  requirements:
59
- - - ">="
101
+ - - "~>"
60
102
  - !ruby/object:Gem::Version
61
- version: '0'
103
+ version: 0.3.0
62
104
  type: :development
63
105
  prerelease: false
64
106
  version_requirements: !ruby/object:Gem::Requirement
65
107
  requirements:
66
- - - ">="
108
+ - - "~>"
67
109
  - !ruby/object:Gem::Version
68
- version: '0'
110
+ version: 0.3.0
69
111
  description: 'Parsing and constructing documents using XML-based Office formats: ODF
70
112
  and OOXML.'
71
113
  email:
@@ -74,16 +116,29 @@ executables: []
74
116
  extensions: []
75
117
  extra_rdoc_files: []
76
118
  files:
119
+ - ".gitattributes"
77
120
  - ".gitignore"
121
+ - ".rspec"
78
122
  - ".travis.yml"
123
+ - CHANGELOG.md
79
124
  - Gemfile
80
125
  - LICENSE.txt
81
126
  - README.md
82
127
  - Rakefile
83
128
  - lib/officedoc.rb
129
+ - lib/officedoc/null_object.rb
130
+ - lib/officedoc/package.rb
131
+ - lib/officedoc/package/raw.rb
132
+ - lib/officedoc/package/raw/parts.rb
133
+ - lib/officedoc/package/raw/ruby_zip_engine.rb
84
134
  - lib/officedoc/version.rb
85
135
  - officedoc.gemspec
136
+ - spec/classes/package/raw/part_spec.rb
137
+ - spec/classes/package/raw_spec.rb
138
+ - spec/features/package_spec.rb
139
+ - spec/samples/sample1.docx
86
140
  - spec/spec_helper.rb
141
+ - spec/support/file_handlers.rb
87
142
  - tasks/rspec.rake
88
143
  homepage: https://github.com/moonfly/officedoc
89
144
  licenses:
@@ -97,7 +152,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
152
  requirements:
98
153
  - - ">="
99
154
  - !ruby/object:Gem::Version
100
- version: '0'
155
+ version: 2.1.0
101
156
  required_rubygems_version: !ruby/object:Gem::Requirement
102
157
  requirements:
103
158
  - - ">="
@@ -110,4 +165,9 @@ signing_key:
110
165
  specification_version: 4
111
166
  summary: Parsing and constructing ODF and OOXML documents
112
167
  test_files:
168
+ - spec/classes/package/raw/part_spec.rb
169
+ - spec/classes/package/raw_spec.rb
170
+ - spec/features/package_spec.rb
171
+ - spec/samples/sample1.docx
113
172
  - spec/spec_helper.rb
173
+ - spec/support/file_handlers.rb