module sourcemap import io import os import x.json2 const source_map_version = 3 type SourceMapJson = map[string]json2.Any pub struct SourceMap { pub mut: version int @[json: version] file string @[json: file] source_root string @[json: source_root] sources Sets @[json: sources] sources_content map[string]string names Sets mappings Mappings sources_content_inline bool } struct StringWriter { pub mut: bytes []u8 } pub fn new_sourcemap(file string, source_root string, sources_content_inline bool) SourceMap { return SourceMap{ version: source_map_version file: file source_root: source_root mappings: new_mappings() sources_content_inline: sources_content_inline } } // Add a single mapping from original source line and column to the generated source's line and column for this source map being created. pub fn (mut sm SourceMap) add_mapping(source_name string, source_position SourcePositionType, gen_line u32, gen_column u32, name string) { if source_name == '' { panic('add_mapping, source_name should not be ""') } sources_ind := sm.sources.add(source_name) names_ind := if name != '' { NameIndexType(IndexNumber(sm.names.add(name))) } else { NameIndexType(Empty{}) } sm.mappings.add_mapping(gen_line, gen_column, sources_ind, source_position, names_ind) } // Add multiple mappings from the same source pub fn (mut sm SourceMap) add_mapping_list(source_name string, mapping_list []MappingInput) ! { if source_name == '' { panic('add_mapping_list, source_name should not be ""') } sources_ind := sm.sources.add(source_name) for mapping in mapping_list { names_ind := if mapping.name != '' { NameIndexType(IndexNumber(sm.names.add(mapping.name))) } else { NameIndexType(Empty{}) } sm.mappings.add_mapping(mapping.gen_line, mapping.gen_column, sources_ind, mapping.source_position, names_ind) } } // Set the source content for a source file. pub fn (mut sm SourceMap) set_source_content(source_name string, source_content string) { sm.sources_content[source_name] = source_content } fn (mut sm SourceMap) export_mappings(mut writer io.Writer) { sm.mappings.export_mappings(mut writer) or { panic('export failed') } } fn (mut sm SourceMap) export_mappings_string() string { mut output := &StringWriter{} sm.mappings.export_mappings(mut output) or { panic('export failed') } return output.bytes.bytestr() } // create a JSON representing the sourcemap // Sourcemap Specs http://sourcemaps.info/spec.html pub fn (mut sm SourceMap) to_json() SourceMapJson { mut source_map_json := map[string]json2.Any{} mappings_json := sm.export_mappings_string() source_map_json['version'] = sm.version if sm.file != '' { source_map_json['file'] = json2.Any(sm.file) } if sm.source_root != '' { source_map_json['sourceRoot'] = json2.Any(sm.source_root) } mut sources_json := []json2.Any{} mut sources_content_json := []json2.Any{} for source_file, _ in sm.sources.value { sources_json << source_file if source_file in sm.sources_content { sources_content_json << sm.sources_content[source_file] } else { if sm.sources_content_inline { if source_file_content := os.read_file(source_file) { sources_content_json << source_file_content } else { sources_content_json << json2.null } } else { sources_content_json << json2.null } } } source_map_json['sources'] = json2.Any(sources_json) source_map_json['sourcesContent'] = json2.Any(sources_content_json) mut names_json := []json2.Any{} for name, _ in sm.names.value { names_json << name } source_map_json['names'] = json2.Any(names_json) source_map_json['mappings'] = json2.Any(mappings_json) return source_map_json } fn (mut w StringWriter) write(buf []u8) !int { w.bytes << buf return buf.len }