/// <summary>
        /// Removes column information from a source map
        /// This can significantly reduce the size of source maps
        /// If there is a tie between mapping entries, the first generated line takes priority
        /// <returns>A new source map</returns>
        /// </summary>
        public static SourceMap Flatten(SourceMap sourceMap)
        {
            SourceMap newMap = new SourceMap
            {
                File           = sourceMap.File,
                Version        = sourceMap.Version,
                Mappings       = sourceMap.Mappings,
                Sources        = sourceMap.Sources == null ? null : new List <string>(sourceMap.Sources),
                Names          = sourceMap.Names == null ? null : new List <string>(sourceMap.Names),
                ParsedMappings = new List <MappingEntry>()
            };

            HashSet <int> visitedLines = new HashSet <int>();

            foreach (MappingEntry mapping in sourceMap.ParsedMappings)
            {
                int generatedLine = mapping.GeneratedSourcePosition.ZeroBasedLineNumber;

                if (!visitedLines.Contains(generatedLine))
                {
                    visitedLines.Add(generatedLine);
                    var newMapping = mapping.Clone();
                    newMapping.GeneratedSourcePosition.ZeroBasedColumnNumber = 0;
                    newMapping.OriginalSourcePosition.ZeroBasedColumnNumber  = 0;
                    newMap.ParsedMappings.Add(newMapping);
                }
            }

            return(newMap);
        }
