assets-publisher-for-hanami 2.0.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.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +257 -0
- data/Rakefile +2 -0
- data/assets-publisher-for-hanami.gemspec +33 -0
- data/bin/setup +7 -0
- data/lib/cabeza-de-termo/assets-publisher/assets/asset.rb +81 -0
- data/lib/cabeza-de-termo/assets-publisher/assets/types/asset-type.rb +41 -0
- data/lib/cabeza-de-termo/assets-publisher/assets/types/javascript-type.rb +20 -0
- data/lib/cabeza-de-termo/assets-publisher/assets/types/stylesheet-type.rb +20 -0
- data/lib/cabeza-de-termo/assets-publisher/clock-cards/clock-card-machine.rb +43 -0
- data/lib/cabeza-de-termo/assets-publisher/clock-cards/clock-card.rb +47 -0
- data/lib/cabeza-de-termo/assets-publisher/compilation-jobs/compilation-job.rb +80 -0
- data/lib/cabeza-de-termo/assets-publisher/compilation-jobs/compilation-jobs-builder.rb +52 -0
- data/lib/cabeza-de-termo/assets-publisher/compilation-jobs/one-file-per-asset-builder.rb +66 -0
- data/lib/cabeza-de-termo/assets-publisher/compilers/command-line-compiler.rb +26 -0
- data/lib/cabeza-de-termo/assets-publisher/compilers/compiler.rb +50 -0
- data/lib/cabeza-de-termo/assets-publisher/compilers/tilt-compiler.rb +47 -0
- data/lib/cabeza-de-termo/assets-publisher/configuration/configuration.rb +66 -0
- data/lib/cabeza-de-termo/assets-publisher/errors/asset-not-found-error.rb +12 -0
- data/lib/cabeza-de-termo/assets-publisher/errors/compilation-job-failed-error.rb +14 -0
- data/lib/cabeza-de-termo/assets-publisher/errors/compilation-job-not-supported-error.rb +14 -0
- data/lib/cabeza-de-termo/assets-publisher/errors/error.rb +6 -0
- data/lib/cabeza-de-termo/assets-publisher/errors/unknown-asset-location-error.rb +12 -0
- data/lib/cabeza-de-termo/assets-publisher/helpers/helper.rb +27 -0
- data/lib/cabeza-de-termo/assets-publisher/locations/absolute-location.rb +25 -0
- data/lib/cabeza-de-termo/assets-publisher/locations/location.rb +54 -0
- data/lib/cabeza-de-termo/assets-publisher/locations/source-location.rb +13 -0
- data/lib/cabeza-de-termo/assets-publisher/publisher.rb +142 -0
- data/lib/cabeza-de-termo/assets-publisher/source-finders/assets-finder.rb +44 -0
- data/lib/cabeza-de-termo/assets-publisher/source-finders/assets-source.rb +31 -0
- data/lib/cabeza-de-termo/assets-publisher/version.rb +7 -0
- metadata +191 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tilt'
|
3
|
+
require_relative 'compiler'
|
4
|
+
|
5
|
+
module CabezaDeTermo
|
6
|
+
module AssetsPublisher
|
7
|
+
class TiltCompiler < Compiler
|
8
|
+
protected
|
9
|
+
|
10
|
+
def source_asset
|
11
|
+
compilation_job.assets.first
|
12
|
+
end
|
13
|
+
|
14
|
+
def compile_assets()
|
15
|
+
validate_assets_collection
|
16
|
+
|
17
|
+
compile_single_asset
|
18
|
+
end
|
19
|
+
|
20
|
+
def compile_single_asset()
|
21
|
+
just_copy? ? copy! : compile!
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_assets_collection()
|
25
|
+
raise_compilation_job_not_supported_error unless source_assets.size == 1
|
26
|
+
end
|
27
|
+
|
28
|
+
def just_copy?()
|
29
|
+
['.css', '.js'].include?(source_asset.real_path.extname)
|
30
|
+
end
|
31
|
+
|
32
|
+
def copy!()
|
33
|
+
::FileUtils.copy_file(source_asset.real_path, compilation_job.destination_filename)
|
34
|
+
end
|
35
|
+
|
36
|
+
def compile!()
|
37
|
+
::File.open(compilation_job.destination_filename, 'w') do |file|
|
38
|
+
file.write( render_source )
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_source()
|
43
|
+
Tilt.new(source_asset.real_path).render
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CabezaDeTermo
|
2
|
+
module AssetsPublisher
|
3
|
+
# The Publisher configuration.
|
4
|
+
class Configuration
|
5
|
+
# Initialize the instance
|
6
|
+
def initialize
|
7
|
+
@source_folders = []
|
8
|
+
|
9
|
+
destination_folder nil
|
10
|
+
add_timestamps_to_published_assets true
|
11
|
+
stylesheets_compiler {}
|
12
|
+
javascripts_compiler {}
|
13
|
+
use_rendering_scope_assets_collector nil
|
14
|
+
end
|
15
|
+
|
16
|
+
# Answer if the Publisher will add a timestamp to the assets with relative paths
|
17
|
+
def add_timestamps_to_published_assets?
|
18
|
+
@add_timestamps_to_published_assets
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set if the Publisher will add a timestamp to the assets with relative paths
|
22
|
+
def add_timestamps_to_published_assets(boolean)
|
23
|
+
@add_timestamps_to_published_assets = boolean
|
24
|
+
end
|
25
|
+
|
26
|
+
# Answer the asset sources collection
|
27
|
+
def source_folders
|
28
|
+
@source_folders
|
29
|
+
end
|
30
|
+
|
31
|
+
def destination_folder(folder)
|
32
|
+
@destination_folder = folder
|
33
|
+
end
|
34
|
+
|
35
|
+
def destination_path
|
36
|
+
::Pathname.new(@destination_folder)
|
37
|
+
end
|
38
|
+
|
39
|
+
def published_assets_subfolder
|
40
|
+
::Pathname.new('assets')
|
41
|
+
end
|
42
|
+
|
43
|
+
def stylesheets_compiler(&block)
|
44
|
+
return @stylesheets_compiler_block.call if block.nil?
|
45
|
+
@stylesheets_compiler_block = block
|
46
|
+
end
|
47
|
+
|
48
|
+
def javascripts_compiler(&block)
|
49
|
+
return @javascripts_compiler_block.call if block.nil?
|
50
|
+
@javascripts_compiler_block = block
|
51
|
+
end
|
52
|
+
|
53
|
+
def command_line_compiler(&block)
|
54
|
+
CommandLineCompiler.new(&block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def use_rendering_scope_assets_collector(rendering_scope_assets_collector)
|
58
|
+
@rendering_scope_assets_collector = rendering_scope_assets_collector
|
59
|
+
end
|
60
|
+
|
61
|
+
def rendering_scope_assets_collector()
|
62
|
+
@rendering_scope_assets_collector
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'error'
|
2
|
+
|
3
|
+
module CabezaDeTermo
|
4
|
+
module AssetsPublisher
|
5
|
+
class CompilationJobFailedError < Error
|
6
|
+
def initialize(compiler, compilation_job, message)
|
7
|
+
super(message)
|
8
|
+
|
9
|
+
@compiler = compiler
|
10
|
+
@compilation_job = compilation_job
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'error'
|
2
|
+
|
3
|
+
module CabezaDeTermo
|
4
|
+
module AssetsPublisher
|
5
|
+
class CompilationJobNotSupportedError < Error
|
6
|
+
def initialize(compiler, compilation_job, message)
|
7
|
+
super(message)
|
8
|
+
|
9
|
+
@compiler = compiler
|
10
|
+
@compilation_job = compilation_job
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'cabeza-de-termo/assets-publisher/publisher'
|
2
|
+
|
3
|
+
module CabezaDeTermo
|
4
|
+
module AssetsPublisher
|
5
|
+
# The View helper.
|
6
|
+
# To use it, add this to your view:
|
7
|
+
#
|
8
|
+
# module Web
|
9
|
+
# module Views
|
10
|
+
# class YourView
|
11
|
+
# include CabezaDeTermo::AssetsPublisher::Helper
|
12
|
+
# ...
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# This will publish only one method to your views: #assets_publisher. From that method
|
18
|
+
# you can call the Publisher protocol.
|
19
|
+
module Helper
|
20
|
+
# Answer the Publisher to collect and publish stylesheets and javascripts from
|
21
|
+
# your current view.
|
22
|
+
def assets_publisher
|
23
|
+
Publisher.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'location'
|
2
|
+
|
3
|
+
module CabezaDeTermo
|
4
|
+
module AssetsPublisher
|
5
|
+
class AbsoluteLocation < Location
|
6
|
+
# Answer the path of the asset uri.
|
7
|
+
def real_path_of(uri)
|
8
|
+
Pathname.new(destination_path.to_s + uri.to_s).expand_path
|
9
|
+
end
|
10
|
+
|
11
|
+
# Asking
|
12
|
+
|
13
|
+
def is_absolute?()
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
# Answer the path of the folder where compiled assets are published
|
20
|
+
def destination_path
|
21
|
+
configuration.destination_path
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'cabeza-de-termo/assets-publisher/errors/unknown-asset-location-error'
|
2
|
+
|
3
|
+
module CabezaDeTermo
|
4
|
+
module AssetsPublisher
|
5
|
+
class Location
|
6
|
+
# Answer a new location for the uri
|
7
|
+
def self.from(uri)
|
8
|
+
class_for_uri(uri).new(uri)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Answer the class to use for the uri
|
12
|
+
def self.class_for_uri(uri)
|
13
|
+
uri = Pathname.new(uri)
|
14
|
+
|
15
|
+
return class_named("CabezaDeTermo::AssetsPublisher::AbsoluteLocation") if uri.absolute?
|
16
|
+
return class_named("CabezaDeTermo::AssetsPublisher::SourceLocation") if uri.relative?
|
17
|
+
|
18
|
+
raise UnknownAssetLocationError.new(uri)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Answer a class from its fully quilified name
|
22
|
+
def self.class_named(fully_qualified)
|
23
|
+
fully_qualified.split('::').inject(Object) do |mod, class_name|
|
24
|
+
mod.const_get(class_name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Instance methods
|
29
|
+
|
30
|
+
def initialize(uri)
|
31
|
+
@uri = uri
|
32
|
+
end
|
33
|
+
|
34
|
+
# Answer the Publisher configuration.
|
35
|
+
def configuration
|
36
|
+
Publisher.configuration
|
37
|
+
end
|
38
|
+
|
39
|
+
# Asking
|
40
|
+
|
41
|
+
def is_absolute?()
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Answer the path of the asset uri
|
46
|
+
def real_path_of(uri)
|
47
|
+
CdT.subclass_responsibility
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
require_relative 'source-location'
|
54
|
+
require_relative 'absolute-location'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'location'
|
2
|
+
require 'cabeza-de-termo/assets-publisher/source-finders/assets-finder'
|
3
|
+
|
4
|
+
module CabezaDeTermo
|
5
|
+
module AssetsPublisher
|
6
|
+
class SourceLocation < Location
|
7
|
+
# Answer the path of the asset uri
|
8
|
+
def real_path_of(uri)
|
9
|
+
(AssetsFinder.asset_source_path_of uri).expand_path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'cdt/utilities/bind'
|
2
|
+
require 'cdt/utilities/subclass-responsibility'
|
3
|
+
require 'cdt/utilities/if-not-nil'
|
4
|
+
require_relative 'version'
|
5
|
+
require_relative 'configuration/configuration'
|
6
|
+
require_relative 'assets/asset'
|
7
|
+
require_relative 'compilation-jobs/one-file-per-asset-builder'
|
8
|
+
require_relative 'compilers/tilt-compiler'
|
9
|
+
require_relative 'compilers/command-line-compiler'
|
10
|
+
require_relative 'clock-cards/clock-card-machine'
|
11
|
+
|
12
|
+
module CabezaDeTermo
|
13
|
+
module AssetsPublisher
|
14
|
+
# The collector and publisher of the stylesheets and javascripts from the current view.
|
15
|
+
class Publisher
|
16
|
+
|
17
|
+
@configuration_prototype = nil
|
18
|
+
|
19
|
+
@clock_card_machine = ClockCardMachine.new
|
20
|
+
|
21
|
+
@configurations_per_thread = {}
|
22
|
+
|
23
|
+
# Class methods
|
24
|
+
class << self
|
25
|
+
# Answer the Publihser configuration
|
26
|
+
def configuration()
|
27
|
+
configurations_per_thread[::Thread.current]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Pass the config to the block to allow the app to configure the Publisher
|
31
|
+
def configure(&block)
|
32
|
+
CdT.bind_block_evaluation_to configuration_prototype, &block
|
33
|
+
end
|
34
|
+
|
35
|
+
def clock_card_machine()
|
36
|
+
@clock_card_machine
|
37
|
+
end
|
38
|
+
|
39
|
+
def configurations_per_thread()
|
40
|
+
@configurations_per_thread
|
41
|
+
end
|
42
|
+
|
43
|
+
# Answer the Publihser configuration
|
44
|
+
def configuration_prototype()
|
45
|
+
@configuration_prototype ||= default_configuration
|
46
|
+
end
|
47
|
+
|
48
|
+
def reset_configuration_prototype()
|
49
|
+
@configuration_prototype = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def default_configuration()
|
53
|
+
CdT.bind_block_evaluation_to(Configuration.new) do
|
54
|
+
add_timestamps_to_published_assets true
|
55
|
+
|
56
|
+
stylesheets_compiler { TiltCompiler.new }
|
57
|
+
javascripts_compiler { TiltCompiler.new }
|
58
|
+
|
59
|
+
use_rendering_scope_assets_collector CabezaDeTermo::Assets::HanamiRenderingScope
|
60
|
+
|
61
|
+
self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Instance methods
|
67
|
+
|
68
|
+
# Collect and publish the stylesheets from the rendering_scope. Answer the html to include
|
69
|
+
# in your template.
|
70
|
+
def stylesheets_for(rendering_scope)
|
71
|
+
with_configuration_copy do
|
72
|
+
compile_and_build_html_for(StylesheetType.new, rendering_scope)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Collect and publish the javascripts from the rendering_scope. Answer the html to include
|
77
|
+
# in your template.
|
78
|
+
def javascripts_for(rendering_scope)
|
79
|
+
with_configuration_copy do
|
80
|
+
compile_and_build_html_for(JavascriptType.new, rendering_scope)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def compile_and_build_html_for(asset_type, rendering_scope)
|
87
|
+
compile_assets_and_build_html_for asset_type, assets_for(asset_type, rendering_scope)
|
88
|
+
end
|
89
|
+
|
90
|
+
def compile_assets_and_build_html_for(asset_type, assets)
|
91
|
+
jobs = compilation_jobs_for(asset_type, assets)
|
92
|
+
|
93
|
+
compile_jobs(asset_type, jobs)
|
94
|
+
jobs_html(jobs)
|
95
|
+
end
|
96
|
+
|
97
|
+
def compile_jobs(asset_type, compilation_jobs)
|
98
|
+
compilation_jobs.each do |job|
|
99
|
+
compile(job, asset_type)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def compile(compilation_job, asset_type)
|
104
|
+
return unless clock_card_machine.is_outdated? compilation_job
|
105
|
+
|
106
|
+
compilation_job.compile_with(asset_type.compiler)
|
107
|
+
|
108
|
+
clock_card_machine.register_modifications_on compilation_job
|
109
|
+
end
|
110
|
+
|
111
|
+
def jobs_html(compilation_jobs)
|
112
|
+
compilation_jobs.inject('') do |html, compilation_job|
|
113
|
+
html += compilation_job.html
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Create and answer a new comopilation job
|
118
|
+
def compilation_jobs_for(asset_type, assets)
|
119
|
+
OneFilePerAssetBuilder.jobs_for asset_type, assets
|
120
|
+
end
|
121
|
+
|
122
|
+
def assets_for(asset_type, rendering_scope)
|
123
|
+
asset_type.collect_assets_from(rendering_scope)
|
124
|
+
end
|
125
|
+
|
126
|
+
def clock_card_machine()
|
127
|
+
self.class.clock_card_machine
|
128
|
+
end
|
129
|
+
|
130
|
+
def with_configuration_copy(&block)
|
131
|
+
begin
|
132
|
+
self.class.configurations_per_thread[::Thread.current] =
|
133
|
+
self.class.configuration_prototype.dup
|
134
|
+
|
135
|
+
block.call
|
136
|
+
ensure
|
137
|
+
self.class.configurations_per_thread.delete(::Thread.current)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|