Inheritance: Block, IWritable
Ejemplo n.º 1
0
        internal NestedBlockProperty(SelectorAndBlock innerBlock, int start, int stop)
        {
            Block = innerBlock;

            Start = start;
            Stop  = stop;
        }
Ejemplo n.º 2
0
        public InnerMediaProperty(MediaQuery media, SelectorAndBlock block, int start, int stop, string file)
        {
            MediaQuery = media;

            Block = block;

            Start    = start;
            Stop     = stop;
            FilePath = file;
        }
Ejemplo n.º 3
0
        private static void Verify(SelectorAndBlock block)
        {
            var nestedBlock = block.Properties.OfType<NestedBlockProperty>().ToList();
            var innerMedia = block.Properties.OfType<InnerMediaProperty>().ToList();

            if (nestedBlock.Count != 0)
            {
                throw new InvalidOperationException("It shouldn't be possible for nested blocks to remain here");
            }

            foreach (var media in innerMedia)
            {
                Current.RecordError(ErrorType.Compiler, media, "@media blocks cannot be nested within each other");
            }
        }
Ejemplo n.º 4
0
        internal SelectorAndBlock BindAndEvaluateMixins(Scope scope = null, int depth = 0, LinkedList<MixinApplicationProperty> invokationChain = null)
        {
            if (depth > Scope.MAX_DEPTH)
            {
                Current.RecordError(ErrorType.Compiler, invokationChain.Last.Value, "Scope max depth exceeded, probably infinite recursion");
                throw new StoppedCompilingException();
            }

            var injectReset = IsReset && scope == null;
            scope = scope ?? Current.GlobalScope;

            if (injectReset)
            {
                var vars = new Dictionary<string, Value>();
                foreach (var var in ResetContext)
                {
                    vars[var.Name] = var.Value.Bind(scope);
                }

                scope = scope.Push(vars, new Dictionary<string, MixinBlock>(), Position.NoSite);
            }

            invokationChain = invokationChain ?? new LinkedList<MixinApplicationProperty>();

            var retRules = new List<Property>();

            var nestedBlocks = Properties.OfType<NestedBlockProperty>();
            var mixinApplications = Properties.OfType<MixinApplicationProperty>();
            var nameValueRules = Properties.OfType<NameValueProperty>().ToList();
            var inclRules = Properties.OfType<IncludeSelectorProperty>();
            var resetRules = Properties.Where(w => w is ResetProperty || w is ResetSelfProperty);
            var variableRules = Properties.OfType<VariableProperty>();

            if (variableRules.Count() > 0)
            {
                var vars = new Dictionary<string, Value>();
                foreach (var var in variableRules)
                {
                    vars[var.Name] = var.Value.Bind(scope);
                }

                scope = scope.Push(vars, new Dictionary<string, MixinBlock>(), this);
            }

            foreach (var nameValue in nameValueRules)
            {
                retRules.Add(new NameValueProperty(nameValue.Name, nameValue.Value.Bind(scope), nameValue.Start, nameValue.Stop, nameValue.FilePath));
            }

            // Do the overrides last, so they can override everything
            foreach (var rule in mixinApplications.OrderBy(k => k.DoesOverride ? 1 : 0))
            {
                var mixin = scope.LookupMixin(rule.Name);

                if (mixin == null)
                {
                    if (!rule.IsOptional)
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "No mixin of the name [" + rule.Name + "] found");
                    }

                    // We can keep going, to possibly find more errors, so do so!
                    continue;
                }

                var @params = rule.Parameters.ToList();
                var passedCount = @params.Count;
                var maximum = mixin.Parameters.Count();
                var minimum = mixin.Parameters.Count(c => c.DefaultValue is NotFoundValue);

                var iLastRaw = @params.FindLastIndex(a => a.Name.IsNullOrEmpty());
                var iFirstByName = @params.FindIndex(a => a.Name.HasValue());

                var byNames = @params.Where(s => s.Name.HasValue());

                if (iFirstByName != -1 && iLastRaw > iFirstByName)
                {
                    Current.RecordError(ErrorType.Compiler, rule, "Arguments passed by name must appear after those passed without");
                    continue;
                }

                var outerContinue = false;
                foreach (var byName in byNames)
                {
                    bool found = false;
                    int index = -1;
                    for (var i = 0; i < mixin.Parameters.Count(); i++)
                    {
                        var p = mixin.Parameters.ElementAt(i);
                        if (p.Name == byName.Name)
                        {
                            found = true;
                            index = i;
                        }
                    }

                    if (!found)
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "Argument to mixin [" + rule.Name + "] passed with name [" + byName.Name + "] but no parameter with that name exists.");
                        outerContinue = true;
                        continue;
                    }

                    if (index <= iLastRaw)
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "Argument [" + byName.Name + "] passed by name, but already passed earlier in mixin declaration");
                        outerContinue = true;
                        continue;
                    }
                }

                if (outerContinue) { continue; }

                if (iLastRaw != -1 && iLastRaw + 1 < minimum)
                {
                    Current.RecordError(ErrorType.Compiler, rule, "Tried to invoke mixin [" + rule.Name + "] with " + passedCount + " parameters, when a minimum of " + minimum + " are needed.");
                    continue;
                }

                if (passedCount > maximum)
                {
                    Current.RecordError(ErrorType.Compiler, rule, "Tried to invoke mixin [" + rule.Name + "] with " + passedCount + " parameters, when a maximum of " + maximum + " are allowed.");
                    continue;
                }

                var alreadyDefined = new List<string>();
                var mixinReferences = new Dictionary<string, MixinBlock>();
                var boundVariables = new Dictionary<string, Value>();
                for (int i = 0; i <= iLastRaw; i++)
                {
                    var @param = mixin.Parameters.ElementAt(i);
                    var value = rule.Parameters.ElementAt(i);

                    BindParameter(scope, mixinReferences, boundVariables, @param, value.Value);
                    alreadyDefined.Add(@param.Name);
                }

                foreach (var byName in byNames)
                {
                    var @param = mixin.Parameters.Single(p => p.Name == byName.Name);
                    var value = byName.Value;

                    BindParameter(scope, mixinReferences, boundVariables, @param, value);
                    alreadyDefined.Add(@param.Name);
                }

                foreach (var withDefault in mixin.Parameters.Where(w => !(w.DefaultValue is NotFoundValue) && !alreadyDefined.Contains(w.Name)))
                {
                    var @param = mixin.Parameters.Single(p => p.Name == withDefault.Name);
                    var value = withDefault.DefaultValue;

                    BindParameter(scope, mixinReferences, boundVariables, @param, value);
                }

                foreach (var mustBeDefined in mixin.Parameters.Where(w => w.DefaultValue is NotFoundValue))
                {
                    if (!alreadyDefined.Contains(mustBeDefined.Name))
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "No value passed for parameter [" + mustBeDefined.Name + "]");
                        continue;
                    }
                }

                bool includeArguments = true;
                var argParts = new List<Value>();
                foreach (var param in mixin.Parameters)
                {
                    Value part;
                    if (boundVariables.TryGetValue(param.Name, out part))
                    {
                        if (!(part is ExcludeFromOutputValue))
                        {
                            argParts.Add(part);
                        }
                    }
                    else
                    {
                        includeArguments = false;
                    }
                }

                // Only include arguments if all the variables are "simple", and thus found as variables
                if (includeArguments && argParts.Count > 0)
                {
                    boundVariables["arguments"] = argParts.Count > 1 ? new CommaDelimittedValue(argParts) : argParts[0];
                }

                var localScope = Current.GlobalScope.Push(boundVariables, mixinReferences, rule);

                invokationChain.AddLast(rule);

                var blockEquiv = new SelectorAndBlock(InvalidSelector.Singleton, mixin.Properties, null, -1, -1, null);
                var boundMixin = blockEquiv.BindAndEvaluateMixins(localScope, depth + 1, invokationChain);

                invokationChain.RemoveLast();

                var newRules = boundMixin.Properties;

                // Any rules that are defined in a @mixin()! clause need to override the outer ones
                if (rule.DoesOverride)
                {
                    retRules.RemoveAll(r => r is NameValueProperty && newRules.OfType<NameValueProperty>().Any(a => a.Name == ((NameValueProperty)r).Name));
                }

                retRules.AddRange(newRules);
            }

            foreach (var block in nestedBlocks)
            {
                retRules.Add(new NestedBlockProperty(block.Block.BindAndEvaluateMixins(scope), block.Start, block.Stop));
            }

            retRules.AddRange(inclRules);
            retRules.AddRange(resetRules);

            return new SelectorAndBlock(this.Selector, retRules, this.ResetContext, this.Start, this.Stop, this.FilePath);
        }
