texd 0.1.0

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.
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Texd
4
+ # LookupContext is used to find files accross gem, engine and application
5
+ # barriers. This allows other gems and engines to define additional paths
6
+ # to look into, when searching for files.
7
+ #
8
+ # This mechanism is useful, if you want to build a Rails engine to provide
9
+ # default files, and reuse those defaults accross multiple Rails apps.
10
+ #
11
+ # To add a file to the loolup path set, configure Texd:
12
+ #
13
+ # # in lib/yourgem/railtie.rb
14
+ # module Yourgem::Railtie < Rails::Railtie
15
+ # initializer "configure Texd" do
16
+ # Texd.configure do |config|
17
+ # config.lookup_paths << Pathname.new(__dir__).join("../../app/tex")
18
+ # end
19
+ # end
20
+ # end
21
+ #
22
+ # Then files in your `app/tex/` directory will be used, if they are not
23
+ # found in the host application's `app/tex/` directory ("app/tex" is just
24
+ # a convention, you could add arbitrary directories).
25
+ class LookupContext
26
+ # @!parse
27
+ # # Raised when LookupContext#find could not find a file.
28
+ # class MissingFileError < RenderError; end
29
+ MissingFileError = Class.new Error
30
+
31
+ # A list of directories, in priority order, to search files in.
32
+ attr_reader :paths
33
+
34
+ # @param [Array<String, Pathname>] paths is a set of paths to search
35
+ # files in; usually configured with `Texd.config.lookup_paths`
36
+ def initialize(paths)
37
+ @paths = (paths || []).map { |path| expand(path) }
38
+ end
39
+
40
+ # Performs file look up in the configured paths.
41
+ #
42
+ # @param [String, Pathname] name of file to find.
43
+ # @return [Pathname] path to file, when found
44
+ # @raise [MissingFileError] when file could not be found
45
+ def find(name)
46
+ return expand(name) if File.absolute_path?(name)
47
+
48
+ paths.each do |path|
49
+ candidate = path.join(name).expand_path
50
+ return candidate if candidate.exist?
51
+ end
52
+
53
+ msg = format "file %p not found\nsearch paths:\n\t", name
54
+ msg << paths.join("\n\t")
55
+ raise MissingFileError, msg
56
+ end
57
+
58
+ private
59
+
60
+ def expand(path)
61
+ Pathname.new(path).expand_path
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Texd
4
+ class Railtie < ::Rails::Railtie
5
+ initializer "initialize texd" do
6
+ # register MIME type for .tex files
7
+ Mime::Type.register "text/x-tex", :tex, ["text/plain"], ["tex"]
8
+
9
+ # prepend app/tex for Rails host application
10
+ Texd.config.lookup_paths.unshift Rails.root.join("app/tex")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Texd
4
+ VERSION = "0.1.0"
5
+ end
data/lib/texd.rb ADDED
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Texd
4
+ # @!parse
5
+ # # Catch-all error for all exceptions raised by Texd
6
+ # class Error < StandarError; end
7
+ Error = Class.new StandardError
8
+ end
9
+
10
+ require "rails"
11
+
12
+ require_relative "texd/version"
13
+ require_relative "texd/config"
14
+ require_relative "texd/helpers"
15
+ require_relative "texd/client"
16
+ require_relative "texd/attachment"
17
+ require_relative "texd/document"
18
+ require_relative "texd/lookup_context"
19
+ require_relative "texd/railtie"
20
+
21
+ module Texd
22
+ extend self
23
+
24
+ # Reconfigures Texd. Should be called once in your initializer.
25
+ #
26
+ # @example config/initializers/texd.rb
27
+ # Texd.configure do |config|
28
+ # config.endpoint = ENV.fetch("TEXD_ENDPOINT", "http://localhost:2201/")
29
+ # config.error_format = ENV.fetch("TEXD_ERRORS", "full")
30
+ # config.tex_engine = ENV["TEXD_ENGINE"]
31
+ # config.tex_image = ENV["TEXD_IMAGE"]
32
+ # config.helpers = []
33
+ # config.lookup_paths = [Rails.root.join("app/tex")]
34
+ # end
35
+ #
36
+ # @yield [Texd::Configuration] the previous config object
37
+ # @return [Texd::Configuration] the new current config object
38
+ def configure
39
+ yield config if block_given?
40
+ config
41
+ end
42
+
43
+ # @return [Texd::Configuration] the current config object.
44
+ def config
45
+ @config ||= Configuration.new
46
+ end
47
+
48
+ # @return [Texd::Client] the currently configured HTTP client.
49
+ def client
50
+ if (new_hash = config.hash) && new_hash != @config_hash
51
+ @client = Client.new(config)
52
+ @config_hash = new_hash
53
+ end
54
+
55
+ @client
56
+ end
57
+
58
+ # Creates a helper module containing (a) the `texd_attach` helper,
59
+ # and (b) any other helper configured in Text.config.helpers.
60
+ #
61
+ # This needs to be dynamic, because the attachment list is volatile.
62
+ #
63
+ # @api private
64
+ def helpers(attachments)
65
+ Module.new do
66
+ include Texd::Helpers
67
+
68
+ define_method :texd_attach do |path, rename: true, with_extension: true|
69
+ attachments.attach(path, rename).name(with_extension)
70
+ end
71
+
72
+ define_method :texd_reference do |path, rename: true, with_extension: true|
73
+ attachments.reference(path, rename).name(with_extension)
74
+ end
75
+
76
+ alias_method :texd_references, :texd_reference
77
+
78
+ Texd.config.helpers.each do |mod|
79
+ include mod
80
+ end
81
+ end
82
+ end
83
+
84
+ # Render compiles a template, uploads the files to the texd instance,
85
+ # and returns the PDF.
86
+ #
87
+ # The arguments are directly forwarded to ApplicationController#render
88
+ # (which in turn delegates to ActionView::Renderer#render).
89
+ #
90
+ # @example Render app/views/document/document.tex.erb
91
+ # begin
92
+ # pdf = Texd.render(template: "documents/document")
93
+ # rescue Texd::Client::CompilationError => err
94
+ # # Compilation failed and we might have a log in err.logs (only
95
+ # # Texd.config.error_format is "full" or "condensed").
96
+ # # Otherwise some details might be available in err.details.
97
+ # # have a log in err.details
98
+ # rescue Texd::Client::InputError => err
99
+ # # something failed during input file processing. For details see
100
+ # # err.details
101
+ # rescue Texd::Client::QueueError => err
102
+ # # server is busy, try again later.
103
+ # rescue Texd::Error => err
104
+ # # something went wrong before we even got to sent data to the server
105
+ # end
106
+ #
107
+ # @raise [Texd::Client::ResponseError] on input and queue errors. Also on
108
+ # compilation errors, if Texd.config.error_format is set to JSON.
109
+ # @raise [Texd::Error] on other Texd related errors.
110
+ # @return [String] the PDF object
111
+ def render(*args)
112
+ doc = Document.compile(*args)
113
+
114
+ client.render doc.to_upload_ios,
115
+ input: doc.main_input_name
116
+ rescue Client::ReferenceError => err
117
+ # retry once with resolved references
118
+ client.render doc.to_upload_ios(missing_refs: err.references),
119
+ input: doc.main_input_name
120
+ end
121
+ end
data/texd.gemspec ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/texd/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "texd"
7
+ spec.version = Texd::VERSION
8
+ spec.authors = ["Dominik Menke"]
9
+ spec.email = ["dom@digineo.de"]
10
+
11
+ spec.summary = "texd is a Ruby client for the texd web service."
12
+ spec.description = "The texd project provides a network reachable TeX compiler. This gem is a client for that."
13
+ spec.homepage = "https://github.com/digineo/texd-ruby"
14
+ spec.license = "MIT"
15
+
16
+ spec.required_ruby_version = ">= 2.7.0"
17
+
18
+ spec.metadata["rubygems_mfa_required"] = "true"
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = spec.homepage
21
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/v#{Texd::VERSION}/CHANGELOG.md"
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) {
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
28
+ end
29
+ }
30
+
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ spec.add_dependency "multipart-post", "~> 2.0"
36
+ spec.add_dependency "rails", ">= 6.0", "< 8"
37
+
38
+ spec.add_development_dependency "combustion"
39
+ spec.add_development_dependency "rake", "~> 13.0"
40
+ spec.add_development_dependency "rspec", "~> 3.0"
41
+ spec.add_development_dependency "rspec-rails"
42
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: texd
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dominik Menke
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multipart-post
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '8'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '6.0'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '8'
47
+ - !ruby/object:Gem::Dependency
48
+ name: combustion
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '13.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec-rails
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ description: The texd project provides a network reachable TeX compiler. This gem
104
+ is a client for that.
105
+ email:
106
+ - dom@digineo.de
107
+ executables: []
108
+ extensions: []
109
+ extra_rdoc_files: []
110
+ files:
111
+ - ".rspec"
112
+ - ".rubocop.yml"
113
+ - CHANGELOG.md
114
+ - Gemfile
115
+ - Gemfile.lock
116
+ - LICENSE
117
+ - Makefile
118
+ - README.md
119
+ - Rakefile
120
+ - gemfiles/rails-6.0
121
+ - gemfiles/rails-6.0.lock
122
+ - gemfiles/rails-6.1
123
+ - gemfiles/rails-6.1.lock
124
+ - gemfiles/rails-7.0
125
+ - gemfiles/rails-7.0.lock
126
+ - lib/texd.rb
127
+ - lib/texd/attachment.rb
128
+ - lib/texd/client.rb
129
+ - lib/texd/config.rb
130
+ - lib/texd/document.rb
131
+ - lib/texd/helpers.rb
132
+ - lib/texd/lookup_context.rb
133
+ - lib/texd/railtie.rb
134
+ - lib/texd/version.rb
135
+ - texd.gemspec
136
+ homepage: https://github.com/digineo/texd-ruby
137
+ licenses:
138
+ - MIT
139
+ metadata:
140
+ rubygems_mfa_required: 'true'
141
+ homepage_uri: https://github.com/digineo/texd-ruby
142
+ source_code_uri: https://github.com/digineo/texd-ruby
143
+ changelog_uri: https://github.com/digineo/texd-ruby/blob/v0.1.0/CHANGELOG.md
144
+ post_install_message:
145
+ rdoc_options: []
146
+ require_paths:
147
+ - lib
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: 2.7.0
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubygems_version: 3.1.6
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: texd is a Ruby client for the texd web service.
163
+ test_files: []