Class: Opal::SourceMap::File
- Inherits:
-
Object
- Object
- Opal::SourceMap::File
- Includes:
- Map
- Defined in:
- lib/opal/source_map/file.rb
Instance Attribute Summary collapse
-
#file ⇒ Object
readonly
Returns the value of attribute file.
-
#fragments ⇒ Object
readonly
Returns the value of attribute fragments.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
Instance Method Summary collapse
-
#absolute_mappings ⇒ Object
The “mappings” data is broken down as follows:.
- #generated_code ⇒ Object
-
#initialize(fragments, file, source, generated_code = nil) ⇒ File
constructor
A new instance of File.
-
#map(source_root: '') ⇒ Object
Proposed Format 1: { 2: "version" : 3, 3: "file": "out.js", 4: "sourceRoot": "", 5: "sources": ["foo.js", "bar.js"], 6: "sourcesContent": [null, null], 7: "names": ["src", "maps", "are", "fun"], 8: "mappings": "A,AAAB;;ABCDE;" 9: }.
- #names ⇒ Object
- #relative_mappings ⇒ Object
-
#segment_from_fragment(fragment, generated_column) ⇒ Object
The fields in each segment are:.
Methods included from Map
#as_json, #cache, #marshal_dump, #marshal_load, #to_data_uri_comment, #to_h, #to_json, #to_s
Constructor Details
#initialize(fragments, file, source, generated_code = nil) ⇒ File
Returns a new instance of File.
10 11 12 13 14 15 16 17 |
# File 'lib/opal/source_map/file.rb', line 10 def initialize(fragments, file, source, generated_code = nil) @fragments = fragments @file = file @source = source @names_map = Hash.new { |hash, name| hash[name] = hash.size } @generated_code = generated_code @absolute_mappings = nil end |
Instance Attribute Details
#file ⇒ Object (readonly)
Returns the value of attribute file.
7 8 9 |
# File 'lib/opal/source_map/file.rb', line 7 def file @file end |
#fragments ⇒ Object (readonly)
Returns the value of attribute fragments.
6 7 8 |
# File 'lib/opal/source_map/file.rb', line 6 def fragments @fragments end |
#source ⇒ Object (readonly)
Returns the value of attribute source.
8 9 10 |
# File 'lib/opal/source_map/file.rb', line 8 def source @source end |
Instance Method Details
#absolute_mappings ⇒ Object
The “mappings” data is broken down as follows:
each group representing a line in the generated file is separated by a ”;” each segment is separated by a “,” each segment is made up of 1,4 or 5 variable length fields.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/opal/source_map/file.rb', line 160 def absolute_mappings @absolute_mappings ||= begin mappings = [] fragments_by_line.each do |raw_segments| generated_column = 0 segments = [] raw_segments.each do |(generated_code, fragment)| unless fragment.is_a?(Opal::Fragment) && fragment.skip_source_map? segments << segment_from_fragment(fragment, generated_column) end generated_column += generated_code.size end mappings << segments end mappings end end |
#generated_code ⇒ Object
19 20 21 |
# File 'lib/opal/source_map/file.rb', line 19 def generated_code @generated_code ||= @fragments.map(&:code).join end |
#map(source_root: '') ⇒ Object
Proposed Format 1: { 2: "version" : 3, 3: "file": "out.js", 4: "sourceRoot": "", 5: "sources": ["foo.js", "bar.js"], 6: "sourcesContent": [null, null], 7: "names": ["src", "maps", "are", "fun"], 8: "mappings": "A,AAAB;;ABCDE;" 9: }
Line 1: The entire file is a single JSON object Line 2: File version (always the first entry in the object) and must be a positive integer. Line 3: An optional name of the generated code that this source map is associated with. Line 4: An optional source root, useful for relocating source files on a server or removing repeated values in the “sources” entry. This value is prepended to the individual entries in the “source” field. Line 5: A list of original sources used by the “mappings” entry. Line 6: An optional list of source content, useful when the “source” can’t be hosted. The contents are listed in the same order as the sources in line 5. “null” may be used if some original sources should be retrieved by name. Line 7: A list of symbol names used by the “mappings” entry. Line 8: A string with the encoded mapping data.
48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/opal/source_map/file.rb', line 48 def map(source_root: '') { version: 3, # file: "out.js", # This is optional sourceRoot: source_root, sources: [file], sourcesContent: [source.encoding == Encoding::UTF_8 ? source : source.encode('UTF-8', undef: :replace)], names: names, mappings: Opal::SourceMap::VLQ.encode_mappings(relative_mappings), # x_com_opalrb_original_lines: source.count("\n"), # x_com_opalrb_generated_lines: generated_code.count("\n"), } end |
#names ⇒ Object
62 63 64 65 66 67 |
# File 'lib/opal/source_map/file.rb', line 62 def names @names ||= begin absolute_mappings # let the processing happen @names_map.to_a.sort_by { |_, index| index }.map { |name, _| name } end end |
#relative_mappings ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/opal/source_map/file.rb', line 126 def relative_mappings @relative_mappings ||= begin reference_segment = [0, 0, 0, 0, 0] reference_name_index = 0 absolute_mappings.map do |absolute_mapping| # [generated_column, source_index, original_line, original_column, map_name_index] reference_segment[0] = 0 # reset the generated_column at each new line absolute_mapping.map do |absolute_segment| segment = [] segment[0] = absolute_segment[0] - reference_segment[0] segment[1] = absolute_segment[1] - (reference_segment[1] || 0) segment[2] = absolute_segment[2] - (reference_segment[2] || 0) segment[3] = absolute_segment[3] - (reference_segment[3] || 0) # Since [4] can be nil we need to keep track of it in the reference_segment even if it's nil in absolute_segment if absolute_segment[4] segment[4] = absolute_segment[4].to_int - (reference_segment[4] || reference_name_index).to_int reference_name_index = absolute_segment[4] end reference_segment = absolute_segment segment end end end end |
#segment_from_fragment(fragment, generated_column) ⇒ Object
The fields in each segment are:
The zero-based starting column of the line in the generated code that the segment represents. If this is the first field of the first segment, or the first segment following a new generated line (“;”), then this field holds the whole base 64 VLQ. Otherwise, this field contains a base 64 VLQ that is relative to the previous occurrence of this field. Note that this is different than the fields below because the previous value is reset after every generated line.
If present, an zero-based index into the “sources” list. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented.
If present, the zero-based starting line in the original source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field.
If present, the zero-based starting column of the line in the source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field.
If present, the zero-based index into the “names” list associated with this segment. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/opal/source_map/file.rb', line 100 def segment_from_fragment(fragment, generated_column) source_index = 0 # always 0, we're dealing with a single file original_line = (fragment.line || 0) - 1 # fragments have 1-based lines original_line = 0 if original_line < 0 # line 0 (-1) for fragments in source maps will crash # browsers devtools and the webpack build process original_column = fragment.column || 0 # fragments have 0-based columns if fragment.source_map_name map_name_index = (@names_map[fragment.source_map_name.to_s] ||= @names_map.size) [ generated_column, source_index, original_line, original_column, map_name_index, ] else [ generated_column, source_index, original_line, original_column, ] end end |