Ejemplo n.º 5
0
        internal static InnerMediaProperty ParseInnerMediaDirective(ParserStream stream)
        {
            var start = stream.Position;

            var media = new StringBuilder();
            stream.ScanUntil(media, '{');

            var mediaStr = media.ToString().Trim();
            if (mediaStr.IsNullOrEmpty())
            {
                Current.RecordError(ErrorType.Parser, Position.Create(start, stream.Position, Current.CurrentFilePath), "Expected media list");
                throw new StoppedParsingException();
            }

            var mediaQuery = MediaQueryParser.Parse(mediaStr, Position.Create(start, stream.Position, Current.CurrentFilePath));

            var props = ParseCssRules(InvalidSelector.Singleton, stream);

            var blockEquiv = new SelectorAndBlock(InvalidSelector.Singleton, props, null, start, stream.Position, Current.CurrentFilePath);

            return new InnerMediaProperty(mediaQuery, blockEquiv, start, stream.Position, Current.CurrentFilePath);
        }
Ejemplo n.º 6
0
        public static List<Block> Task(List<Block> blocks)
        {
            var ret = new List<Block>();

            ret.AddRange(blocks.OfType<CssCharset>());
            ret.AddRange(blocks.OfType<Model.Import>().Select(s => new Model.Import(MinifyValue(s.ToImport), ForQuery(s.MediaQuery), s.Start, s.Stop, s.FilePath)));
            ret.AddRange(blocks.Where(w => w is SelectorAndBlock && ((SelectorAndBlock)w).IsReset));

            var remainder = blocks.Where(w => !ret.Contains(w));

            foreach (var statement in remainder)
            {
                var block = statement as SelectorAndBlock;
                if (block != null)
                {
                    var rules = new List<Property>();
                    foreach (var prop in block.Properties)
                    {
                        rules.Add(MinifyProperty(prop));
                    }

                    rules = MinifyPropertyList(rules).ToList();

                    ret.Add(new SelectorAndBlock(block.Selector, rules, block.ResetContext, block.Start, block.Stop, block.FilePath));
                    continue;
                }

                var media = statement as MediaBlock;
                if (media != null)
                {
                    var subStatements = Task(media.Blocks.ToList());
                    ret.Add(new MediaBlock(ForQuery(media.MediaQuery), subStatements, media.Start, media.Stop, media.FilePath));
                    continue;
                }

                var keyframes = statement as KeyFramesBlock;
                if (keyframes != null)
                {
                    var frames = new List<KeyFrame>();

                    // minify each frame
                    foreach (var frame in keyframes.Frames)
                    {
                        var blockEquiv = new SelectorAndBlock(InvalidSelector.Singleton, frame.Properties, null, frame.Start, frame.Stop, frame.FilePath);
                        var mind = Task(new List<Block>() { blockEquiv });
                        frames.Add(new KeyFrame(frame.Percentages.ToList(), ((SelectorAndBlock)mind[0]).Properties.ToList(), frame.Start, frame.Stop, frame.FilePath));
                    }

                    // collapse frames if rules are identical
                    var frameMap =
                        frames.ToDictionary(
                            d =>
                            {
                                using (var str = new StringWriter())
                                using (var css = new MinimalCssWriter(str))
                                {
                                    foreach (var rule in d.Properties.Cast<NameValueProperty>())
                                    {
                                        css.WriteRule(rule, lastRule: false);
                                    }

                                    return str.ToString();
                                }
                            },
                            d => d
                        );

                    frames.Clear();
                    foreach (var frame in frameMap.GroupBy(k => k.Key))
                    {
                        var allPercents = new List<decimal>();
                        foreach (var f in frame)
                        {
                            allPercents.AddRange(f.Value.Percentages);
                        }

                        var urFrame = frame.First().Value;

                        frames.Add(new KeyFrame(allPercents, urFrame.Properties.ToList(), urFrame.Start, urFrame.Stop, urFrame.FilePath));
                    }

                    ret.Add(new KeyFramesBlock(keyframes.Prefix, keyframes.Name, frames, keyframes.Variables.ToList(), keyframes.Start, keyframes.Stop, keyframes.FilePath));
                    continue;
                }

                ret.Add(statement);
            }

            return ret;
        }