示例#2
0
        /// <summary>
        /// Removes column information from a source map
        /// This can significantly reduce the size of source maps
        /// If there is a tie between mapping entries, the first generated line takes priority
        /// <returns>A new source map</returns>
        /// </summary>
        public static SourceMap Flatten(SourceMap sourceMap)
        {
            HashSet <int>       visitedLines   = new HashSet <int>();
            List <MappingEntry> parsedMappings = new List <MappingEntry>(sourceMap.ParsedMappings.Count);           // assume each line will not have been visited before

            foreach (MappingEntry mapping in sourceMap.ParsedMappings)
            {
                int generatedLine = mapping.GeneratedSourcePosition.ZeroBasedLineNumber;

                if (visitedLines.Add(generatedLine))
                {
                    MappingEntry newMapping = mapping.CloneWithResetColumnNumber();
                    parsedMappings.Add(newMapping);
                }
            }

            // Free-up any unneeded space.  This no-ops if we're already the right size.
            parsedMappings.Capacity = parsedMappings.Count;

            SourceMap newMap = new SourceMap(
                version: sourceMap.Version,
                file: sourceMap.File,
                mappings: sourceMap.Mappings,
                sources: sourceMap.Sources,
                names: sourceMap.Names,
                parsedMappings: parsedMappings,
                sourcesContent: sourceMap.SourcesContent);

            return(newMap);
        }
        /// <summary>
        /// Parses a stream representing a source map into a SourceMap object.
        /// </summary>
        public SourceMap ParseSourceMap(StreamReader sourceMapStream)
        {
            if (sourceMapStream == null)
            {
                return(null);
            }
            using (JsonTextReader jsonTextReader = new JsonTextReader(sourceMapStream))
            {
                JsonSerializer serializer = new JsonSerializer();

                SourceMap result = serializer.Deserialize <SourceMap>(jsonTextReader);

                // Since SourceMap is immutable we need to allocate a new one and copy over all the information
                List <MappingEntry> parsedMappings = _mappingsListParser.ParseMappings(result.Mappings, result.Names, result.Sources);

                // Resize to free unused memory
                parsedMappings.Capacity = parsedMappings.Count;

                result = new SourceMap(
                    version: result.Version,
                    file: result.File,
                    mappings: result.Mappings,
                    sources: result.Sources,
                    names: result.Names,
                    parsedMappings: parsedMappings,
                    sourcesContent: result.SourcesContent);

                sourceMapStream.Close();
                return(result);
            }
        }
        /// <summary>
        /// Serialize SourceMap object to json string with given serialize settings
        /// </summary>
        public string SerializeMapping(SourceMap sourceMap, JsonSerializerSettings jsonSerializerSettings = null)
        {
            if (sourceMap == null)
            {
                throw new ArgumentNullException(nameof(sourceMap));
            }

            string mappings = null;

            if (sourceMap.ParsedMappings != null && sourceMap.ParsedMappings.Count > 0)
            {
                MappingGenerateState state  = new MappingGenerateState(sourceMap.Names, sourceMap.Sources);
                StringBuilder        output = new StringBuilder();

                foreach (MappingEntry entry in sourceMap.ParsedMappings)
                {
                    SerializeMappingEntry(entry, state, output);
                }

                output.Append(';');

                mappings = output.ToString();
            }

            SourceMap mapToSerialize = new SourceMap(
                version: sourceMap.Version,
                file: sourceMap.File,
                mappings: mappings,
                sources: sourceMap.Sources,
                names: sourceMap.Names,
                parsedMappings: default,
        /// <summary>
        /// Convenience wrapper around SerializeMapping, but returns a base 64 encoded string instead
        /// </summary>
        public string GenerateSourceMapInlineComment(SourceMap sourceMap, JsonSerializerSettings jsonSerializerSettings = null)
        {
            string mappings = SerializeMapping(sourceMap, jsonSerializerSettings);

            byte[] bytes   = System.Text.Encoding.UTF8.GetBytes(mappings);
            var    encoded = Convert.ToBase64String(bytes);

            return(@"//# sourceMappingURL=data:application/json;base64," + encoded);
        }
        string ProcessWithSourceMaps(IEnumerable <AssetContent> assets)
        {
            var results = assets.Select(a => new { asset = a, result = this.reactEnvironment.ExecuteWithBabel <JavaScriptWithSourceMap>("ReactNET_transform_sourcemap", a.Contents, babelConfig, a.Path) }).ToArray();

            var offset          = 0;
            var map             = new SourcemapToolkit.SourcemapParser.SourceMap();
            var sourceMapParser = new SourceMapParser();
            var outputBuilder   = new StringBuilder();

            foreach (var result in results)
            {
                var json = result.result.SourceMap.ToJson();
                using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
                {
                    using (var streamReader = new StreamReader(memoryStream))
                    {
                        var sourceMap = sourceMapParser.ParseSourceMap(streamReader);

                        foreach (var name in sourceMap.Names)
                        {
                            map.Names.Add(name);
                        }

                        map.Sources.Add(result.asset.Path.ToLower());

                        foreach (var mappingEntry in sourceMap.ParsedMappings)
                        {
                            if (mappingEntry.OriginalSourcePosition == null)
                            {
                                continue;
                            }

                            map.ParsedMappings.Add(mappingEntry);

                            mappingEntry.OriginalFileName = result.asset.Path.ToLower();

                            mappingEntry.GeneratedSourcePosition.ZeroBasedLineNumber += offset;
                        }

                        offset += result.result.Code.Split('\n').Length;
                    }
                }

                outputBuilder.AppendLine(result.result.Code);
            }

            var sourceMapGenerator             = new SourceMapGenerator();
            var generateSourceMapInlineComment = sourceMapGenerator.GenerateSourceMapInlineComment(map);

            outputBuilder.AppendLine(generateSourceMapInlineComment);

            return(outputBuilder.ToString());
        }
示例#7
0
        /// <summary>
        /// Parses a stream representing a source map into a SourceMap object.
        /// </summary>
        public SourceMap ParseSourceMap(StreamReader sourceMapStream)
        {
            if (sourceMapStream == null)
            {
                return(null);
            }
            using (JsonTextReader jsonTextReader = new JsonTextReader(sourceMapStream))
            {
                JsonSerializer serializer = new JsonSerializer();

                SourceMap result = serializer.Deserialize <SourceMap>(jsonTextReader);
                result.ParsedMappings = _mappingsListParser.ParseMappings(result.Mappings, result.Names, result.Sources);
                sourceMapStream.Close();
                return(result);
            }
        }
示例#8
0
        /// <summary>
        /// Serialize SourceMap object to json string with given serialize settings
        /// </summary>
        public string SerializeMapping(SourceMap sourceMap, JsonSerializerSettings jsonSerializerSettings = null)
        {
            if (sourceMap == null)
            {
                throw new ArgumentNullException(nameof(sourceMap));
            }

            SourceMap mapToSerialize = new SourceMap()
            {
                File           = sourceMap.File,
                Names          = sourceMap.Names,
                Sources        = sourceMap.Sources,
                Version        = sourceMap.Version,
                SourcesContent = sourceMap.SourcesContent
            };

            if (sourceMap.ParsedMappings != null && sourceMap.ParsedMappings.Count > 0)
            {
                MappingGenerateState state  = new MappingGenerateState(sourceMap.Names, sourceMap.Sources);
                StringBuilder        output = new StringBuilder();

                foreach (MappingEntry entry in sourceMap.ParsedMappings)
                {
                    SerializeMappingEntry(entry, state, output);
                }

                output.Append(';');

                mapToSerialize.Mappings = output.ToString();
            }

            return(JsonConvert.SerializeObject(mapToSerialize,
                                               jsonSerializerSettings ?? new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                NullValueHandling = NullValueHandling.Ignore,
            }));
        }
示例#9
0
        /// <summary>
        /// Applies the mappings of a sub source map to the current source map
        /// Each mapping to the supplied source file is rewritten using the supplied source map
        /// This is useful in situations where we have a to b to c, with mappings ba.map and cb.map
        /// Calling cb.ApplySourceMap(ba) will return mappings from c to a (ca)
        /// <param name="submap">The submap to apply</param>
        /// <param name="sourceFile">The filename of the source file. If not specified, submap's File property will be used</param>
        /// <returns>A new source map</returns>
        /// </summary>
        public SourceMap ApplySourceMap(SourceMap submap, string sourceFile = null)
        {
            if (submap == null)
            {
                throw new ArgumentNullException(nameof(submap));
            }

            if (sourceFile == null)
            {
                if (submap.File == null)
                {
                    throw new Exception("ApplySourceMap expects either the explicit source file to the map, or submap's 'file' property");
                }

                sourceFile = submap.File;
            }

            SourceMap newSourceMap = new SourceMap
            {
                File           = this.File,
                Version        = this.Version,
                Sources        = new List <string>(),
                Names          = new List <string>(),
                SourcesContent = new List <string>(),
                ParsedMappings = new List <MappingEntry>()
            };

            // transform mappings in this source map
            foreach (MappingEntry mappingEntry in this.ParsedMappings)
            {
                MappingEntry newMappingEntry = mappingEntry.Clone();

                if (mappingEntry.OriginalFileName == sourceFile && mappingEntry.OriginalSourcePosition != null)
                {
                    MappingEntry correspondingSubMapMappingEntry = submap.GetMappingEntryForGeneratedSourcePosition(mappingEntry.OriginalSourcePosition);

                    if (correspondingSubMapMappingEntry != null)
                    {
                        // Copy the mapping
                        newMappingEntry = new MappingEntry
                        {
                            GeneratedSourcePosition = mappingEntry.GeneratedSourcePosition.Clone(),
                            OriginalSourcePosition  = correspondingSubMapMappingEntry.OriginalSourcePosition.Clone(),
                            OriginalName            = correspondingSubMapMappingEntry.OriginalName ?? mappingEntry.OriginalName,
                            OriginalFileName        = correspondingSubMapMappingEntry.OriginalFileName ?? mappingEntry.OriginalFileName
                        };
                    }
                }

                // Copy into "Sources" and "Names"
                string originalFileName = newMappingEntry.OriginalFileName;
                string originalName     = newMappingEntry.OriginalName;

                if (originalFileName != null && !newSourceMap.Sources.Contains(originalFileName))
                {
                    newSourceMap.Sources.Add(originalFileName);
                }

                if (originalName != null && !newSourceMap.Names.Contains(originalName))
                {
                    newSourceMap.Names.Add(originalName);
                }

                newSourceMap.ParsedMappings.Add(newMappingEntry);
            }
            ;

            return(newSourceMap);
        }
示例#10
0
        /// <summary>
        /// Applies the mappings of a sub source map to the current source map
        /// Each mapping to the supplied source file is rewritten using the supplied source map
        /// This is useful in situations where we have a to b to c, with mappings ba.map and cb.map
        /// Calling cb.ApplySourceMap(ba) will return mappings from c to a (ca)
        /// <param name="submap">The submap to apply</param>
        /// <param name="sourceFile">The filename of the source file. If not specified, submap's File property will be used</param>
        /// <returns>A new source map</returns>
        /// </summary>
        public SourceMap ApplySourceMap(SourceMap submap, string sourceFile = null)
        {
            if (submap == null)
            {
                throw new ArgumentNullException(nameof(submap));
            }

            if (sourceFile == null)
            {
                if (submap.File == null)
                {
                    throw new Exception($"{nameof(ApplySourceMap)} expects either the explicit source file to the map, or submap's 'file' property");
                }

                sourceFile = submap.File;
            }

            HashSet <string>    sources        = new HashSet <string>(StringComparer.Ordinal);
            HashSet <string>    names          = new HashSet <string>(StringComparer.Ordinal);
            List <MappingEntry> parsedMappings = new List <MappingEntry>(this.ParsedMappings.Count);

            // transform mappings in this source map
            foreach (MappingEntry mappingEntry in this.ParsedMappings)
            {
                MappingEntry newMappingEntry = mappingEntry;

                if (mappingEntry.OriginalFileName == sourceFile && mappingEntry.OriginalSourcePosition != SourcePosition.NotFound)
                {
                    MappingEntry?correspondingSubMapMappingEntry = submap.GetMappingEntryForGeneratedSourcePosition(mappingEntry.OriginalSourcePosition);

                    if (correspondingSubMapMappingEntry != null)
                    {
                        // Copy the mapping
                        newMappingEntry = new MappingEntry(
                            generatedSourcePosition: mappingEntry.GeneratedSourcePosition,
                            originalSourcePosition: correspondingSubMapMappingEntry.Value.OriginalSourcePosition,
                            originalName: correspondingSubMapMappingEntry.Value.OriginalName ?? mappingEntry.OriginalName,
                            originalFileName: correspondingSubMapMappingEntry.Value.OriginalFileName ?? mappingEntry.OriginalFileName);
                    }
                }

                // Copy into "Sources" and "Names"
                string originalFileName = newMappingEntry.OriginalFileName;
                string originalName     = newMappingEntry.OriginalName;

                if (originalFileName != null)
                {
                    sources.Add(originalFileName);
                }

                if (originalName != null)
                {
                    names.Add(originalName);
                }

                parsedMappings.Add(newMappingEntry);
            }

            SourceMap newSourceMap = new SourceMap(
                version: Version,
                file: File,
                mappings: default,