card-mod-assets 0.13.1 → 0.14.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
  SHA256:
3
- metadata.gz: 1c805a7e96dcb3e25db2b3dcc3b9b232145355f0520b49942c62944e963a04f0
4
- data.tar.gz: 62b94ec94c0bd8d99118a167256311fca965622893640cb2bd798ad91728061a
3
+ metadata.gz: 7f9d0e127bf79045726a27dbaf66a286139002334fe4c033cd19623fc9cb8f03
4
+ data.tar.gz: 6a1f2cfe3e848187feafb484b072b5a0f2a14115159398356e50a6484db3873a
5
5
  SHA512:
6
- metadata.gz: b94d246c3cc490b3d4dedb3066dfa2f821154a6fd16ddd001ce6cbd38464cc57a99abb14a6fbbe10c14773ba0a1311acbb5a01d47bc38679ee453205c049744e
7
- data.tar.gz: e4a7ab1cb2a015292bf7b2130a6a2b15825837d014f06fb5e9c434aaa43810ff056145ab25c3b7a2d5aaa8cdf4524b901078ecd77ade0fda0343648a227f887c
6
+ metadata.gz: 6f5f0481e3982d3683c952143f7f6a6e7250d0aa551792599e553ee319f22bdd03626b1f9153212651eeb3c4f332ec1e332689d43a0a2468f5d6504165ff4abb
7
+ data.tar.gz: 74796a14ede06d0b95ff3039733deb57a2d96a80ddcc1272160a4060c2b8bd490f2913b28a4cde33aa602bd11daea8ad2a3aceaf2ca4ba7024e2e36a82e05775
@@ -0,0 +1,114 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class DeathToMachines < Cardio::Migration::Core
4
+ DEPRECATED_CODE_NAMES = %i[
5
+ machine_input machine_output machine_cache
6
+ style_media
7
+ style_prosemirror script_prosemirror script_prosemirror_config
8
+ script_ace script_ace_config
9
+ script_datepicker_config style_datepicker
10
+ script_tinymce script_tinymce_config
11
+ script_load_select2 style_select2 script_select2
12
+ style_bootstrap_cards
13
+ font_awesome
14
+ material_icons
15
+ style_bootstrap_colorpicker
16
+ style_select2_bootstrap
17
+ style_libraries
18
+ script_html5shiv_printshiv
19
+ smartmenu_css smartmenu_js
20
+ mod_script_assets mod_style_assets
21
+ style_bootstrap_compatible
22
+ style_right_sidebar
23
+ style_bootstrap_mixins
24
+ style_bootstrap_breakpoints
25
+ script_bootstrap
26
+ script_datepicker
27
+ script_jquery_helper style_jquery_ui_smoothness
28
+ style_cards
29
+ ].freeze
30
+
31
+ DEPRECATED_CARD_NAMES = [
32
+ "simple skin",
33
+ "themeless bootstrap skin",
34
+ "style: traditional", "style: common", "style: glyphicons",
35
+ "classic bootstrap skin+*colors", "classic bootstrap skin+*variables",
36
+ "style: classic cards"
37
+ ].freeze
38
+
39
+ def up
40
+ delete_machine_cards :machine_output
41
+ delete_machine_cards :machine_input
42
+ delete_machine_cards :machine_cache
43
+ delete_group_card
44
+ delete_old_style_cards
45
+
46
+ ensure_code_card "*asset input"
47
+ ensure_code_card "*asset output"
48
+
49
+ drop_all_style_items
50
+ update_mod_asset_type_id
51
+
52
+ Card::Cache.reset_all
53
+
54
+ delete_deprecated_code_cards
55
+ end
56
+
57
+ private
58
+
59
+ def update_mod_asset_type_id
60
+ return unless Card::Codename.exists? "mod_script_assets"
61
+
62
+ Card.search type_id: ["in", Card::ModScriptAssetsID, Card::ModStyleAssetsID] do |card|
63
+ card.update! type_id: Card::ListID,
64
+ skip: %i[validate_asset_inputs update_asset_output_file]
65
+ end
66
+ end
67
+
68
+ def drop_all_style_items
69
+ Card[:all, :style].item_cards.each do |card|
70
+ next unless card.left&.type_id == Card::ModID && card.right&.codename == :style
71
+ Card[:all, :style].drop_item! card
72
+ end
73
+ end
74
+
75
+ def delete_deprecated_code_cards
76
+ DEPRECATED_CODE_NAMES.each do |codename|
77
+ delete_code_card codename
78
+ end
79
+
80
+ %w[cerulean cosmo cyborg darkly flatly journal lumen
81
+ paper readable sandstone simplex
82
+ slate spacelab superhero united yeti bootstrap_default].each do |theme|
83
+ delete_code_card "theme_#{theme}"
84
+ end
85
+ end
86
+
87
+ def delete_machine_cards codename
88
+ Card.search right: codename do |card|
89
+ card.update_column :codename, ""
90
+ card.delete!
91
+ end
92
+ end
93
+
94
+ def delete_old_style_cards
95
+ DEPRECATED_CARD_NAMES.each do |doomed|
96
+ delete_card doomed
97
+ end
98
+ end
99
+
100
+ def delete_group_card
101
+ Card.search type_id: ["in",
102
+ Card::LocalScriptManifestGroupID,
103
+ Card::LocalStyleManifestGroupID,
104
+ Card::LocalScriptFolderGroupID,
105
+ Card::LocalStyleFolderGroupID] do |card|
106
+ Card.search left_id: card.id do |field|
107
+ field.update_column :codename, ""
108
+ field.delete
109
+ end
110
+ card.update_column :codename, ""
111
+ card.delete! skip: :asset_input_changed_on_delete
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,95 @@
1
+ class Card
2
+ # Provides methods to refresh script and style assets
3
+ module Assets
4
+ REFRESHED = "ASSETS_REFRESHED".freeze
5
+
6
+ class << self
7
+ # FIXME: if we need this (not sure we do? see below), these types should probably
8
+ # be in a basket so that monkeys can add them.
9
+ def inputter_types
10
+ [
11
+ JavaScriptID,
12
+ CoffeeScriptID,
13
+ CssID,
14
+ ScssID
15
+ ]
16
+ end
17
+
18
+ def refresh_assets force: false
19
+ return unless force || refresh_assets?
20
+
21
+ inputters = standard_inputters
22
+
23
+ # typically nonstandard inputters are standard cards, so their events
24
+ # should manage normal (non-forced) refreshing.
25
+ # (standard_inputters, by contrast, are in code, so this refreshing is
26
+ # needed eg in development mode to detect changes)
27
+ inputters += nonstandard_inputters if force
28
+ inputters.each(&:refresh_asset)
29
+
30
+ generate_asset_output_files if force
31
+ end
32
+
33
+ def make_output_coded
34
+ asset_outputters.each(&:make_asset_output_coded)
35
+ end
36
+
37
+ def active_theme_cards
38
+ style_rule = { left: { type_id: SetID }, right_id: StyleID }
39
+ Card.search(referred_to_by: style_rule).select do |theme|
40
+ theme.respond_to? :theme_name
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def generate_asset_output_files
47
+ asset_outputters.each(&:update_asset_output)
48
+ end
49
+
50
+ def script_outputters
51
+ Card.search(left: { type: :mod }, right_id: ScriptID).flatten
52
+ end
53
+
54
+ def style_outputters
55
+ [Card[:all, :style]]
56
+ end
57
+
58
+ def asset_outputters
59
+ script_outputters + style_outputters
60
+ end
61
+
62
+ # MOD+:style and MOD+:script cards, which represent the assets in MOD/assets/style
63
+ # and MOD/assets/script directories respectively
64
+ def standard_inputters
65
+ @standard_inputter_ids ||=
66
+ Card.search left: { type: :mod }, right_id: [StyleID, ScriptID], return: :id
67
+ @standard_inputter_ids.map(&:card)
68
+ end
69
+
70
+ # standalone cards, NOT in mod assets directories
71
+ def nonstandard_inputters
72
+ Card.search type_id: inputter_types.unshift("in")
73
+ end
74
+
75
+ def refresh_assets?
76
+ case Cardio.config.asset_refresh
77
+ when :eager then true
78
+ when :cautious then cautious_refresh?
79
+ when :never then false
80
+ else
81
+ raise Card::Error,
82
+ "unknown option for asset refresh: #{Cardio.config.asset_refresh}"
83
+ end
84
+ end
85
+
86
+ # only refresh when cache was cleared
87
+ def cautious_refresh?
88
+ return false unless Cache.persistent_cache
89
+ return false if Card.cache.read REFRESHED
90
+
91
+ Card.cache.write REFRESHED, true
92
+ end
93
+ end
94
+ end
95
+ end
data/locales/de.yml ADDED
@@ -0,0 +1,2 @@
1
+ en:
2
+ assets_invalid_input: "%{input_name} ist keine gültige Asset-Eingabekarte"
data/locales/en.yml ADDED
@@ -0,0 +1,2 @@
1
+ en:
2
+ assets_invalid_input: "%{input_name} is not a valid asset input card"
@@ -1,10 +1,4 @@
1
- def group_name
2
- codename.to_s.sub(/^.+__/, "")
3
- end
4
-
5
- def relative_paths
6
- paths
7
- end
1
+ attr_accessor :group_name
8
2
 