Ejemplo n.º 7
0
        private static SelectorAndBlock PrefixBlock(SelectorAndBlock block)
        {
            var ret = new List<Property>();

            var asNameValue = block.Properties.Cast<NameValueProperty>().ToList();

            foreach (var prop in asNameValue)
            {
                var possible = PrefixProperty(prop);

                // No prefix versions, no point in any conflict checking; just put it back and continue
                if (possible == null)
                {
                    ret.Add(prop);
                    continue;
                }

                var alreadyPresent = 
                    asNameValue.Where(
                        w => 
                            possible.Any(p => 
                                p.Name.Equals(w.Name, StringComparison.InvariantCultureIgnoreCase) && 
                                p.Name != prop.Name
                            )
                    ).ToList();

                foreach (var dupe in alreadyPresent)
                {
                    var dupeOf = possible.Where(w => w.Name == dupe.Name).ToList();

                    if (dupeOf.All(d => d.Value.Equals(dupe.Value)))
                    {
                        Current.RecordInfo("Prefixed property " + dupe.Name + " in '" + block.Selector + "' could have been generated automatically");
                    }
                }

                possible.RemoveAll(x => alreadyPresent.Any(y => y.Name.Equals(x.Name, StringComparison.InvariantCultureIgnoreCase)));

                ret.AddRange(possible);
            }

            return new SelectorAndBlock(block.Selector, ret, block.ResetContext, block.Start, block.Stop, block.FilePath);
        }
