Class: Twee2::StoryFile
- Inherits:
-
Object
- Object
- Twee2::StoryFile
- Defined in:
- lib/twee2/story_file.rb
Constant Summary collapse
- HAML_OPTIONS =
{ remove_whitespace: true }
- COFFEESCRIPT_OPTIONS =
{ bare: true }
Instance Attribute Summary collapse
-
#child_story_files ⇒ Object
readonly
Returns the value of attribute child_story_files.
-
#passages ⇒ Object
Returns the value of attribute passages.
Instance Method Summary collapse
-
#initialize(filename) ⇒ StoryFile
constructor
Loads the StoryFile with the given name.
-
#run_preprocessors ⇒ Object
Runs HAML, Coffeescript etc.
-
#xmldata ⇒ Object
Returns the rendered XML that represents this story.
Constructor Details
#initialize(filename) ⇒ StoryFile
Loads the StoryFile with the given name
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/twee2/story_file.rb', line 23 def initialize(filename) raise(StoryFileNotFoundException) if !File::exists?(filename) @passages, current_passage = {}, nil @child_story_files = [] # Load file into memory to begin with lines = File::read(filename).split(/\r?\n/) # First pass - go through and perform 'includes' i, in_story_includes_section = 0, false while i < lines.length line = lines[i] if line =~ /^:: *StoryIncludes */ in_story_includes_section = true elsif line =~ /^::/ in_story_includes_section = false elsif in_story_includes_section && (line.strip != '') child_file = line.strip # include a file here because we're in the StoryIncludes section if File::exists?(child_file) lines.push(*File::read(child_file).split(/\r?\n/)) # add it on to the end child_story_files.push(child_file) else puts "WARNING: tried to include file '#{line.strip}' via StoryIncludes but file was not found." end elsif line =~ /^( *)::@include (.*)$/ # include a file here because an @include directive was spotted prefix, filename = $1, $2.strip if File::exists?(filename) lines[i,1] = File::read(filename).split(/\r?\n/).map{|l|"#{prefix}#{l}"} # insert in-place, with prefix of appropriate amount of whitespace i-=1 # process this line again, in case of ::@include nesting else puts "WARNING: tried to ::@include file '#{filename}' but file was not found." end end i+=1 end # Second pass - parse the file lines.each do |line| if line =~ /^:: *([^\[]*?) *(\[(.*?)\])? *(<(.*?)>)? *$/ @passages[current_passage = $1.strip] = { tags: ($3 || '').split(' '), position: $5, content: '', exclude_from_output: false, pid: nil} elsif current_passage @passages[current_passage][:content] << "#{line}\n" end end @passages.each_key{|k| @passages[k][:content].strip!} # Strip excessive trailing whitespace # Run each passage through a preprocessor, if required run_preprocessors # Extract 'special' passages and mark them as not being included in output story_css, pid, @story_js, @story_start_pid, @story_start_name = '', 0, '', nil, 'Start' @passages.each_key do |k| if k == 'StoryTitle' Twee2::build_config.story_name = @passages[k][:content] @passages[k][:exclude_from_output] = true elsif k == 'StoryIncludes' @passages[k][:exclude_from_output] = true # includes should already have been handled above elsif %w{StorySubtitle StoryAuthor StoryMenu StorySettings}.include? k puts "WARNING: ignoring passage '#{k}'" @passages[k][:exclude_from_output] = true elsif @passages[k][:tags].include? 'stylesheet' story_css << "#{@passages[k][:content]}\n" @passages[k][:exclude_from_output] = true elsif @passages[k][:tags].include? 'script' @story_js << "#{@passages[k][:content]}\n" @passages[k][:exclude_from_output] = true elsif @passages[k][:tags].include? 'twee2' eval @passages[k][:content] @passages[k][:exclude_from_output] = true else @passages[k][:pid] = (pid += 1) end end @story_start_pid = (@passages[@story_start_name] || {pid: 1})[:pid] # Generate XML in Twine 2 format @story_data = Builder::XmlMarkup.new # TODO: what is tw-storydata's "options" attribute for? @story_data.tag!('tw-storydata', { name: Twee2::build_config.story_name, startnode: @story_start_pid, creator: 'Twee2', 'creator-version' => Twee2::VERSION, ifid: Twee2::build_config.story_ifid, format: '{{STORY_FORMAT}}', options: '' }) do @story_data.style(story_css, role: 'stylesheet', id: 'twine-user-stylesheet', type: 'text/twine-css') @story_data.script('{{STORY_JS}}', role: 'script', id: 'twine-user-script', type: 'text/twine-javascript') @passages.each do |k,v| unless v[:exclude_from_output] @story_data.tag!('tw-passagedata', { pid: v[:pid], name: k, tags: v[:tags].join(' '), position: v[:position] }, v[:content]) end end end end |
Instance Attribute Details
#child_story_files ⇒ Object (readonly)
Returns the value of attribute child_story_files.
12 13 14 |
# File 'lib/twee2/story_file.rb', line 12 def child_story_files @child_story_files end |
#passages ⇒ Object
Returns the value of attribute passages.
11 12 13 |
# File 'lib/twee2/story_file.rb', line 11 def passages @passages end |
Instance Method Details
#run_preprocessors ⇒ Object
Runs HAML, Coffeescript etc. preprocessors across each applicable passage
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/twee2/story_file.rb', line 124 def run_preprocessors @passages.each_key do |k| # HAML if @passages[k][:tags].include? 'haml' @passages[k][:content] = Haml::Engine.new(@passages[k][:content], HAML_OPTIONS).render @passages[k][:tags].delete 'haml' end # Coffeescript if @passages[k][:tags].include? 'coffee' @passages[k][:content] = CoffeeScript.compile(@passages[k][:content], COFFEESCRIPT_OPTIONS) @passages[k][:tags].delete 'coffee' end # SASS / SCSS if @passages[k][:tags].include? 'sass' @passages[k][:content] = Sass::Engine.new(@passages[k][:content], :syntax => :sass).render end if @passages[k][:tags].include? 'scss' @passages[k][:content] = Sass::Engine.new(@passages[k][:content], :syntax => :scss).render end end end |
#xmldata ⇒ Object
Returns the rendered XML that represents this story
118 119 120 121 |
# File 'lib/twee2/story_file.rb', line 118 def xmldata data = @story_data.target! data.gsub('{{STORY_JS}}', @story_js) end |