9
3
  format :html do
10
4
  view :core do
@@ -8,6 +8,12 @@ def source_paths
8
8
  end
9
9
  end
10
10
 
11
+ def files_must_exist!
12
+ source_paths.select do |path|
13
+ raise Card::Error, "couldn't locate asset file: #{path}" if unknown_file? path
14
+ end
15
+ end
16
+
11
17
  def source_files
12
18
  [db_content]
13
19
  end
@@ -33,18 +39,6 @@ def new?
33
39
  false
34
40
  end
35
41
 
36
- def compress?
37
- @minimize
38
- end
39
-
40
- def minimize
41
- @minimze = true
42
- end
43
-
44
- def local
45
- @local = true
46
- end
47
-
48
42
  format do
49
43
  def link_view opts={}
50
44
  opts[:path] = { card: { type: card.type, content: card.db_content } }
@@ -0,0 +1,55 @@
1
+ include_set Abstract::ReadOnly
2
+ include_set Abstract::Sources
3
+ include_set Abstract::Items
4
+
5
+ def virtual?
6
+ new?
7
+ end
8
+
9
+ def render_items_and_compress format
10
+ item_cards.compact.map do |mcard|
11
+ mcard.format(format)._render_compressed
12
+ end.join "\n"
13
+ end
14
+
15
+ def item_cards _args={}
16
+ relative_paths.map do |path|
17
+ new_asset_file_card path
18
+ end.compact
19
+ end
20
+
21
+ def new_asset_file_card path, name=::File.basename(path)
22
+ return unless (constants = new_asset_constants path)
23
+ asset_card = Card.new(name: name, type_id: constants[:type_id], content: path)
24
+ asset_card.include_set_module constants[:set_module]
25
+ asset_card.minimize if @minimize
26
+ asset_card.local if @local
27
+ asset_card.base_path = base_path
28
+ asset_card.files_must_exist!
29
+ asset_card
30
+ end
31
+
32
+ def source_paths
33
+ paths
34
+ end
35
+
36
+ def local
37
+ @local = true
38
+ end
39
+
40
+ def source_changed? since:
41
+ existing_source_paths.any? { |path| ::File.mtime(path) > since }
42
+ end
43
+
44
+ def input_item_cards
45
+ item_cards # we create virtual cards for manifest groups, hence we have
46
+ # to override the default which rejects virtual cards.
47
+ end
48
+
49
+ def asset_input_needs_refresh?
50
+ !asset_input_updated_at || source_changed?(since: asset_input_updated_at)
51
+ end
52
+
53
+ def last_file_change
54
+ paths.map { |path| ::File.mtime(path) }.max
55
+ end
@@ -0,0 +1,71 @@
1
+ card_accessor :asset_input, type_id: Card::PlainTextID
2
+
3
+ def dependent_asset_inputters
4
+ referers_responding_to :asset_input
5
+ end
6
+
7
+ def outputters
8
+ referers_responding_to :update_asset_output
9
+ end
10
+
11
+ def referers_responding_to method_name
12
+ referers.select { |referer| referer.respond_to? method_name }
13
+ end
14
+
15
+ event :asset_input_changed, :finalize, on: :save do
16
+ update_asset_input
17
+ end
18
+
19
+ event :asset_input_changed_on_delete, :finalize, on: :delete, before: :clear_references do
20
+ update_referers_after_input_changed
21
+ end
22
+
23
+ def update_referers_after_input_changed
24
+ # puts "dependent inputters for #{name}: #{dependent_asset_inputters}"
25
+ # puts "outputters: #{outputters}"
26
+
27
+ dependent_asset_inputters.each(&:update_asset_input)
28
+ outputters.each(&:update_asset_output)
29
+ end
30
+
31
+ def update_asset_input
32
+ return unless Codename.exists? :asset_input
33
+ # otherwise the migration that adds the asset_input card fails
34
+
35
+ Card::Auth.as_bot do
36
+ asset_input_card.update content: render_asset_input_content
37
+ update_referers_after_input_changed
38
+ end
39
+ end
40
+
41
+ def asset_input_content
42
+ return render_asset_input_content if virtual?
43
+ update_asset_input if asset_input.blank?
44
+ asset_input
45
+ end
46
+
47
+ def render_asset_input_content
48
+ format(input_format).render(input_view)
49
+ end
50
+
51
+ def input_view
52
+ :core
53
+ end
54
+
55
+ def asset_input_updated_at
56
+ asset_input_card&.updated_at
57
+ end
58
+
59
+ def refresh_asset
60
+ update_asset_input if asset_input_needs_refresh?
61
+ end
62
+
63
+ def asset_input_needs_refresh?
64
+ false
65
+ end
66
+
67
+ format :html do
68
+ def edit_success
69
+ { reload: true }
70
+ end
71
+ end
@@ -0,0 +1,97 @@
1
+ include_set Abstract::Lock
2
+
3
+ card_accessor :asset_output, type: :file
4
+
5
+ def output_filetype
6
+ output_format
7
+ end
8
+
9
+ event :update_asset_output_file, :finalize, on: :save do
10
+ update_asset_output
11
+ end
12
+
13
+ event :validate_asset_inputs, :validate, on: :save, skip: :allowed do
14
+ return unless (invalid_input = find_invalid_input)
15
+
16
+ errors.add :content, t(:assets_invalid_input, input_name: invalid_input.name)
17
+ end
18
+
19
+ def find_invalid_input
20
+ item_cards.find { |c| !c.respond_to?(:asset_input_content) }
21
+ end
22
+
23
+ def update_asset_output
24
+ # puts "update_asset_output called: #{name}"
25
+ lock do
26
+ store_output input_from_item_cards
27
+ end
28
+ end
29
+
30
+ def update_asset_output_live
31
+ update_asset_output
32
+ card_path asset_output_url
33
+ end
34
+
35
+ def input_from_item_cards joint="\n"
36
+ input_item_cards.map(&:asset_input_content).compact.join(joint)
37
+ end
38
+
39
+ def store_output output
40
+ handle_file(output) do |file|
41
+ Card::Auth.as_bot do
42
+ # FIXME: this is definitely not how we want to do this.
43
+ # problem is that file object is getting stashed in set_specific attributes,
44
+ # and then reassigned later. This causes problems in cases where a single
45
+ # card (eg *all+*style) is updated by multiple inputters, because the old file arg
46
+ # sticks around in the set specific stash and then reemerges after it's been
47
+ # unlinked. we need a more general solution
48
+ # (error reproducible eg when running card:mod:install on wikirate)
49
+ aoc = asset_output_card
50
+ aoc.update file: file
51
+ aoc.set_specific.delete :file
52
+ end
53
+ end
54
+ end
55
+
56
+ def handle_file output
57
+ file = Tempfile.new [id.to_s, ".#{output_filetype}"]
58
+ file.write output
59
+ file.close
60
+ yield file
61
+ file.unlink
62
+ end
63
+
64
+ view :asset_output_url do
65
+ asset_output_url
66
+ end
67
+
68
+ def make_asset_output_coded mod
69
+ mod ||= :assets
70
+ Card::Auth.as_bot do
71
+ ENV["STORE_CODED_FILES"] = "true"
72
+ asset_output_card.update! storage_type: :coded, mod: mod,
73
+ codename: asset_output_codename
74
+ ENV["STORE_CODED_FILES"] = nil
75
+ end
76
+ end
77
+
78
+ def asset_output_codename
79
+ asset_output_card.name.parts.map do |part|
80
+ Card[part].codename&.to_s || Card[part].name.safe_key
81
+ end.join "_"
82
+ end
83
+
84
+ def input_item_cards
85
+ item_cards(known_only: true).compact.reject(&:trash)
86
+ end
87
+
88
+ def asset_output_url
89
+ # ensure_asset_output
90
+ asset_output_card.file&.url # (:default, timestamp: false)
91
+ # to get rid of additional number in url
92
+ end
93
+
94
+ def asset_output_path
95
+ # ensure_asset_output
96
+ asset_output_card.file&.path
97
+ end
@@ -0,0 +1,26 @@
1
+ attr_accessor :assets_path
2
+ attr_accessor :group_name
3
+
4
+ def paths
5
+ return [] unless (path = assets_path)
6
+
7
+ relative_paths.map { |child| ::File.join path, child }
8
+ end
9
+
10
+ def relative_paths
11
+ return [] unless (path = assets_path)
12
+
13
+ Dir.chdir(path) { Dir.glob(search_path).sort }
14
+ end
15
+
16
+ def search_path
17
+ File.join "**", "*.{#{valid_file_extensions.join(',')}}"
18
+ end
19
+
20
+ def base_path
21
+ assets_path
22
+ end
23
+
24
+ def minimize?
25
+ @minimize = true
26
+ end
@@ -1,76 +1,78 @@
1
1
  include_set Abstract::Pointer