Ejemplo n.º 8
0
        private static IEnumerable<Block> Unroll(SelectorAndBlock block)
        {
            var ret = new List<Block>();
            var props = new List<Property>();

            foreach (var prop in block.Properties)
            {
                var media = prop as InnerMediaProperty;
                var nested = prop as NestedBlockProperty;
                if (media == null && nested == null)
                {
                    props.Add(prop);
                    continue;
                }

                if (nested != null)
                {
                    var inner = Unroll(nested.Block);
                    var innerMedia = inner.OfType<MediaBlock>();
                    var other = inner.Where(i => !(i is MediaBlock)).Cast<SelectorAndBlock>();

                    props.AddRange(other.Select(s => new NestedBlockProperty(s, s.Start, s.Stop)));

                    foreach (var m in innerMedia)
                    {
                        var selBlock =
                            new SelectorAndBlock(
                                block.Selector,
                                m.Blocks.Cast<SelectorAndBlock>().Select(s => new NestedBlockProperty(s, s.Start, s.Stop)),
                                null,
                                m.Start,
                                m.Stop,
                                m.FilePath
                            );

                        var newMedia =
                            new MediaBlock(
                                m.MediaQuery,
                                new List<Block> { selBlock },
                                m.Start,
                                m.Stop,
                                m.FilePath
                            );

                        ret.Add(newMedia);
                    }

                    continue;
                }

                var unrolled =
                    new MediaBlock(
                        media.MediaQuery,
                        new List<Block>
                        {
                            new SelectorAndBlock(
                                block.Selector,
                                media.Block.Properties,
                                null,
                                -1,
                                -1,
                                media.FilePath
                            )
                        },
                        -1,
                        -1,
                        media.FilePath
                    );

                ret.Add(unrolled);
            }

            ret.Add(new SelectorAndBlock(block.Selector, props, null, block.Start, block.Stop, block.FilePath));

            return ret;
        }
