regenerate 0.1.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.
@@ -0,0 +1,32 @@
1
+ begin
2
+ require "bundler"
3
+ Bundler.setup
4
+ rescue LoadError
5
+ $stderr.puts "You need to have Bundler installed to be able build this gem."
6
+ end
7
+
8
+ gemspec = eval(File.read("regenerate.gemspec"))
9
+
10
+ desc "Validate the gemspec"
11
+ task :gemspec do
12
+ gemspec.validate
13
+ end
14
+
15
+ desc "Build gem locally"
16
+ task :build => :gemspec do
17
+ system "gem build #{gemspec.name}.gemspec"
18
+ FileUtils.mkdir_p "pkg"
19
+ FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg"
20
+ end
21
+
22
+ desc "Install gem locally"
23
+ task :install => :build do
24
+ system "gem install pkg/#{gemspec.name}-#{gemspec.version}"
25
+ end
26
+
27
+ desc "Clean automatically generated files"
28
+ task :clean do
29
+ FileUtils.rm_rf "pkg"
30
+ end
31
+
32
+ task :default => :build
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'regenerate'
4
+
5
+ if ARGV.length == 1
6
+ Regenerate.regenerate(ARGV[0])
7
+ else
8
+ raise Exception, "regenerate expects exactly one argument: #{ARGV.inspect}"
9
+ end
@@ -0,0 +1,13 @@
1
+ # A framework for static website generation which regenerates files in place.
2
+
3
+ require 'regenerate/web-page.rb'
4
+ require 'regenerate/site-regenerator.rb'
5
+
6
+ STDOUT.sync = true
7
+ STDERR.sync = true
8
+
9
+ #puts "ARGV = #{ARGV.inspect}"
10
+
11
+ if ARGV.length >= 1
12
+ Regenerate.regeneratePath(ARGV[0])
13
+ end
@@ -0,0 +1,31 @@
1
+ module Regenerate
2
+
3
+ module Utils
4
+
5
+ def makeBackupFile(outFile)
6
+ backupFileName = outFile+"~"
7
+ if File.exists? backupFileName
8
+ puts "Deleting existing backup file #{backupFileName} ..."
9
+ File.delete (backupFileName)
10
+ end
11
+ if File.exists? outFile
12
+ puts "Renaming file #{outFile} to #{backupFileName} ..."
13
+ File.rename(outFile, backupFileName)
14
+ end
15
+ end
16
+
17
+ def ensureDirectoryExists(directoryName)
18
+ if File.exist? directoryName
19
+ if not File.directory? directoryName
20
+ raise "Cannot create directory #{directoryName}, already exists as a non-directory file"
21
+ end
22
+ else
23
+ puts "Creating missing directory #{directoryName} ..."
24
+ FileUtils.makedirs(directoryName)
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
@@ -0,0 +1,156 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+ require 'regenerate/regenerate-utils.rb'
4
+
5
+ module Regenerate
6
+
7
+ class PathAndParents
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def each
13
+ currentPath = @path
14
+ topLevel = false
15
+ while !topLevel do
16
+ yield currentPath
17
+ parentPath = File.dirname(currentPath)
18
+ topLevel = parentPath == currentPath
19
+ currentPath = parentPath
20
+ end
21
+ end
22
+ end
23
+
24
+ class SiteRegenerator
25
+
26
+ include Regenerate::Utils
27
+
28
+ def initialize(baseDir, sourceSubDir, outputSubDir)
29
+ @baseDir = File.expand_path(baseDir)
30
+ @sourceSubDir = sourceSubDir
31
+ @outputSubDir = outputSubDir
32
+ @sourceTypeSubDirs = {:source => @sourceSubDir, :output => @outputSubDir}
33
+ @sourceTypeDirs = {:source => File.join(@baseDir, @sourceSubDir),
34
+ :output => File.join(@baseDir, @outputSubDir)}
35
+ @oppositeSourceType = {:source => :output, :output => :source}
36
+ puts "SiteRegenerator, @baseDir = #{@baseDir.inspect}"
37
+ end
38
+
39
+ def checkNotSourceOnly(pathComponents)
40
+ for component in pathComponents do
41
+ if component.start_with?("_")
42
+ raise "Cannot regenerate source-only component #{pathComponents.join("/")}"
43
+ end
44
+ end
45
+ end
46
+
47
+ REGENERATE_EXTENSIONS = [".htm", ".html", ".xml"]
48
+
49
+ def copySrcToOutputFile(srcFile, outFile)
50
+ makeBackupFile(outFile)
51
+ FileUtils.cp(srcFile, outFile, :verbose => true)
52
+ end
53
+
54
+ def regenerateFileFromSource(srcFile, pathComponents)
55
+ puts "regenerateFileFromSource, srcFile = #{srcFile}, pathComponents = #{pathComponents.inspect}"
56
+ subPath = pathComponents.join("/")
57
+ outFile = File.join(@sourceTypeDirs[:output], subPath)
58
+ puts " outFile = #{outFile}"
59
+ ensureDirectoryExists(File.dirname(outFile))
60
+ extension = File.extname(srcFile).downcase
61
+ puts " extension = #{extension}"
62
+ if REGENERATE_EXTENSIONS.include? extension
63
+ WebPage.new(srcFile).regenerateToOutputFile(outFile)
64
+ else
65
+ copySrcToOutputFile(srcFile, outFile)
66
+ end
67
+ end
68
+
69
+ def regenerateSourceFromOutput(outFile, pathComponents)
70
+ puts "regenerateSourceFromOutput, outFile = #{outFile}, pathComponents = #{pathComponents.inspect}"
71
+ subPath = pathComponents.join("/")
72
+ srcFile = File.join(@sourceTypeDirs[:source], subPath)
73
+ puts " srcFile = #{srcFile}"
74
+ ensureDirectoryExists(File.dirname(srcFile))
75
+ extension = File.extname(outFile).downcase
76
+ puts " extension = #{extension}"
77
+ if REGENERATE_EXTENSIONS.include? extension
78
+ raise "Regeneration from output not yet implemented."
79
+ else
80
+ copySrcToOutputFile(outFile, srcFile)
81
+ end
82
+ end
83
+
84
+ def regenerateFile(srcFile, pathComponents, sourceType)
85
+ puts "regenerateFile, srcFile = #{srcFile}, sourceType = #{sourceType.inspect}"
86
+ outFile = File.join(@sourceTypeDirs[@oppositeSourceType[sourceType]], File.join(pathComponents))
87
+ puts " outFile = #{outFile}"
88
+ outFileDir = File.dirname(outFile)
89
+ if !File.exists?(outFileDir)
90
+ if sourceType == :output
91
+ raise "Cannot create missing source directory #{outFileDir} - please do so manually if required"
92
+ end
93
+ ensureDirectoryExists(outFileDir)
94
+ end
95
+ if sourceType == :output
96
+ regenerateSourceFromOutput(srcFile, pathComponents)
97
+ elsif sourceType == :source
98
+ regenerateFileFromSource(srcFile, pathComponents)
99
+ end
100
+ end
101
+
102
+ def regenerateSubPath(pathComponents, sourceType)
103
+ puts "regenerateSubPath, pathComponents = #{pathComponents.inspect}, sourceType = #{sourceType.inspect}"
104
+ srcPath = File.join(@sourceTypeDirs[sourceType], File.join(pathComponents))
105
+ puts " srcPath = #{srcPath}"
106
+ if File.directory? (srcPath)
107
+ for entry in Dir.entries(srcPath) do
108
+ if ![".", ".."].include? entry
109
+ if !entry.start_with?("_")
110
+ regenerateSubPath(pathComponents + [entry], sourceType)
111
+ end
112
+ end
113
+ end
114
+ elsif File.file? (srcPath)
115
+ regenerateFile(srcPath, pathComponents, sourceType)
116
+ end
117
+ end
118
+
119
+ def regeneratePath(path)
120
+ path = File.expand_path(path)
121
+ puts "SiteRegenerator.regeneratePath, path = #{path}"
122
+ relativePath = Pathname.new(path).relative_path_from(Pathname.new(@baseDir))
123
+ puts " relativePath = #{relativePath}"
124
+ relativePathComponents = relativePath.to_s.split("/")
125
+ puts " relativePathComponents = #{relativePathComponents.inspect}"
126
+ subDir = relativePathComponents[0]
127
+ relativeSubDirPathComponents = relativePathComponents[1..-1]
128
+ checkNotSourceOnly(relativeSubDirPathComponents)
129
+ if subDir == @sourceSubDir
130
+ regenerateSubPath(relativeSubDirPathComponents, :source)
131
+ elsif subDir == @outputSubDir
132
+ regenerateSubPath(relativeSubDirPathComponents, :output)
133
+ else
134
+ raise "Path #{path} to regenerate is not contained in #{@sourceSubDir} (source) or #{@outputSubDir} (output) sub-directory of base dir #{@baseDir}"
135
+ end
136
+ end
137
+
138
+ end
139
+
140
+ def self.findRegenerateScript(path, fileName)
141
+ for dir in PathAndParents.new(path) do
142
+ scriptFileName = File.join(dir, fileName)
143
+ puts " looking for #{scriptFileName} ..."
144
+ if File.exists?(scriptFileName)
145
+ return scriptFileName
146
+ end
147
+ end
148
+ raise "File #{fileName} not found in #{path} or any or its parent directories"
149
+ end
150
+
151
+ def self.regeneratePath(path)
152
+ regenerateScriptFileName = findRegenerateScript(path, ".regenerate.rb")
153
+ regenerateScript = File.read(regenerateScriptFileName)
154
+ eval(regenerateScript, binding, regenerateScriptFileName, 1)
155
+ end
156
+ end
@@ -0,0 +1,468 @@
1
+ require 'set'
2
+ require 'erb'
3
+ require 'json'
4
+ require 'regenerate/regenerate-utils.rb'
5
+
6
+ module Regenerate
7
+
8
+ # A component, which includes a sequence of lines which make up the text of that component
9
+ class PageComponent
10
+ attr_reader :text
11
+ attr_accessor :parentPage
12
+
13
+ def initialize
14
+ @lines = []
15
+ @text = nil # if text is nil, component is not yet finished
16
+ @parentPage = nil
17
+ end
18
+
19
+ def processStartComment(parsedCommentLine)
20
+ @startName = parsedCommentLine.name
21
+ initializeFromStartComment(parsedCommentLine)
22
+ if parsedCommentLine.sectionEnd # section end in start comment line, so already finished
23
+ finishText
24
+ end
25
+ end
26
+
27
+ def processEndComment(parsedCommentLine)
28
+ finishText
29
+ if parsedCommentLine.name != @startName
30
+ raise ParseException.new("Name #{parsedCommentLine.name.inspect} in end comment doesn't match name #{@startName.inspect} in start comment.")
31
+ end
32
+ end
33
+
34
+ def initializeFromStartComment(parsedCommentLine)
35
+ # default do nothing
36
+ end
37
+
38
+ def finished
39
+ @text != nil
40
+ end
41
+
42
+ def addLine(line)
43
+ @lines << line
44
+ end
45
+
46
+ def addToParentPage
47
+ # default do nothing
48
+ end
49
+
50
+ def finishText
51
+ @text = @lines.join("\n")
52
+ addToParentPage
53
+ end
54
+ end
55
+
56
+ # A component of static text which is not assigned to any variable, and which does not change
57
+ class StaticHtml < PageComponent
58
+ def output(showSource = true)
59
+ text + "\n"
60
+ end
61
+
62
+ def varName
63
+ nil
64
+ end
65
+ end
66
+
67
+ class RubyCode<PageComponent
68
+
69
+ attr_reader :lineNumber
70
+
71
+ def initialize(lineNumber)
72
+ super()
73
+ @lineNumber = lineNumber
74
+ end
75
+
76
+ def output(showSource = true)
77
+ if showSource
78
+ "<!-- [ruby\n#{text}\nruby] -->\n"
79
+ else
80
+ ""
81
+ end
82
+ end
83
+
84
+ def addToParentPage
85
+ @parentPage.addRubyComponent(self)
86
+ end
87
+ end
88
+
89
+ class SetPageObjectClass<PageComponent
90
+ attr_reader :className
91
+ def initialize(className)
92
+ super()
93
+ @className = className
94
+ end
95
+
96
+ def output(showSource = true)
97
+ if showSource
98
+ "<!-- [class #{@className}] -->\n"
99
+ else
100
+ ""
101
+ end
102
+ end
103
+
104
+ def addToParentPage
105
+ @parentPage.setPageObject(@className)
106
+ end
107
+ end
108
+
109
+ # Base class for the text variable types
110
+ class TextVariable<PageComponent
111
+ attr_reader :varName
112
+
113
+ def initializeFromStartComment(parsedCommentLine)
114
+ @varName = parsedCommentLine.instanceVarName
115
+ end
116
+
117
+ def addToParentPage
118
+ #puts "TextVariable.addToParentPage #{@varName} = #{@text.inspect}"
119
+ @parentPage.setPageObjectInstanceVar(@varName, @text)
120
+ end
121
+
122
+ def textVariableValue
123
+ @parentPage.getPageObjectInstanceVar(@varName)
124
+ end
125
+ end
126
+
127
+ # HtmlVariable Can be both source and result
128
+ class HtmlVariable < TextVariable
129
+
130
+ def processEndComment(parsedCommentLine)
131
+ super(parsedCommentLine)
132
+ if !parsedCommentLine.hasCommentStart
133
+ raise ParseException.new("End comment for HTML variable does not have a comment start")
134
+ end
135
+ end
136
+
137
+ def output(showSource = true)
138
+ if showSource
139
+ textValue = textVariableValue
140
+ if textValue == nil || textValue == ""
141
+ "<!-- [#{@varName}] -->\n"
142
+ else
143
+ "<!-- [#{@varName} -->\n#{textValue}\n<!-- #{@varName}] -->\n"
144
+ end
145
+ else
146
+ text
147
+ end
148
+ end
149
+ end
150
+
151
+ # CommentVariable Is an input only
152
+ class CommentVariable < TextVariable
153
+ def processEndComment(parsedCommentLine)
154
+ super(parsedCommentLine)
155
+ if parsedCommentLine.hasCommentStart
156
+ raise ParseException.new("End comment for comment variable has an unexpected comment start")
157
+ end
158
+ end
159
+
160
+ def output(showSource = true)
161
+ if showSource
162
+ "<!-- [#{@varName}\n#{textVariableValue}\n#{@varName}] -->\n"
163
+ else
164
+ ""
165
+ end
166
+ end
167
+ end
168
+
169
+ COMMENT_LINE_REGEX = /^\s*(<!--\s*|)(\[|)((@|)[_a-zA-Z][_a-zA-Z0-9]*)(|\s+([_a-zA-Z0-9]*))(\]|)(\s*-->|)?\s*$/
170
+
171
+ class ParseException<Exception
172
+ end
173
+
174
+ class ParsedRejennerCommentLine
175
+
176
+ attr_reader :isInstanceVar, :hasCommentStart, :hasCommentEnd, :sectionStart, :sectionEnd
177
+ attr_reader :isEmptySection, :line, :name, :value
178
+
179
+ def initialize(line, match)
180
+ @hasCommentStart = match[1] != ""
181
+ @sectionStart = match[2] != ""
182
+ @isInstanceVar = match[4] != ""
183
+ @name = match[3]
184
+ @value = match[6]
185
+ @sectionEnd = match[7] != ""
186
+ @hasCommentEnd = match[8] != ""
187
+ @line = line
188
+ @isEmptySection = @sectionStart && @sectionEnd
189
+ end
190
+
191
+ def to_s
192
+ "#{@hasCommentStart ? "<!-- ":""}#{@sectionStart ? "[ ":""}#{@isInstanceVar ? "@ ":""}#{@name.inspect}#{@value ? " "+@value:""}#{@sectionEnd ? " ]":""}#{@hasCommentEnd ? " -->":""}"
193
+ end
194
+
195
+ def isRejennerCommentLine
196
+ return (@hasCommentStart || @hasCommentEnd) && (@sectionStart || @sectionEnd)
197
+ end
198
+
199
+ def isRuby
200
+ !@isInstanceVar && @name == "ruby"
201
+ end
202
+
203
+ def instanceVarName
204
+ return @name
205
+ end
206
+
207
+ def raiseParseException(message)
208
+ raise ParseException.new("Error parsing line #{@line.inspect}: #{message}")
209
+ end
210
+
211
+ # only call this method if isRejennerCommentLine returns true
212
+ def checkIsValid
213
+ if !@isInstanceVar and !["ruby", "class"].include?(@name)
214
+ raiseParseException("Unknown section name #{@name.inspect}")
215
+ end
216
+ if @isEmptySection and (!@hasCommentStart && !@hasCommentEnd)
217
+ raiseParseException("Empty section, but is not a closed comment")
218
+ end
219
+ if !@sectionStart && !@hasCommentEnd
220
+ raiseParseException("End of section in comment start")
221
+ end
222
+ if !@sectionEnd && !@hasCommentStart
223
+ raiseParseException("Start of section in comment end")
224
+ end
225
+ if (@sectionStart && @sectionEnd) && isRuby
226
+ raiseParseException("Empty ruby section")
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+ class WebPage
233
+
234
+ include Regenerate::Utils
235
+
236
+ attr_reader :fileName
237
+
238
+ def initialize(fileName)
239
+ @fileName = fileName
240
+ @components = []
241
+ @currentComponent = nil
242
+ @componentInstanceVariables = {}
243
+ initializePageObject(PageObject.new) # default, can be overridden by SetPageObjectClass
244
+ @rubyComponents = []
245
+ readFileLines
246
+ end
247
+
248
+ def initializePageObject(pageObject)
249
+ @pageObject = pageObject
250
+ setPageObjectInstanceVar("@fileName", @fileName)
251
+ setPageObjectInstanceVar("@baseDir", File.dirname(@fileName))
252
+ setPageObjectInstanceVar("@baseFileName", File.basename(@fileName))
253
+ @initialInstanceVariables = Set.new(@pageObject.instance_variables)
254
+ end
255
+
256
+ def getPageObjectInstanceVar(varName)
257
+ @pageObject.instance_variable_get(varName)
258
+ end
259
+
260
+ def setPageObjectInstanceVar(varName, value)
261
+ puts " setPageObjectInstanceVar, #{varName} = #{value.inspect}"
262
+ @pageObject.instance_variable_set(varName, value)
263
+ end
264
+
265
+ def addRubyComponent(rubyComponent)
266
+ @rubyComponents << rubyComponent
267
+ end
268
+
269
+ def setInstanceVarValue(varName, value)
270
+ if @initialInstanceVariables.member? varName
271
+ raise Exception, "Instance variable #{varName} is a pre-existing instance variable"
272
+ end
273
+ if @componentInstanceVariables.member? varName
274
+ raise Exception, "Instance variable #{varName} is a already defined for a component"
275
+ end
276
+ instance_variable_set(varName, value)
277
+ componentInstanceVariables << varName
278
+ end
279
+
280
+ def startNewComponent(component, startComment = nil)
281
+
282
+ component.parentPage = self
283
+ @currentComponent = component
284
+ #puts "startNewComponent, @currentComponent = #{@currentComponent.inspect}"
285
+ @components << component
286
+ if startComment
287
+ component.processStartComment(startComment)
288
+ end
289
+ end
290
+
291
+ def processTextLine(line, lineNumber)
292
+ #puts "text: #{line}"
293
+ if @currentComponent == nil
294
+ startNewComponent(StaticHtml.new)
295
+ end
296
+ @currentComponent.addLine(line)
297
+ end
298
+
299
+ def classFromString(str)
300
+ str.split('::').inject(Object) do |mod, class_name|
301
+ mod.const_get(class_name)
302
+ end
303
+ end
304
+
305
+ def setPageObject(className)
306
+ pageObjectClass = classFromString(className)
307
+ initializePageObject(pageObjectClass.new)
308
+ end
309
+
310
+ def processCommandLine(parsedCommandLine, lineNumber)
311
+ #puts "command: #{parsedCommandLine}"
312
+ if @currentComponent && (@currentComponent.is_a? StaticHtml)
313
+ @currentComponent.finishText
314
+ @currentComponent = nil
315
+ end
316
+ if @currentComponent
317
+ if parsedCommandLine.sectionStart
318
+ raise ParseException.new("Unexpected section start #{parsedCommandLine} inside component")
319
+ end
320
+ @currentComponent.processEndComment(parsedCommandLine)
321
+ @currentComponent = nil
322
+ else
323
+ if !parsedCommandLine.sectionStart
324
+ raise ParseException.new("Unexpected section end #{parsedCommandLine}, outside of component")
325
+ end
326
+ if parsedCommandLine.isInstanceVar
327
+ if parsedCommandLine.hasCommentEnd
328
+ startNewComponent(HtmlVariable.new, parsedCommandLine)
329
+ else
330
+ startNewComponent(CommentVariable.new, parsedCommandLine)
331
+ end
332
+ else
333
+ if parsedCommandLine.name == "ruby"
334
+ startNewComponent(RubyCode.new(lineNumber+1), parsedCommandLine)
335
+ elsif parsedCommandLine.name == "class"
336
+ startNewComponent(SetPageObjectClass.new(parsedCommandLine.value), parsedCommandLine)
337
+ else
338
+ raise ParseException.new("Unknown section type #{parsedCommandLine.name.inspect}")
339
+ end
340
+ end
341
+ if @currentComponent.finished
342
+ @currentComponent = nil
343
+ end
344
+ end
345
+
346
+ end
347
+
348
+ def finish
349
+ if @currentComponent
350
+ if @currentComponent.is_a? StaticHtml
351
+ @currentComponent.finishText
352
+ @currentComponent = nil
353
+ else
354
+ raise ParseException.new("Unfinished last component at end of file")
355
+ end
356
+ end
357
+ end
358
+
359
+ def writeRegeneratedFile(outFile)
360
+ makeBackupFile(outFile)
361
+ puts "Outputting regenerated page to #{outFile} ..."
362
+ File.open(outFile, "w") do |f|
363
+ for component in @components do
364
+ f.write(component.output)
365
+ end
366
+ end
367
+ puts "Finished writing #{outFile}"
368
+ end
369
+
370
+ def readFileLines
371
+ puts "Opening #{@fileName} ..."
372
+ lineNumber = 0
373
+ File.open(@fileName).each_line do |line|
374
+ line.chomp!
375
+ lineNumber += 1
376
+ #puts "line #{lineNumber}: #{line}"
377
+ commentLineMatch = COMMENT_LINE_REGEX.match(line)
378
+ if commentLineMatch
379
+ parsedCommandLine = ParsedRejennerCommentLine.new(line, commentLineMatch)
380
+ #puts "parsedCommandLine = #{parsedCommandLine}"
381
+ if parsedCommandLine.isRejennerCommentLine
382
+ parsedCommandLine.checkIsValid
383
+ processCommandLine(parsedCommandLine, lineNumber)
384
+ else
385
+ processTextLine(line, lineNumber)
386
+ end
387
+ else
388
+ processTextLine(line, lineNumber)
389
+ end
390
+ end
391
+ finish
392
+ #puts "Finished reading #{@fileName}."
393
+ end
394
+
395
+ def regenerate
396
+ executeRubyComponents
397
+ writeRegeneratedFile(@fileName)
398
+ #display
399
+ end
400
+
401
+ def regenerateToOutputFile(outFile)
402
+ executeRubyComponents
403
+ writeRegeneratedFile(outFile)
404
+ end
405
+
406
+ def executeRubyComponents
407
+ fileDir = File.dirname(@fileName)
408
+ puts "Executing ruby components in directory #{fileDir} ..."
409
+ Dir.chdir(fileDir) do
410
+ for rubyComponent in @rubyComponents
411
+ rubyCode = rubyComponent.text
412
+ puts ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
413
+ puts "Executing ruby (line #{rubyComponent.lineNumber}) #{rubyCode.inspect} ..."
414
+ @pageObject.instance_eval(rubyCode, @fileName, rubyComponent.lineNumber)
415
+ #puts "Finished executing ruby at line #{rubyComponent.lineNumber}"
416
+ end
417
+ end
418
+ #puts "Finished executing ruby components."
419
+ end
420
+
421
+ def display
422
+ puts "=========================================================================="
423
+ puts "Output of #{@fileName}"
424
+ for component in @components do
425
+ puts "--------------------------------------"
426
+ puts(component.output)
427
+ end
428
+ end
429
+ end
430
+
431
+ class PageObject
432
+ include Regenerate::Utils
433
+
434
+ def erb(templateFileName)
435
+ @binding = binding
436
+ File.open(relative_path(templateFileName), "r") do |input|
437
+ templateText = input.read
438
+ template = ERB.new(templateText, nil, nil)
439
+ template.filename = templateFileName
440
+ result = template.result(@binding)
441
+ end
442
+ end
443
+
444
+ def relative_path(path)
445
+ File.expand_path(File.join(@baseDir, path.to_str))
446
+ end
447
+
448
+ def require_relative(path)
449
+ require relative_path(path)
450
+ end
451
+
452
+ def saveProperties
453
+ properties = {}
454
+ for property in propertiesToSave
455
+ value = instance_variable_get("@" + property.to_s)
456
+ properties[property] = value
457
+ end
458
+ propertiesFileName = relative_path(self.class.propertiesFileName(@baseFileName))
459
+ puts "Saving properties #{properties.inspect} to #{propertiesFileName}"
460
+ ensureDirectoryExists(File.dirname(propertiesFileName))
461
+ File.open(propertiesFileName,"w") do |f|
462
+ f.write(JSON.pretty_generate(properties))
463
+ end
464
+ end
465
+
466
+ end
467
+
468
+ end