roger_themes 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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