Ejemplo n.º 9
0
        internal SelectorAndBlock BindAndEvaluateMixins(Scope scope = null, int depth = 0, LinkedList <MixinApplicationProperty> invokationChain = null)
        {
            if (depth > Scope.MAX_DEPTH)
            {
                Current.RecordError(ErrorType.Compiler, invokationChain.Last.Value, "Scope max depth exceeded, probably infinite recursion");
                throw new StoppedCompilingException();
            }

            var injectReset = IsReset && scope == null;

            scope = scope ?? Current.GlobalScope;

            if (injectReset)
            {
                var vars = new Dictionary <string, Value>();
                foreach (var var in ResetContext)
                {
                    vars[var.Name] = var.Value.Bind(scope);
                }

                scope = scope.Push(vars, new Dictionary <string, MixinBlock>(), Position.NoSite);
            }

            invokationChain = invokationChain ?? new LinkedList <MixinApplicationProperty>();

            var retRules = new List <Property>();

            var nestedBlocks      = Properties.OfType <NestedBlockProperty>();
            var mixinApplications = Properties.OfType <MixinApplicationProperty>();
            var nameValueRules    = Properties.OfType <NameValueProperty>().ToList();
            var inclRules         = Properties.OfType <IncludeSelectorProperty>();
            var resetRules        = Properties.Where(w => w is ResetProperty || w is ResetSelfProperty);
            var variableRules     = Properties.OfType <VariableProperty>();
            var innerMedia        = Properties.OfType <InnerMediaProperty>();

            if (variableRules.Count() > 0)
            {
                var vars = new Dictionary <string, Value>();
                foreach (var var in variableRules)
                {
                    vars[var.Name] = var.Value.Bind(scope);
                }

                scope = scope.Push(vars, new Dictionary <string, MixinBlock>(), this);
            }

            foreach (var nameValue in nameValueRules)
            {
                retRules.Add(new NameValueProperty(nameValue.Name, nameValue.Value.Bind(scope), nameValue.Start, nameValue.Stop, nameValue.FilePath));
            }

            // Do the overrides last, so they can override everything
            foreach (var rule in mixinApplications.OrderBy(k => k.DoesOverride ? 1 : 0))
            {
                var mixin = scope.LookupMixin(rule.Name);

                if (mixin == null)
                {
                    if (!rule.IsOptional)
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "No mixin of the name [" + rule.Name + "] found");
                    }

                    // We can keep going, to possibly find more errors, so do so!
                    continue;
                }

                var @params     = rule.Parameters.ToList();
                var passedCount = @params.Count;
                var maximum     = mixin.Parameters.Count();
                var minimum     = mixin.Parameters.Count(c => c.DefaultValue is NotFoundValue);

                var iLastRaw     = @params.FindLastIndex(a => a.Name.IsNullOrEmpty());
                var iFirstByName = @params.FindIndex(a => a.Name.HasValue());

                var byNames = @params.Where(s => s.Name.HasValue());

                if (iFirstByName != -1 && iLastRaw > iFirstByName)
                {
                    Current.RecordError(ErrorType.Compiler, rule, "Arguments passed by name must appear after those passed without");
                    continue;
                }

                var outerContinue = false;
                foreach (var byName in byNames)
                {
                    bool found = false;
                    int  index = -1;
                    for (var i = 0; i < mixin.Parameters.Count(); i++)
                    {
                        var p = mixin.Parameters.ElementAt(i);
                        if (p.Name == byName.Name)
                        {
                            found = true;
                            index = i;
                        }
                    }

                    if (!found)
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "Argument to mixin [" + rule.Name + "] passed with name [" + byName.Name + "] but no parameter with that name exists.");
                        outerContinue = true;
                        continue;
                    }

                    if (index <= iLastRaw)
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "Argument [" + byName.Name + "] passed by name, but already passed earlier in mixin declaration");
                        outerContinue = true;
                        continue;
                    }
                }

                if (outerContinue)
                {
                    continue;
                }

                if (iLastRaw != -1 && iLastRaw + 1 < minimum)
                {
                    Current.RecordError(ErrorType.Compiler, rule, "Tried to invoke mixin [" + rule.Name + "] with " + passedCount + " parameters, when a minimum of " + minimum + " are needed.");
                    continue;
                }

                if (passedCount > maximum)
                {
                    Current.RecordError(ErrorType.Compiler, rule, "Tried to invoke mixin [" + rule.Name + "] with " + passedCount + " parameters, when a maximum of " + maximum + " are allowed.");
                    continue;
                }

                var alreadyDefined  = new List <string>();
                var mixinReferences = new Dictionary <string, MixinBlock>();
                var boundVariables  = new Dictionary <string, Value>();
                for (int i = 0; i <= iLastRaw; i++)
                {
                    var @param = mixin.Parameters.ElementAt(i);
                    var value  = rule.Parameters.ElementAt(i);

                    BindParameter(scope, mixinReferences, boundVariables, @param, value.Value);
                    alreadyDefined.Add(@param.Name);
                }

                foreach (var byName in byNames)
                {
                    var @param = mixin.Parameters.Single(p => p.Name == byName.Name);
                    var value  = byName.Value;

                    BindParameter(scope, mixinReferences, boundVariables, @param, value);
                    alreadyDefined.Add(@param.Name);
                }

                foreach (var withDefault in mixin.Parameters.Where(w => !(w.DefaultValue is NotFoundValue) && !alreadyDefined.Contains(w.Name)))
                {
                    var @param = mixin.Parameters.Single(p => p.Name == withDefault.Name);
                    var value  = withDefault.DefaultValue;

                    BindParameter(scope, mixinReferences, boundVariables, @param, value);
                }

                foreach (var mustBeDefined in mixin.Parameters.Where(w => w.DefaultValue is NotFoundValue))
                {
                    if (!alreadyDefined.Contains(mustBeDefined.Name))
                    {
                        Current.RecordError(ErrorType.Compiler, rule, "No value passed for parameter [" + mustBeDefined.Name + "]");
                        continue;
                    }
                }

                bool includeArguments = true;
                var  argParts         = new List <Value>();
                foreach (var param in mixin.Parameters)
                {
                    Value part;
                    if (boundVariables.TryGetValue(param.Name, out part))
                    {
                        if (!(part is ExcludeFromOutputValue))
                        {
                            argParts.Add(part);
                        }
                    }
                    else
                    {
                        includeArguments = false;
                    }
                }

                // Only include arguments if all the variables are "simple", and thus found as variables
                if (includeArguments && argParts.Count > 0)
                {
                    boundVariables["arguments"] = argParts.Count > 1 ? new CommaDelimittedValue(argParts) : argParts[0];
                }

                var localScope = Current.GlobalScope.Push(boundVariables, mixinReferences, rule);

                invokationChain.AddLast(rule);

                var blockEquiv = new SelectorAndBlock(InvalidSelector.Singleton, mixin.Properties, null, -1, -1, null);
                var boundMixin = blockEquiv.BindAndEvaluateMixins(localScope, depth + 1, invokationChain);

                invokationChain.RemoveLast();

                var newRules = boundMixin.Properties;

                // Any rules that are defined in a @mixin()! clause need to override the outer ones
                if (rule.DoesOverride)
                {
                    retRules.RemoveAll(r => r is NameValueProperty && newRules.OfType <NameValueProperty>().Any(a => a.Name == ((NameValueProperty)r).Name));
                }

                retRules.AddRange(newRules);
            }

            foreach (var block in nestedBlocks)
            {
                retRules.Add(new NestedBlockProperty(block.Block.BindAndEvaluateMixins(scope), block.Start, block.Stop));
            }

            foreach (var media in innerMedia)
            {
                retRules.Add(new InnerMediaProperty(media.MediaQuery, media.Block.BindAndEvaluateMixins(scope), media.Start, media.Stop, media.FilePath));
            }

            retRules.AddRange(inclRules);
            retRules.AddRange(resetRules);

            return(new SelectorAndBlock(this.Selector, retRules, this.ResetContext, this.Start, this.Stop, this.FilePath));
        }
Ejemplo n.º 10
0
        private static SelectorAndBlock CacheBreakBlock(SelectorAndBlock block)
        {
            var ret = new List<Property>();

            foreach (var prop in block.Properties.Cast<NameValueProperty>())
            {
                ret.Add(CacheBreakProperty(prop));
            }

            return new SelectorAndBlock(block.Selector, ret, block.ResetContext, block.Start, block.Stop, block.FilePath);
        }
Ejemplo n.º 11
0
        internal NestedBlockProperty(SelectorAndBlock innerBlock, int start, int stop)
        {
            Block = innerBlock;

            Start = start;
            Stop = stop;
        }
Ejemplo n.º 12
0
        public InnerMediaProperty(MediaQuery media, SelectorAndBlock block, int start, int stop, string file)
        {
            MediaQuery = media;

            Block = block;

            Start = start;
            Stop = stop;
            FilePath = file;
        }