Class: SC::ManifestEntry

Inherits:
HashStruct show all
Defined in:
lib/sproutcore/models/manifest_entry.rb

Overview

A manifest entry describes a single item that can be built by the build system. A manifest entry can be assigned any properties you like during the manifest build process.

A ManifestEntry must have at least the following properties to build:

bundle::       owner bundle
build_rule::   name of the task to invoke to build this entry
build_path::   absolute path to place built files
staging_path:: absolute path to place staging files
source_path::  absolute path to source file
source_paths:: arrays of source paths to use for build. alt to single
is_hidden:: if true, entry is not included in build

Constant Summary collapse

BUILD_DIRECTIVES_REGEX =
/(sc_require|require|sc_resource)\(\s*(['"])(.+)['"]\s*\)/

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from HashStruct

#deep_clone, #has_options?, #merge, #merge!, #method_missing, #print_first_caller

Constructor Details

#initialize(manifest, opts = {}) ⇒ ManifestEntry

Returns a new instance of ManifestEntry.



28
29
30
31
# File 'lib/sproutcore/models/manifest_entry.rb', line 28

def initialize(manifest, opts={})
  @manifest = manifest
  super(opts)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class SC::HashStruct

Instance Attribute Details

#manifestObject

The owner manifest



122
123
124
# File 'lib/sproutcore/models/manifest_entry.rb', line 122

def manifest
  @manifest
end

Instance Method Details

#build!Object

Invokes the entry’s build task to build to its build path. If the entry has source entries, they will be staged first.



258
259
260
# File 'lib/sproutcore/models/manifest_entry.rb', line 258

def build!
  build_to self[:build_path]
end

#cacheable_urlObject

Returns a URL with a possible timestamp token appended to the end of the entry if the target’s timestamp_url config is set, or with a randomly assigned domain name prepended if hyper-domaining is turned on. Otherwise returns the URL itself.



167
168
169
170
171
172
173
174
175
# File 'lib/sproutcore/models/manifest_entry.rb', line 167

def cacheable_url
  ret = self[:url]
  ret = [ret, self.timestamp].join('?') if target.config[:timestamp_urls]
  ret = SC.attach_prefix(ret)
  if target.config[:hyper_domaining]
    ret = [self.hyperdomain_prefix(ret), ret].join('')
  end
  return ret
end

#clean!Object

Removes the build and staging files for this entry so the next build will rebuild.

Returns

self


273
274
275
276
277
# File 'lib/sproutcore/models/manifest_entry.rb', line 273

def clean!
  FileUtils.rm(self[:build_path]) if File.exist?(self[:build_path])
  FileUtils.rm(self[:staging_path]) if File.exist?(self[:staging_path])
  return self
end

#composite!Object

Marks the entry as composite. Returns self



111
# File 'lib/sproutcore/models/manifest_entry.rb', line 111

def composite!; self[:composite] = true; self; end

#composite?Boolean

true if the manifest entry represents a composite resource built from one or more source entries. Composite resources will have their source_entries staged before the entry itself is built to staged.

Returns:

  • (Boolean)


108
# File 'lib/sproutcore/models/manifest_entry.rb', line 108

def composite?; self[:composite]; end

#discover_build_directives!Object

Scans the source paths for standard build directives and annotates the entry accordingly. You should only call this method on entries representing CSS or JavaScript resources. It will yield undefined results on all other file types.



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/sproutcore/models/manifest_entry.rb', line 229

def discover_build_directives!

  target.begin_attr_changes

  self[:required] = []
  entry = self.transform? ? self[:source_entry] : self
  entry.scan_source(BUILD_DIRECTIVES_REGEX) do |matches|
    # strip off any file ext
    filename = matches[2].ext ''
    case matches[0]
    when 'sc_require'
      self[:required] << filename
    when 'require'
      self[:required] << filename
    when 'sc_resource'
      self[:resource] = filename
    end
  end

  target.end_attr_changes

end

#dynamic?Boolean

Returns:

  • (Boolean)


124
# File 'lib/sproutcore/models/manifest_entry.rb', line 124

def dynamic?; self[:dynamic]; end

#extensionObject



113
114
115
# File 'lib/sproutcore/models/manifest_entry.rb', line 113

def extension
  @extension ||= File.extname(self[:filename])
end

#extensionless_filenameObject



37
38
39
# File 'lib/sproutcore/models/manifest_entry.rb', line 37

def extensionless_filename
  @extensionless_filename ||= normalized_filename.ext("")
end

#hidden?Boolean

true if the current manifest entry should not be included in the build. The entry may still be used as an input for other entries and it may still be referenced directly

Returns:

  • (Boolean)


97
# File 'lib/sproutcore/models/manifest_entry.rb', line 97

def hidden?; self[:hidden] ||= false; end

#hide!Object

Sets the entry’s hidden? property to true



100
101
102
103
# File 'lib/sproutcore/models/manifest_entry.rb', line 100

def hide!
  self[:hidden] = true
  self
end

#hyperdomain_prefix(url) ⇒ Object

If the hyper_domaining config is an array of strings, this will select one of them based on the hash of the URL, and provide an absolute URL to the entry. The hyperdomain includes the protocol. (http://, etc)



180
181
182
183
184
185
# File 'lib/sproutcore/models/manifest_entry.rb', line 180

def hyperdomain_prefix(url)
  hyperdomains = target.config.hyper_domaining
  index = url.hash % hyperdomains.length

  return "#{hyperdomains[index]}"
end

#inline_contentsObject



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/sproutcore/models/manifest_entry.rb', line 289

def inline_contents
  unless File.exists?(self[:staging_path])

    # stage source entries if needed...
    (self.source_entries || []).each { |e| e.stage! } if composite?

    # get build task and build it
    buildfile = manifest.target.buildfile
    if !buildfile.task_defined?(self.build_task)
      raise "Could not build entry #{self.filename} because build task '#{self.build_task}' is not defined"
    end

    buildfile.invoke 'build:minify:inline_javascript',
      :entry => self,
      :manifest => self.manifest,
      :target => self.manifest.target,
      :config => self.manifest.target.config,
      :project => self.manifest.target.project,
      :src_path => self[:source_path],
      :src_paths => self[:source_paths],
      :dst_path => self[:staging_path]
    end
  File.readlines(self[:staging_path])
end

#inspectObject



61
62
63
# File 'lib/sproutcore/models/manifest_entry.rb', line 61

def inspect
  "SC::ManifestEntry(#{self[:filename]}, build_task=>#{self[:build_task]}, entry_type=>#{self[:entry_type]}, is_hidden=>#{self.hidden?})"
end

#inspect_build_stateObject

Diagnostic function. Indicates what will happen if you called build



280
281
282
# File 'lib/sproutcore/models/manifest_entry.rb', line 280

def inspect_build_state
  inspect_build_to self[:build_path]
end

#inspect_staging_stateObject



284
285
286
# File 'lib/sproutcore/models/manifest_entry.rb', line 284

def inspect_staging_state
  inspect_build_to self[:staging_path]
end

#normalized_filenameObject



33
34
35
# File 'lib/sproutcore/models/manifest_entry.rb', line 33

def normalized_filename
  @normalized_filename = self[:filename].to_s.downcase
end

#prepare!Object

invoked whenever the manifest entry is first created. This will invoke the entry:prepare task if defined.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/sproutcore/models/manifest_entry.rb', line 43

def prepare!
  if !@is_prepared
    @is_prepared = true
    buildfile = manifest.target.buildfile
    if buildfile.task_defined? 'entry:prepare'
      buildfile.invoke 'entry:prepare',
        :entry => self,
        :manifest => self.manifest,
        :target => self.manifest.target,
        :config => self.manifest.target.config,
        :project => self.manifest.target.project
    end
  end
  return self
end

#prepared?Boolean

Returns:

  • (Boolean)


59
# File 'lib/sproutcore/models/manifest_entry.rb', line 59

def prepared?; @is_prepared || false; end

#rootnameObject



117
118
119
# File 'lib/sproutcore/models/manifest_entry.rb', line 117

def rootname
  @rootname ||= self[:filename].sub(/#{extension}$/, '')
end

#scan_source(regexp, &block) ⇒ Object

Scans the source paths (first staging any source entries) for the passed regex. Your block will be executed with each line that matched. Returns the results of each block

Example

entry.extract_content(/require\((.+)\)/) { |line| $1 }


196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/sproutcore/models/manifest_entry.rb', line 196

def scan_source(regexp, &block)
  if entries = self[:source_entries]
    entries.each { |entry| entry.stage! }
  end

  if paths = self[:source_paths]
    paths.each do |path|
      next unless File.exist?(path)

      # fine all directives in the source.  use file cache to make this
      # fast later on.
      begin
        results = target.file_attr('scan_source', path) do
          File.read(path).scan(regexp)
        end
      rescue ArgumentError
        puts path
        raise
      end

      results.each { |result| yield(result) }

    end
  end
end

#stage!Object

Builds an entry into its staging path. This method can be invoked on any entry whose output is required by another entry to be built.



264
265
266
# File 'lib/sproutcore/models/manifest_entry.rb', line 264

def stage!
  build_to self[:staging_path]
end

#targetObject

The owner target



127
# File 'lib/sproutcore/models/manifest_entry.rb', line 127

def target; @target ||= manifest.target; end

#targetsObject

deferred_modules targets, only applicable to module_info entries



130
# File 'lib/sproutcore/models/manifest_entry.rb', line 130

def targets; self[:targets]; end

#timestampObject

Returns a timestamp for when this file was last changed. This will reach back to the source entries, finding the latest original entry.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/sproutcore/models/manifest_entry.rb', line 138

def timestamp
  if dynamic? # MUST check for this first...
    timestamps = targets.map do |t|
      timestamps2 = t.manifest_for(variation).build!.entries.map do |e|
        ts = e.timestamp
        ts.nil? ? 0 : ts
      end
      timestamps2.max
    end
    timestamps.max

  elsif composite?
    self[:source_entries].map { |e| e.timestamp || 0 }.max || Time.now.to_i

  elsif self[:timestamp]
    # for certain entries, such as the Chance entry, we can't use composite entry
    # but still need to have a timestamp to prevent caching. To do this, we allow
    # the entry to specify the timestamp directly; it will calculate it on its own.
    self[:timestamp]

  else
    File.exist?(self[:source_path]) ? File.mtime(self[:source_path]).to_i : 0
  end
end

#to_hash(opts = {}) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sproutcore/models/manifest_entry.rb', line 65

def to_hash(opts={})
  ret = super()
  if ret[:source_entries]
    ret[:source_entries] = ret[:source_entries].map { |e| e.to_hash(opts)}
  end

  if only_keys = opts[:only]
    filtered = {}
    ret.each do |key, value|
      filtered[key] = value if only_keys.include?(key)
    end
    ret = filtered
  end

  if except_keys = opts[:except]
    filtered = {}
    ret.each do |key, value|
      filtered[key] = value unless except_keys.include?(key)
    end
    ret = filtered
  end

  return ret
end

#variationObject

variation for deferred_modules targets, only applicable to module_info entries



134
# File 'lib/sproutcore/models/manifest_entry.rb', line 134

def variation; self[:variation]; end