2
+ include_set Abstract::ReadOnly
2
3
 
3
- def mod_name
4
- left&.codename.to_s.sub(/^mod_/, "")
4
+ def item_cards _args={}
5
+ local_group_cards
5
6
  end
6
7
 
7
- def mod
8
- @mod ||= Cardio::Mod.dirs.fetch_mod(mod_name)
8
+ def item_names _args={}
9
+ local_group_cards.map(&:name)
9
10
  end
10
11
 
11
- def assets_path
12
- return unless mod&.assets_path.present?
13
-
14
- File.join mod&.assets_path, subpath
12
+ # group cards that don't refer to remote sources
13
+ def local_group_cards
14
+ @local_group_cards ||=
15
+ if manifest_exists?
16
+ local_manifest_group_cards
17
+ else
18
+ [folder_group_card].compact
19
+ end
15
20
  end
16
21
 
17
- def manifest_path
22
+ def folder_group_card
18
23
  return unless assets_path
19
-
20
- File.join(assets_path, "manifest.yml")
24
+ card = new_assets_group_card local_group_name, folder_group_type_id
25
+ card.assets_path = assets_path
26
+ card
21
27
  end
22
28
 
23
- def expected_item_keys
24
- return [] unless assets_dir_exists?
29
+ def local_manifest_group_cards
30
+ manifest.map do |group_name, config|
31
+ next if remote_group?(group_name, config)
32
+ new_local_manifest_group_card group_name
33
+ end.compact
34
+ end
25
35
 
