Example #1
0
        Minify <TResult>(string source,
                         TResult space, TResult newLine,
                         MinificationOptions options,
                         Func <Token, TResult> resultSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(_()); IEnumerable <TResult> _()
            {
Example #2
0
 public static IEnumerable <string> Minify(string source, string newLine,
                                           MinificationOptions options) =>
 Minify(source, " ", newLine, options, t => t.Substring(source));
Example #3
0
 public static IEnumerable <string> Minify(string source, MinificationOptions options) =>
 Minify(source, Environment.NewLine, options);
Example #4
0
 public MinificationOptions OrCommentFilterOf(MinificationOptions other)
 => CommentFilter == other.CommentFilter || CommentFilter != null && other.CommentFilter == null ? this
      : CommentFilter == null && other.CommentFilter != null?WithCommentFilter(other.CommentFilter)
     : WithCommentFilter((t, s) => CommentFilter(t, s) || other.CommentFilter(t, s));
Example #5
0
 MinificationOptions(MinificationOptions options) :
     this(options.CommentFilter, options.KeepLeadComment)
 {
 }
Example #6
0
        Minify <TResult>(string source,
                         TResult space, TResult newLine,
                         MinificationOptions options,
                         Func <Token, TResult> resultSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(_()); IEnumerable <TResult> _()
            {
                bool IsSpaceOrTab(char ch) => ch == ' ' || ch == '\t';
                bool IsAsciiLetter(char ch) => (ch = (char)(ch & ~0x20)) >= 'A' && ch <= 'z';
                bool IsWordChar(char ch) => char.IsLetter(ch) ||
                ch >= '0' && ch <= '9' ||
                ch == '_';

                var lcs    = LeadCommentState.Awaiting;
                var lastCh = (char?)null;
                var lastSingleLineCommentLine = (int?)null;

                TResult NewLineWhileResettingLastChar()
                {
                    lastCh = null;
                    return(newLine);
                }

                foreach (var t in Scanner.Scan(source))
                {
                    switch (t.Kind)
                    {
                    case TokenKind.NewLine:
                    case TokenKind.WhiteSpace:
                        break;

                    case TokenKind k
                        when k.HasTraits(TokenKindTraits.Comment) &&
                        options.KeepLeadComment &&
                        lcs != LeadCommentState.Processed &&
                        (lastSingleLineCommentLine is null ||
                         lastSingleLineCommentLine is int ln &&
                         t.Start.Line - ln == 1):
                    {
                        yield return(resultSelector(t));

                        if (k == TokenKind.SingleLineComment)
                        {
                            lastSingleLineCommentLine = t.Start.Line;
                            yield return(NewLineWhileResettingLastChar());

                            lcs = LeadCommentState.Processing;
                        }
                        else
                        {
                            lcs = LeadCommentState.Processed;
                        }
                        break;
                    }

                    case TokenKind k
                        when k.HasTraits(TokenKindTraits.Comment) &&
                        options.CommentFilter is Func <Token, string, bool> filter &&
                        filter(t, source):
                    {
                        yield return(resultSelector(t));

                        if (k == TokenKind.SingleLineComment)
                        {
                            yield return(NewLineWhileResettingLastChar());
                        }
                        break;
                    }

                    case TokenKind k when k.HasTraits(TokenKindTraits.Comment):
                        continue;

                    default:
                    {
                        lcs = LeadCommentState.Processed;

                        if (t.Kind == TokenKind.PreprocessorDirective)
                        {
                            var tei = t.End.Offset;

                            var si = t.Start.Offset + 1;
                            while (si < tei && IsSpaceOrTab(source[si]))
                            {
                                si++;
                            }

                            var ei = si;
                            while (ei < tei && IsAsciiLetter(source[ei]))
                            {
                                ei++;
                            }

                            var length = ei - si;

                            if (length == 0 ||
                                string.CompareOrdinal("region", 0, source, si, length) != 0 &&
                                string.CompareOrdinal("endregion", 0, source, si, length) != 0)
                            {
                                if (lastCh != null)
                                {
                                    yield return(newLine);
                                }

                                yield return(resultSelector(t));

                                yield return(NewLineWhileResettingLastChar());
                            }
                        }
                        else
                        {
                            if (lastCh is char lch)
                            {
                                var ch = source[t.Start.Offset];
                                if (IsWordChar(ch) && IsWordChar(lch) || ch == lch && (ch == '+' || ch == '-' || ch == '*'))
                                {
                                    yield return(space);
                                }
                            }

                            yield return(resultSelector(t));

                            lastCh = source[t.End.Offset - 1];
                        }

                        break;
                    }
                    }
                }
            }
        }