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.
- data/LICENSE.txt +674 -0
- data/Rakefile +32 -0
- data/bin/regenerate +9 -0
- data/lib/regenerate.rb +13 -0
- data/lib/regenerate/regenerate-utils.rb +31 -0
- data/lib/regenerate/site-regenerator.rb +156 -0
- data/lib/regenerate/web-page.rb +468 -0
- metadata +55 -0
data/Rakefile
ADDED
@@ -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
|
data/bin/regenerate
ADDED
data/lib/regenerate.rb
ADDED
@@ -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
|