26
- if manifest_exists?
27
- manifest.keys.map { |group_key| "#{name}+#{group_key}".to_name.key }
28
- else
29
- ["#{name}+#{local_group_name}".to_name.key]
30
- end
36
+ def remote_group_urls
37
+ return unless manifest_exists?
38
+ manifest_group_items "remote"
31
39
  end
32
40
 
33
- def local_group_name
34
- "local"
41
+ def content?
42
+ assets_path
35
43
  end
36
44
 
37
- def update_items
38
- # return unless groups_changed?
45
+ def mod_name
46
+ left&.codename.to_s.sub(/^mod_/, "")
47
+ end
39
48
 
40
- delete_unused_items do
41
- self.content = ""
42
- return unless assets_dir_exists?
49
+ def mod
50
+ @mod ||= Cardio::Mod.fetch mod_name
51
+ end
43
52
 
44
- ensure_update_items
45
- save!
46
- end
53
+ def manifest_exists?
54
+ @manifest_exists = !manifest_path.nil? if @manifest_exists.nil?
55
+ @manifest_exists
47
56
  end
48
57
 
49
- def ensure_update_items
50
- if manifest_exists?
51
- ensure_manifest_groups_cards
52
- else
53
- ensure_item local_group_name, local_folder_group_type_id
54
- end
58
+ def assets_path
59
+ @assets_path ||= mod&.subpath "assets", subpath
55
60
  end
