roger_themes 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 343f6ba8dd1ada47ce7f807e7f75d0d2eb967290
4
- data.tar.gz: 3eebe8c2dffb2d66371860a956a73d449083a0e0
3
+ metadata.gz: 76fc57d42183dffca4cd97846cdf5874e3fd849d
4
+ data.tar.gz: bbd6603a9c732670c0351b13edc29bdc05574735
5
5
  SHA512:
6
- metadata.gz: 6b17333d87abb55c611d3b4c0654b9def8720a7ea1e89aad35c8a182a4b509daa3a4651232a7dfc162f3ec299303b3044e88180708d6ae9d09b93a2d4b3d5978
7
- data.tar.gz: 1971ad918be63c83e1aa7ac6e46cd3c265e986e19d6925243419dfc0cb1f69e28cfb8c3d0e357cab7cbe0c5684e9e22b385d73e59a20af8d2d069d751ec8313b
6
+ metadata.gz: e5d6460310efd4822829c96890f1c9275f064957307e2b1d74dad16e96d3a50517673d2fa5021f19629af914e3decbc1ac8ee02de200cb0f72e4dad490bc8c45
7
+ data.tar.gz: d0dd0779c0796010a7478050b2802e480693e35e730e771cb988ff171f2bbfc0e36d2d5aa4740b097cdfc29804a798cb3ad6c6dd709cbe2ba8355ff3a6a33743
data/README.md CHANGED
@@ -48,6 +48,12 @@ mockup.release do |r|
48
48
 
49
49
  ## Changelog
50
50
 
51
+ ### v0.6.0
52
+ * Attention! `env["SITE_THEME"]` has been renamed to `env["MAIN_THEME"]`. Also it will now return a `RogerThemes::Theme` object instead of a string. The old behaviour can be restored by replacing `env["SITE_THEME"]` with `env["MAIN_THEME"].name`
53
+ * Add compatibility for subthemes
54
+ * Add support for manifest files
55
+ * Add datastructures for themes and assets
56
+
51
57
  ### v0.5.0
52
58
  * Make compatible with Roger 1.7
53
59
 
data/lib/roger_themes.rb CHANGED
@@ -4,9 +4,21 @@ require "fileutils"
4
4
  include FileUtils
5
5
 
6
6
  module RogerThemes