56
61
 
57
- def delete_unused_items
58
- @old_items = ::Set.new item_keys
59
- yield
60
- remove_deprecated_items @old_items
62
+ def manifest_path
63
+ @manifest_path ||= mod&.subpath "assets", subpath, "manifest.yml"
61
64
  end
62
65
 
63
- def assets_dir_exists?
64
- path = assets_path
65
- path && Dir.exist?(path)
66
+ def local_group_name
67
+ "local"
66
68
  end
67
69
 
68
- def manifest_exists?
69
- manifest_path && File.exist?(manifest_path)
70
+ def remote_group? name, _config
71
+ name == "remote" # || config["remote"]
70
72
  end
71
73
 
72
74
  def manifest_group_items group_name
73
- manifest.dig(group_name, "items") || []
75
+ manifest&.dig(group_name, "items") || []
74
76
  end
75
77
 
76
78
  def manifest_group_minimize? group_name
@@ -78,93 +80,76 @@ def manifest_group_minimize? group_name
78
80
  end
79
81
 
80
82
  def manifest
81
- @manifest ||= YAML.load_file manifest_path
83
+ @manifest ||= load_manifest
82
84
  end
83
85
 
84
- def with_manifest_groups
85
- manifest.each_pair do |key, config|
86
- yield key, config
87
- end
86
+ def load_manifest
87
+ return unless manifest_exists?
88
+ manifest = YAML.load_file manifest_path
89
+ validate_manifest manifest
90
+ manifest
88
91
  end
89
92
 
90
- def ensure_manifest_groups_cards
91
- with_manifest_groups { |group_name, config| new_manifest_group group_name, config }
93
+ def validate_manifest manifest
94
+ if (remote_index = manifest.keys.find_index("remote")) && remote_index.positive?
95
+ raise_manifest_error "only the first group can be a remote group"
96
+ end
97
+ manifest.each do |name, config|
98
+ validate_manifest_item name, config
99
+ end
92
100
  end
93
101
 
94
- def new_manifest_group group_name, config
95
- type_id =
96
- config["remote"] ? ::Card::RemoteManifestGroupID : local_manifest_group_type_id
97
- ensure_item group_name, type_id
102
+ def group_card_args field, type_id, name
103
+ {
104
+ type_id: type_id,
105
+ codename: "#{mod_name}_group__#{field}",
106
+ name: name
107
+ }
98
108
  end
99
109
 
100
- def ensure_item field, type_id
101
- item_name = "#{name}+#{field}"
102
- ensure_item_content item_name
110
+ def source_changed? since:
111
+ source_updates =
112
+ if manifest_exists?
113
+ [manifest_updated_at, local_manifest_group_cards.map(&:last_file_change)].flatten
114
+ else
115
+ folder_group_card&.paths&.map { |path| File.mtime(path) }
116
+ end
103
117
 
104
- card = Card[item_name]
105
- args = ensure_item_args field, type_id, item_name
106
- return if item_already_coded? card, args
118
+ return unless source_updates.present?
107
119
 
108
- ensure_item_save card, args
109
- card.try :update_machine_output
120
+ source_updates.max > since
110
121
  end
111
122
 
112
- def item_already_coded? card, args
113
- card&.type_id == args[:type_id] && card.codename == args[:codename]
123
+ def manifest_updated_at
124
+ return unless manifest_exists?
125
+ File.mtime(manifest_path)
114
126
  end
115
127
 
116
- def ensure_item_content item_name
117
- @old_items.delete item_name.to_name.key
118
- add_item item_name
128
+ def no_action?
129
+ new? && !assets_path
119
130
  end
120
131
 
121
- def ensure_item_save card, args
122
- if card
123
- card.update args
124
- else
125
- Card.create! args
126
- end
127
- end
132
+ private
128
133
 
129
- def ensure_item_args field, type_id, name
130
- {
131
- type_id: type_id,
132
- codename: "#{mod_name}_group__#{field}",
133
- name: name
134
- }
134
+ def new_local_manifest_group_card group_name
135
+ card = new_assets_group_card group_name, local_manifest_group_type_id
136
+ card.group_name = group_name
137
+ card
135
138
  end
136
139
 
137
- def refresh_output force: false
138
- update_items
139
- item_cards.each do |item_card|
140
- item_card.try :refresh_output, force: force
141
- end
140
+ def new_assets_group_card group_name, type_id
141
+ item_name = "#{name}+group: #{group_name}"
142
+ card = Card.new group_card_args(group_name, type_id, item_name)
143
+ card
142
144
  end
143
145
 
144
- def make_machine_output_coded verbose=false
145
- item_cards.each do |item_card|
146
- puts "coding machine output for #{item_card.name}" if verbose
147
- item_card.try(:make_machine_output_coded, mod_name)
148
- end
149
- end
146
+ def validate_manifest_item name, config
147
+ raise_manifest_error "no items section in group \"#{name}\"" unless config["items"]
148
+ return if config["items"].is_a? Array
150
149
 
151
- def no_action?
152
- new? && !assets_dir_exists?
150
+ raise_manifest_error "items section \"#{name}\" must contain a list"
153
151
  end
154
152
 
155
- private
156
-
157
- # def groups_changed?
158
- # expected_items = expected_item_keys
159
- # actual_items = item_keys
160
- # difference = (expected_items + actual_items) - (expected_items & actual_items)
161
- # difference.present?
162
- # end
163
-
164
- def remove_deprecated_items items
165
- items.each do |deprecated_item|
166
- next unless (item_card = Card.fetch(deprecated_item))
167
- item_card.update codename: nil
168
- item_card.delete
169
- end
153
+ def raise_manifest_error msg
154
+ raise Card::Error, "invalid manifest format in #{manifest_path}: #{msg}"
170
155
  end
@@ -0,0 +1,17 @@
1
+ include_set Abstract::VirtualCache
2
+
3
+ def virtual_content
4
+ left.render_asset_input_content
5
+ end
6
+
7
+ def history?
8
+ false
9
+ end
10
+
11
+ def followable?
12
+ false
13
+ end
14
+
15
+ def chunk_list
16
+ :none
17
+ end
@@ -0,0 +1,36 @@
1
+ def followable?
2
+ false
3
+ end
4
+
5
+ def ok_to_read
6
+ left.ok_to_read
7
+ end
8
+
9
+ def history?
10
+ false
11
+ end
12
+
13
+ event :remove_codename, :prepare_to_validate,
14
+ on: :delete,
15
+ when: proc { |c| c.codename.present? } do
16
+ # load file before deleting codename otherwise it will fail later
17
+ attachment
18
+ self.codename = nil
19
+ end
20
+
21
+ format do
22
+ def outputter
23
+ left
24
+ end
25
+
26
+ view :not_found do
27
+ return super() unless update_asset_output_live?
28
+
29
+ root.error_status = 302
30
+ outputter.update_asset_output_live
31
+ end
32
+
33
+ def update_asset_output_live?
34
+ outputter.is_a?(Abstract::AssetOutputter) && !outputter.locked?
35
+ end
36
+ end
data/set/type/mod.rb CHANGED
@@ -1,52 +1,64 @@
1
+ # TODO: We can't detect file removal for folder group
2
+
3
+ include_set List
4
+
5
+ def modname
6
+ codename.to_s.gsub(/^mod_/, "")
7
+ end
8
+
1
9
  def ensure_mod_script_card