7
- # Your code goes here...
7
+
8
+ # The path within the project.html_path
9
+ def self.themes_path=(path)
10
+ @themes_path = path.to_s.sub(/\A\//, "")
11
+ end
12
+
13
+ def self.themes_path
14
+ @themes_path || "themes"
15
+ end
16
+
8
17
  end
9
18
 
19
+ require "roger_themes/manifest"
20
+ require "roger_themes/asset"
21
+ require "roger_themes/theme"
10
22
  require "roger_themes/middleware"
11
23
  require "roger_themes/processor"
12
24
  require "roger_themes/xc_finalizer"
@@ -0,0 +1,44 @@
1
+ module RogerThemes
2
+ class Asset
3
+ attr_reader :theme, :data
4
+
5
+ def initialize(data, theme)
6
+ @data = {}
7
+ update(data)
8
+ @theme = theme
9
+ end
10
+
11
+ def update(data)
12
+ @data.update(data)
13
+ end
14
+
15
+ def initialize_copy(source)
16
+ @data = @data.dup
17
+ end
18
+
19
+ # Relative path within theme
20
+ def path
21
+ @data["path"].to_s
22
+ end
23
+
24
+ def full_path
25
+ theme.path + path
26
+ end
27
+
28
+ def url
29
+ [theme.url.sub(/\/\Z/, ''), path.sub(/\A\//, '')].join("/")
30
+ end
31
+
32
+ def location
33
+ @data["location"].to_s
34
+ end
35
+
36
+ def type
37
+ @data["type"].to_s
38
+ end
39
+
40
+ def attributes
41
+ @data["attributes"] || {}
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ require 'yaml'
2
+
3
+ module RogerThemes
4
+ class Manifest
5
+
6
+ DEFAULTS = {
7
+ title: nil,
8
+ type: "main",
9
+ mains: nil,
10
+ assets: []
11
+ }
12
+
13
+ def initialize(theme)
14
+ manifest_path = theme.path + "manifest.yml"
15
+
16
+ @data = {}.update(DEFAULTS)
17
+
18
+ if File.exist?(manifest_path)
19
+ data = YAML.load_file(manifest_path)
20
+ data.each do |k,v|
21
+ @data[k.to_sym] = v
22
+ end
23
+ end
24
+
25
+ # Make sure we have a title
26
+ @data[:title] ||= theme.name
27
+ end
28
+
29
+ def [](name)
30
+ @data[name]
31
+ end
32
+
33
+ end
34
+ end
@@ -17,15 +17,23 @@ module RogerThemes
17
17
  end
18
18
 
19
19
  def call(env)
20
+ project = env["roger.project"] || self.project # self.project is for tests.
21
+ themes_path = project.html_path + RogerThemes.themes_path
22
+
20
23
  path = ::Rack::Utils.unescape(env["PATH_INFO"])
21
- r = /\A\/themes\/([^\/]+)\/theme\//
24
+ r = /\A\/#{Regexp.escape(RogerThemes.themes_path)}\/([^\/]+)\/theme\//
25
+
26
+ env["SUB_THEME"] = nil
27
+
22
28
  if theme = path[r,1]
29
+ main_theme, sub_theme = theme.split(".", 2)
23
30
  orig_path = env["PATH_INFO"].dup
24
- env["SITE_THEME"] = theme
31
+ env["MAIN_THEME"] = Theme.new(main_theme, themes_path)
32
+ env["SUB_THEME"] = Theme.new(sub_theme, themes_path) if sub_theme
25
33
  env["PATH_INFO"].sub!(r,"")
26
34
  else
27
35
  # Set default theme
28
- env["SITE_THEME"] = @options[:default_theme]
36
+ env["MAIN_THEME"] = Theme.new(@options[:default_theme], themes_path)
29
37
  end
30
38
 
31
39
  ret = @app.call(env)
@@ -3,85 +3,86 @@ require "roger/release/processors/mockup"
3
3
 
4
4
  module RogerThemes
5
5
  class Processor < Roger::Release::Processors::Base
6
- def initialize(options = {})
6
+ self.name = :roger_themes
7
7
 
8
- defaults = {
8
+ def default_options
9
+ {
9
10
  default_theme: 'default',
10
11
  excludes: [
11
12
  /\A_doc\/.*/,
12
13
  /\Athemes\/.*/,
13
14
  "index.html"
14
15
  ],
15
- shared_folders: ["images", "fonts"]
16
+ shared_folders: ["images", "fonts"],
17
+ template_glob: "**/*{.html,.html.erb}"
16
18
  }
17
-
18
- @options = defaults.update(options)
19
19
  end
20
20
 
21
- def call(release, options = {})
22
- @options = @options.dup.update(options)
21
+ def copy_templates_to_theme(template_files, template_root, theme_path)
22
+ puts "--> #{template_root} - #{theme_path}"
23
+ mkdir_p theme_path
23
24
 
24
- files_glob = "**/*{.html,.html.erb}"
25
+ template_files.each do |file|
26
+ mkdir_p theme_path + File.dirname(file)
27
+ cp template_root + file, theme_path + file
28
+ end
29
+ end
25
30
 
26
- themes = []
31
+ def copy_shared_to_theme(theme, theme_path)
32
+ release.debug self, "Copying shared assets from #{options[:shared_folders]} for #{theme.name}"
33
+ shared_folders = SharedFolders.new(options[:shared_folders])
27
34
 
28
- Dir.chdir(release.build_path) do
29
- Dir.chdir("themes") do
30
- themes = Dir.glob("*").select{|d| File.directory?(d) }.map{|t| [t, Pathname.new("themes/#{t}/theme")] }
35
+ shared_folders.folders.each do |source, target|
36
+ if File.directory? release.build_path + source.to_s
37
+ cp_r release.build_path + "#{source}/.", theme_path + target
31
38
  end
39
+ end
40
+ end
32
41
 
33
- # Get files from html path
34
- files = Dir.glob("../html/#{files_glob}").map{ |f| f.sub("../html/", "") }
35
- files.reject!{|c| @options[:excludes].detect{|e| e.match(c) } }
42
+ def mockup(path, env = {})
43
+ processor = Roger::Release::Processors::Mockup.new
36
44
 
37
- release.debug self, "Copying theme files #{files.inspect}"
45
+ release.log self, "Running mockup processor for: #{path}"
46
+ processor.call(release, {
47
+ match: [
48
+ path + options[:template_glob]
49
+ ],
50
+ env: {
51
+ "roger.project" => release.project
52
+ }.update(env)
53
+ })
54
+ end
38
55
 
39
- themes.each do |theme, theme_dir|
40
- mkdir_p theme_dir
56
+ def perform
57
+ themes_path = release.build_path + RogerThemes.themes_path
58
+ main_themes = Theme.main_themes(themes_path)
41
59
 
42
- files.each do |file|
43
- mkdir_p theme_dir + File.dirname(file)
44
- cp release.project.html_path + file, theme_dir + file
45
- end
60
+ # Get templates from html path
61
+ template_files = Dir.glob(release.project.html_path + options[:template_glob]).map{ |f| f.sub(release.project.html_path.to_s + "/", "") }
62
+ template_files.reject!{|c| options[:excludes].detect{|e| e.match(c) } }
63
+
64
+ release.debug self, "Copying theme files #{template_files.inspect}"
65
+
66
+ main_themes.each do |main_theme|
67
+ copy_templates_to_theme(template_files, release.project.html_path, main_theme.html_path)
68
+ mockup(main_theme.html_path, { "MAIN_THEME" => main_theme })
69
+ copy_shared_to_theme(main_theme, main_theme.path)
70
+
71
+ # Copy sub theme to MAINTHEME.SUBTHEME
72
+ main_theme.sub_themes.each do |sub_theme|
73
+ sub_theme_html_path = sub_theme.html_path_in_main(main_theme.name)
74
+
75
+ # Copy template files to main
76
+ copy_templates_to_theme(template_files, release.project.html_path, sub_theme_html_path)
77
+
78
+ # Run mockup
79
+ mockup(sub_theme_html_path, { "MAIN_THEME" => main_theme, "SUB_THEME" => sub_theme })
46
80
  end
47
81
  end
48
82
 
49
- # Run mockup for each theme
50
- themes.each do |theme, theme_dir|
51
- match_glob = theme_dir + files_glob
52
-
53
- mockup_processor = Roger::Release::Processors::Mockup.new()
54
-
55
- release.log self, "Running mockup processor for theme: #{theme}"
56
- mockup_processor.call(release, {
57
- match: [match_glob],
58
- env: {
59
- "SITE_THEME" => theme,
60
- "MOCKUP_PROJECT" => release.project
61
- }
62
- })
63
-
64
- # cp html/images and html/fonts => html/themes/**/images && html/themes/**/fonts
65
- # if not in target dir
66
- # well conceptual not complete, doing so would required scanning all HTML and
67
- # CSS I suppose.
68
- #
69
- # This means that it could be possible to get images that are not used within the
70
- # zip, since these are not requried in css it wouln't cause any problems thou
71
- # the zip size does increase
72
- #
73
- # Behavior must be simialir to the rewrite in processor
74
- release.debug self, "Starting assets copy for #{@options[:shared_folders]}"
75
- shared_folders = SharedFolders.new(@options[:shared_folders])
76
-
77
- Dir.chdir(release.build_path + "themes/#{theme}") do
78
- release.debug self, "Copying assets for #{theme}"
79
- shared_folders.folders.each do |copy_from, copy_to|
80
- if File.directory? release.build_path + copy_from.to_s
81
- cp_r release.build_path + "#{copy_from}/.", copy_to
82
- end
83
- end
84
- end
83
+ # Make sure we got all shared files in our sub themes
84
+ Theme.sub_themes(themes_path).each do |sub_theme|
85
+ copy_shared_to_theme(sub_theme, sub_theme.path)
85
86
  end
86
87
  end
87
88
  end
@@ -0,0 +1,85 @@
1
+ module RogerThemes
2
+ class Theme
3
+ attr_reader :path, :name, :manifest
4
+
5
+ # Get all themes, will cache the results for a themesepath
6
+ def self.all(themes_path, refresh = false)
7
+ @_themes ||= {}
8
+
9
+ if @_themes[themes_path] && !refresh
10
+ return @_themes[themes_path]
11
+ end
12
+
13
+ @_themes[themes_path] = Dir.glob(themes_path + "*").select{|d| File.directory?(d) }.map do |path|
14
+ name = path.sub(/\A#{Regexp.escape(themes_path.to_s)}/, "")
15
+ Theme.new(name, themes_path)
16
+ end
17
+ end
18
+
19
+ def self.sub_themes_for(main_theme_name, themes_path)
20
+ all(themes_path).select{|theme| theme.type == "sub" && theme.compatible_with_main?(main_theme_name) }
21
+
22
+ end
23
+
24
+ def self.main_themes(themes_path)
25
+ all(themes_path).select{|theme| theme.type == "main" }
26
+ end
27
+
28
+ def self.sub_themes(themes_path)
29
+ all(themes_path).select{|theme| theme.type == "sub" }
30
+ end
31
+
32
+ def initialize(name, themes_path)
33
+ @name = name.to_s.sub(/\A\//, "")
34
+ @themes_path = themes_path
35
+ @path = themes_path + @name
36
+ @manifest = Manifest.new(self)
37
+ end
38
+
39
+ def title
40
+ manifest[:title]
41
+ end
42
+
43
+ def type
44
+ manifest[:type]
45
+ end
46
+
47
+ def mains
48
+ manifest[:mains]
49
+ end
50
+
51
+ def assets
52
+ return [] unless manifest[:assets]
53
+ return @assets if @assets
54
+
55
+ @assets = manifest[:assets].map {|asset_data| Asset.new(asset_data, self) }
56
+ end
57
+
58
+ def sub_themes
59
+ self.class.sub_themes_for(name, @themes_path)
60
+ end
61
+
62
+ def url
63
+ "/" + RogerThemes.themes_path + "/" + name
64
+ end
65
+
66
+ # The path where the templates for this theme will reside
67
+ def html_path
68
+ self.path + "theme"
69
+ end
70
+
71
+ def html_path_in_main(main_theme_name)
72
+ path_in_main(main_theme_name) + "theme"
73
+ end
74
+
75
+ def path_in_main(main_theme_name)
76
+ @themes_path + [main_theme_name, name].join(".")
77
+ end
78
+
79
+ def compatible_with_main?(main_theme_name)
80
+ return false unless self.mains.kind_of?(Array)
81
+
82
+ mains.include?(main_theme_name)
83
+ end
84
+ end
85
+ end
@@ -1,3 +1,3 @@
1
1
  module RogerThemes
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -2,30 +2,34 @@ require "roger/release"
2
2
 
3
3
  module RogerThemes
4
4
  class XcFinalizer < Roger::Release::Finalizers::Base
5
- attr_reader :release
5
+ self.name = :xc_finalizer
6
+
7
+ def default_options
8
+ {
9
+ :prefix => nil,
10
+ :zip => "zip",
11
+ :source_path => release.build_path + "themes/*",
12
+ :target_path => release.build_path + "themes/zips"
13
+ }
14
+ end
6
15
 
7
16
  # XC finalizer finalizes designzips.
8
17
  #
9
- # @param [Release] release
10
18
  # @param [Hash] options Options hash
11
19
  # @option options [String, nil] :prefix (nil) The name to prefix the zipfile with (before version)
12
20
  # @option options [String] :zip ("zip") The ZIP command to use
13
21
  # @option options [String, Pathname] :source_path (release.build_path + "themes/*") The paths to zip
14
22
  # @option options [String, Pathname] :target_path (release.build_path + "themes/zips") The path to the zips
15
- def call(release, options = {})
16
- options = {
17
- :prefix => nil,
18
- :zip => "zip",
19
- :source_path => release.build_path + "themes/*",
20
- :target_path => release.build_path + "themes/zips"
21
- }.update(options)
22
-
23
+ def perform()
23
24
  dirs = Dir.glob(options[:source_path].to_s)
24
25
 
25
26
  zipdir = Pathname.new(options[:target_path])
26
27
  FileUtils.mkdir_p(zipdir) unless zipdir.exist?
27
28
 
28
29
  dirs.each do |dir|
30
+ # Do not generate zip of intermediary zips
31
+ next if dir.include?(".")
32
+
29
33
  name = [options[:prefix], File.basename(dir), release.scm.version].compact.join("-")
30
34
  path = Pathname.new(dir)
31
35
 
@@ -0,0 +1,4 @@
1
+ title: "My sub theme"
2
+ type: "sub"
3
+ mains:
4
+ - "my-cool-theme"
@@ -48,13 +48,27 @@ module RogerThemes
48
48
 
49
49
  # Theme links work by means of rewriting the path info i.e.
50
50
  # to render and setting the env[site_theme] var
51
- def test_theme_links
51
+ def test_main_theme_url
52
52
  @request.get("/themes/my-awesome-theme/theme/elements/index.html")
53
53
  assert_equal @app.call_stack.length, 1
54
- assert_equal @app.call_stack[0]["SITE_THEME"], "my-awesome-theme"
54
+ assert_equal @app.call_stack[0]["MAIN_THEME"].name, "my-awesome-theme"
55
55
  assert_equal @app.call_stack[0]["PATH_INFO"], "elements/index.html"
56
56
  end
57
57
 
58
+ def test_sub_theme_url
59
+ @request.get("/themes/my-awesome-theme.my-sub-theme/theme/elements/index.html")
60
+ assert_equal @app.call_stack.length, 1
61
+ assert_equal @app.call_stack[0]["MAIN_THEME"].name, "my-awesome-theme"
62
+ assert_equal @app.call_stack[0]["SUB_THEME"].name, "my-sub-theme"
63
+ assert_equal @app.call_stack[0]["PATH_INFO"], "elements/index.html"
64
+ end
65
+
66
+ def test_local_main_theme_url
67
+ @request.get("/themes/my-awesome-theme/index.html")
68
+ assert_equal @app.call_stack.length, 1
69
+ assert_equal @app.call_stack[0]["PATH_INFO"], "/themes/my-awesome-theme/index.html"
70
+ end
71
+
58
72
  def test_shared_resources
59
73
  # Shared resource will update the PATH_INFO to render a shared image or font
60
74
  @app.return_value = [404, {}, ["YAM"]]
@@ -20,6 +20,7 @@ module RogerThemes
20
20
 
21
21
  def test_processor_can_be_called
22
22
  assert(@processor.respond_to?(:call))
23
+ assert(@processor.respond_to?(:perform))
23
24
  end
24
25
 
25
26
  def test_processor_copies_shared_folders
@@ -50,7 +51,9 @@ module RogerThemes
50
51
  protected
51
52
 
52
53
  def read_file_in_build(path)
53
- File.read((@release.build_path + path).to_s)
54
+ full_path = (@release.build_path + path).to_s
55
+ assert File.exist?(full_path)
56
+ File.read(full_path)
54
57
  end
55
58
  end
56
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roger_themes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edwin van der Graaf
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-01-16 00:00:00.000000000 Z
12
+ date: 2017-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: roger
@@ -116,13 +116,17 @@ files:
116
116
  - README.md
117
117
  - Rakefile
118
118
  - lib/roger_themes.rb
119
+ - lib/roger_themes/asset.rb
120
+ - lib/roger_themes/manifest.rb
119
121
  - lib/roger_themes/middleware.rb
120
122
  - lib/roger_themes/processor.rb
121
123
  - lib/roger_themes/shared_folders.rb
124
+ - lib/roger_themes/theme.rb
122
125
  - lib/roger_themes/version.rb
123
126
  - lib/roger_themes/xc_finalizer.rb
124
127
  - roger_themes.gemspec
125
128
  - test/fixture/html/themes/my-awesome-theme/index.html
129
+ - test/fixture/html/themes/my-sub-theme/manifest.yml
126
130
  - test/middleware_test.rb
127
131
  - test/processor_test.rb
128
132
  - test/shared_folders_test.rb
@@ -147,12 +151,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
151
  version: '0'
148
152
  requirements: []
149
153
  rubyforge_project:
150
- rubygems_version: 2.5.1
154
+ rubygems_version: 2.6.10
151
155
  signing_key:
152
156
  specification_version: 4
153
157
  summary: Create themes and release them as static site
154
158
  test_files:
155
159
  - test/fixture/html/themes/my-awesome-theme/index.html
160
+ - test/fixture/html/themes/my-sub-theme/manifest.yml
156
161
  - test/middleware_test.rb
157
162
  - test/processor_test.rb
158
163
  - test/shared_folders_test.rb