2
- ensure_mod_asset_card :script, Card::ModScriptAssetsID
10
+ ensure_mod_asset_card :script
3
11
  end
4
12
 
5
13
  def ensure_mod_style_card
6
- ensure_mod_asset_card :style, Card::ModStyleAssetsID
14
+ ensure_mod_asset_card :style
7
15
  end
8
16
 
9
17
  private
10
18
 
11
- def ensure_mod_asset_card asset_type, type_id
12
- asset_card = fetch_mod_assets_card asset_type, type_id
19
+ def ensure_mod_asset_card asset_type
20
+ asset_card = fetch_mod_assets_card asset_type
13
21
  return if asset_card.no_action?
14
- asset_card.save! if asset_card.new?
22
+ asset_card.save! if asset_card.new? || asset_card.codename.blank?
15
23
 
16
- asset_card.update_items
17
- if asset_card.item_cards.present?
18
- add_asset asset_type
24
+ if asset_card.content?
25
+ add_mod_asset_card asset_type
26
+ asset_card.refresh_asset
19
27
  else
20
- drop_asset asset_type, asset_card
28
+ puts "Drop: #{asset_card.name}"
29
+ drop_mod_asset_card asset_type, asset_card
21
30
  end
22
31
  end
23
32
 
24
- def add_asset asset_type
25
- all_rule(asset_type).add_item! codename_for(asset_type).to_sym
33
+ def add_mod_asset_card asset_type
34
+ target = asset_type == :style ? Card[:style_mods] : all_rule(asset_type)
35
+ target.add_item! codename_for(asset_type)
26
36
  end
27
37
 
28
- def drop_asset asset_type, asset_card
38
+ def drop_mod_asset_card asset_type, asset_card
29
39
  asset_card.update codename: nil
30
- asset_card.delete update_referers: true
40
+ asset_card.delete
31
41
  all_rule(asset_type).drop_item! asset_card
32
42
  end
33
43
 
34
44
  def codename_for asset_type
35
- "#{codename}_#{asset_type}"
45
+ [codename, asset_type]
36
46
  end
37
47
 
38
48
  def all_rule asset_type
39
49
  Card[:all, asset_type]
40
50
  end
41
51
 
42
- def fetch_mod_assets_card asset_type, type_id
52
+ def fetch_mod_assets_card asset_type
43
53
  codename = codename_for asset_type
44
54
  if Card::Codename.exists? codename
45
55
  Card[codename.to_sym]
46
56
  else
47
- Card.fetch [name, asset_type], new: {
48
- type_id: type_id,
49
- codename: codename
57
+ card = Card.fetch [name, asset_type], new: {
58
+ type_id: Card::ListID, codename: codename
50
59
  }
60
+ card.codename = codename
61
+ card.type_id = Card::ListID
62
+ card
51
63
  end
52
64
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: card-mod-assets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan McCutchen
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-08-06 00:00:00.000000000 Z
13
+ date: 2021-12-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: card
@@ -18,42 +18,104 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 1.103.1
21
+ version: 1.104.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: 1.103.1
28
+ version: 1.104.0
29
29
  - !ruby/object:Gem::Dependency
30
- name: card-mod-machines
30
+ name: execjs
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '2.7'
36
+ - - "!="
37
+ - !ruby/object:Gem::Version
38
+ version: 2.8.0
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '2.7'
46
+ - - "!="
47
+ - !ruby/object:Gem::Version
48
+ version: 2.8.0
49
+ - !ruby/object:Gem::Dependency
50
+ name: card-mod-virtual
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '='
54
+ - !ruby/object:Gem::Version
55
+ version: 0.14.0
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '='
61
+ - !ruby/object:Gem::Version
62
+ version: 0.14.0
63
+ - !ruby/object:Gem::Dependency
64
+ name: card-mod-format
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '='
68
+ - !ruby/object:Gem::Version
69
+ version: 0.14.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '='
75
+ - !ruby/object:Gem::Version
76
+ version: 0.14.0
77
+ - !ruby/object:Gem::Dependency
78
+ name: card-mod-list
79
+ requirement: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '='
82
+ - !ruby/object:Gem::Version
83
+ version: 0.14.0
84
+ type: :runtime
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '='
89
+ - !ruby/object:Gem::Version
90
+ version: 0.14.0
91
+ - !ruby/object:Gem::Dependency
92
+ name: card-mod-carrierwave
31
93
  requirement: !ruby/object:Gem::Requirement
32
94
  requirements:
33
95
  - - '='
34
96
  - !ruby/object:Gem::Version
35
- version: 0.13.1
97
+ version: 0.14.0
36
98
  type: :runtime
37
99
  prerelease: false
38
100
  version_requirements: !ruby/object:Gem::Requirement
39
101
  requirements:
40
102
  - - '='
41
103
  - !ruby/object:Gem::Version
42
- version: 0.13.1
104
+ version: 0.14.0
43
105
  - !ruby/object:Gem::Dependency
44
106
  name: card-mod-content
45
107
  requirement: !ruby/object:Gem::Requirement
46
108
  requirements:
47
109
  - - '='
48
110
  - !ruby/object:Gem::Version
49
- version: 0.13.1
111
+ version: 0.14.0
50
112
  type: :runtime
51
113
  prerelease: false
52
114
  version_requirements: !ruby/object:Gem::Requirement
53
115
  requirements:
54
116
  - - '='
55
117
  - !ruby/object:Gem::Version
56
- version: 0.13.1
118
+ version: 0.14.0
57
119
  description: ''
58
120
  email:
59
121
  - info@decko.org
@@ -62,12 +124,20 @@ extensions: []
62
124
  extra_rdoc_files: []
63
125
  files:
64
126
  - db/migrate_core_cards/20200806112346_add_mod_type.rb
127
+ - db/migrate_core_cards/202108028112352_death_to_machines.rb
128
+ - lib/card/assets.rb
129
+ - locales/de.yml
130
+ - locales/en.yml
65
131
  - set/abstract/01_manifest_group.rb
66
132
  - set/abstract/asset_file.rb
67
- - set/abstract/asset_list.rb
68
- - set/abstract/local_folder_group.rb
133
+ - set/abstract/asset_group.rb
134
+ - set/abstract/asset_inputter.rb
135
+ - set/abstract/asset_outputter.rb
136
+ - set/abstract/folder_group.rb
69
137
  - set/abstract/local_manifest_group.rb
70
138
  - set/abstract/mod_assets.rb
139
+ - set/right/asset_input.rb
140
+ - set/right/asset_output.rb
71
141
  - set/type/mod.rb
72
142
  - set/type/remote_manifest_group.rb
73
143
  homepage: https://decko.org
@@ -95,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
165
  - !ruby/object:Gem::Version
96
166
  version: '0'
97
167
  requirements: []
98
- rubygems_version: 3.1.6
168
+ rubygems_version: 3.2.15
99
169
  signing_key:
100
170
  specification_version: 4
101
171
  summary: decko asset pipeline
@@ -1,66 +0,0 @@
1
- include_set Abstract::ReadOnly
2
- include_set Abstract::Sources
3
- include_set Abstract::Items
4
-
5
- def refresh_output force: false
6
- update_items! if refresh_output? || force
7
- end
8
-
9
- def refresh_output?
10
- !output_updated_at || source_changed?(since: output_updated_at)
11
- end
12
-
13
- event :update_asset_list, :prepare_to_store, on: :save do
14
- self.db_content = relative_paths.join("\n")
15
- end
16
-
17
- def render_items_and_compress format
18
- item_cards.map do |mcard|
19
- js = mcard.format(format)._render_core
20
- js = mcard.compress js if minimize?
21
- "// #{mcard.name}\n#{js}"
22
- end.join "\n"
23
- end
24
-
25
- def update_items!
26
- Card::Auth.as_bot do
27
- save!
28
- end
29
- regenerate_machine_output
30
- end
31
-
32
- def item_name_to_path name
33
- name
34
- end
35
-
36
- def fetch_item_card name, _args={}
37
- new_asset_file_card item_name_to_path(name)
38
- end
39
-
40
- def new_asset_file_card path, name=::File.basename(path)
41
- return unless (constants = new_asset_constants path)
42
- asset_card = Card.new(name: name, type_id: constants[:type_id], content: path)
43
- asset_card.include_set_module constants[:set_module]
44
- asset_card.minimize if @minimize
45
- asset_card.local if @local
46
- asset_card.base_path = base_path
47
- asset_card
48
- end
49
-
50
- def source_paths
51
- paths
52
- end
53
-
54
- def self_machine_input?
55
- true
56
- end
57
-
58
- def local
59
- @local = true
60
- end
61
-
62
- def source_changed? since:
63
- difference = (relative_paths + item_names) - (relative_paths & item_names)
64
- difference.present? ||
65
- existing_source_paths.any? { |path| ::File.mtime(path) > since }
66
- end
@@ -1,23 +0,0 @@
1
- def paths
2
- return [] unless (path = left&.assets_path)
3
-
4
- relative_paths.map { |child| ::File.join path, child }
5
- end
6
-
7
- def relative_paths
8
- return [] unless (path = left&.assets_path)
9
-
10
- Dir.children path
11
- end
12
-
13
- def item_name_to_path name
14
- ::File.join base_path, name
15
- end
16
-
17
- def base_path
18
- left&.assets_path
19
- end
20
-
21
- def minimize?
22
- @minimize = true
23
- end