Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Fizzler V3 #1092

Merged
merged 33 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1c7ce66
Initial ExCss Implementation ported from RemoveFizzlerV2 Branch
inforithmics Sep 9, 2023
6286583
fixing unit tests
inforithmics Sep 9, 2023
8176a07
add unit tests
inforithmics Sep 9, 2023
d51a86b
Added some more Selector Tests
inforithmics Sep 9, 2023
fd7b5cf
fixing unit tests
inforithmics Sep 16, 2023
9d96ecf
fixing build
inforithmics Sep 16, 2023
ea8b7b1
fixed unit tests
inforithmics Sep 16, 2023
82f9ea7
done
inforithmics Sep 17, 2023
e4ac048
removed todos: and added one more case for not implementedexception
inforithmics Sep 17, 2023
7339e24
fixed naming
inforithmics Sep 17, 2023
8ffee3d
added nth of type and nth-last-of-type tests are not run because fizz…
inforithmics Sep 17, 2023
d1c9ee5
implement nthlastchild in fizzler
inforithmics Sep 17, 2023
6613c74
Remove Fizzler from Readme
inforithmics Sep 19, 2023
ae00a19
remove todo because it is now implemented
inforithmics Sep 25, 2023
5a687ee
Anglesharp Initial
inforithmics Sep 28, 2023
583a1c7
AngleSharp fixes
inforithmics Sep 28, 2023
484b3e5
update excss (step and offset are now public)
inforithmics Sep 29, 2023
736588d
disable AngleSharp
inforithmics Sep 29, 2023
9d108ec
fixed compilation with anglesharp (disabled)
inforithmics Sep 29, 2023
dfb7c60
fixing tests
inforithmics Sep 29, 2023
45c87e4
Remove Anglesharp
inforithmics Sep 30, 2023
8b7a228
remove the specifiyed <SvgElement> for AngleSharp compilation
inforithmics Sep 30, 2023
4a43c78
Revert "remove the specifiyed <SvgElement> for AngleSharp compilation"
inforithmics Sep 30, 2023
83be12f
reduce change for <svgelement> removal
inforithmics Sep 30, 2023
fa615ca
reduce changes
inforithmics Sep 30, 2023
48f01e1
parse not selector
inforithmics Sep 30, 2023
c62458b
Updated Fizzler for regression tests to 1.3.0 and implemented :not Ps…
inforithmics Oct 1, 2023
1cb0ba0
removed nullable warning
inforithmics Oct 1, 2023
a2e4e6f
spelling fixes
inforithmics Oct 1, 2023
e16ad81
Ignore some not implemented Properties
inforithmics Oct 1, 2023
f6c5aa5
fixed nth-child and nth-last-child implementation (fizzler implementa…
inforithmics Oct 1, 2023
3afdd58
imiplemented nth type and nth-last-type
inforithmics Oct 1, 2023
09bfd20
Implement :root
inforithmics Oct 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,4 @@ This project has dependencies on other open-source projects. These projects are

|Project|Author|Sources|License|
|--------|-----|---|---------|
|Fizzler|Atif Aziz (@atifaziz)|[GitHub](https://github.com/atifaziz/Fizzler)|[LGPL](https://github.com/atifaziz/Fizzler/blob/master/COPYING.txt)|
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is now removed from the nuget package as dependency is now only used as unit test dependency.

|ExCSS|Tyler Brinks (@tylerbrinks)|[GitHub](https://github.com/TylerBrinks/ExCSS)|[MIT](https://github.com/TylerBrinks/ExCSS/blob/master/license.txt)|
327 changes: 327 additions & 0 deletions Source/Css/ExCssQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using ExCSS;

namespace Svg.Css
{
internal static class ExCssQuery
{
public static IEnumerable<SvgElement> QuerySelectorAll(this SvgElement elem, ISelector selector, SvgElementFactory elementFactory)
{
var input = Enumerable.Repeat(elem, 1);
var ops = new ExSvgElementOps(elementFactory);

var func = GetFunc(selector, ops, ops.Universal());
var descendants = ops.Descendant();
var func1 = func;
func = f => func1(descendants(f));
return func(input).Distinct();
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
CompoundSelector selector,
ExSvgElementOps ops,
Func<IEnumerable<SvgElement>,
IEnumerable<SvgElement>> inFunc)
{
foreach (var it in selector)
{
inFunc = GetFunc(it, ops, inFunc);
}

return inFunc;
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
FirstChildSelector selector,
ExSvgElementOps ops)
{
var step = selector.Step;
var offset = selector.Offset;

if (offset == 0)
{
return ops.FirstChild();
}

return ops.NthChild(step, offset);
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
FirstTypeSelector selector,
ExSvgElementOps ops)
{
var step = selector.Step;
var offset = selector.Offset;

return ops.NthType(step, offset);
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
LastTypeSelector selector,
ExSvgElementOps ops)
{
var step = selector.Step;
var offset = selector.Offset;

return ops.NthLastType(step, offset);
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
LastChildSelector selector,
ExSvgElementOps ops)
{
var step = selector.Step;
var offset = selector.Offset;

if (offset == 0)
{
return ops.LastChild();
}

return ops.NthLastChild(step, offset);
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
ListSelector listSelector,
ExSvgElementOps ops,
Func<IEnumerable<SvgElement>,
IEnumerable<SvgElement>> inFunc)
{
List<Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>>> results = new();

foreach (var selector in listSelector)
{
results.Add(GetFunc(selector, ops, null));
}

return f =>
{
var svgElements = inFunc(f);
var nodes = results[0](svgElements);
for (int i = 1; i < results.Count; i++)
{
nodes = nodes.Union(results[i](svgElements));
}

return nodes;
};
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
PseudoClassSelector selector,
ExSvgElementOps ops,
Func<IEnumerable<SvgElement>,
IEnumerable<SvgElement>> inFunc)
{
Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> pseudoFunc;
if (selector.Class == PseudoClassNames.FirstChild)
{
pseudoFunc = ops.FirstChild();
}
else if (selector.Class == PseudoClassNames.LastChild)
{
pseudoFunc = ops.LastChild();
}
else if (selector.Class == PseudoClassNames.Empty)
{
pseudoFunc = ops.Empty();
}
else if (selector.Class == PseudoClassNames.OnlyChild)
{
pseudoFunc = ops.OnlyChild();
}
else if (selector.Class == PseudoClassNames.Hover)
{
// Currently no Hover Property exists in SvgElement so ignoring it now and returning empty
pseudoFunc = ops.Empty();
}
else
{
if (selector.Class.StartsWith(PseudoClassNames.Not))
{
var sel = selector.Class.Substring(PseudoClassNames.Not.Length + 1, selector.Class.Length - 2 - PseudoClassNames.Not.Length);
var parser = new StylesheetParser(true, true, tolerateInvalidValues: true);
var styleSheet = parser.Parse(sel);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excss does not fully parse the not pseudofunc so I have to parse it myself here.

var newSelector = styleSheet.StyleRules.First().Selector;
var func = GetFunc(newSelector, ops, ops.Universal());
var descendants = ops.Descendant();
var func1 = func;
func = f => func1(descendants(f));
HashSet<SvgElement> notElements = null;

pseudoFunc = f => f.Where(e =>
{
notElements ??= func(f).ToHashSet();
return !notElements.Contains(e);
});
}
else if (selector.Class.StartsWith(PseudoClassNames.Lang))
{
// Currently no Language Property exists in SvgElement so ignoring it now and returning empty
pseudoFunc = ops.Empty();
}
else if (selector.Class.StartsWith(PseudoClassNames.Root))
{
pseudoFunc = ops.Root();
}
else
{
throw new NotImplementedException();
}
}

if (inFunc == null)
{
return pseudoFunc;
}

return f => pseudoFunc(inFunc(f));
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(
ComplexSelector selector,
ExSvgElementOps ops,
Func<IEnumerable<SvgElement>,
IEnumerable<SvgElement>> inFunc)
{
List<Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>>> results = new();


foreach (var it in selector)
{
results.Add(GetFunc(it.Selector, ops, null));

Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> combinatorFunc;
if (it.Delimiter == Combinator.Child.Delimiter)
{
combinatorFunc = ops.Child();
}
else if (it.Delimiter == Combinators.Descendent)
{
combinatorFunc = ops.Descendant();
}
else if (it.Delimiter == Combinator.Deep.Delimiter)
{
throw new NotImplementedException();
}
else if (it.Delimiter == Combinators.Adjacent)
{
combinatorFunc = ops.Adjacent();
}
else if (it.Delimiter == Combinators.Sibling)
{
combinatorFunc = ops.GeneralSibling();
}
else if (it.Delimiter == Combinators.Pipe)
{
// Namespace
throw new NotImplementedException();
}
else if (it.Delimiter == Combinators.Column)
{
throw new NotImplementedException();
}
else if (it.Delimiter == null)
{
combinatorFunc = null;
}
else
{
throw new NotImplementedException();
}

if (combinatorFunc != null)
{
results.Add(combinatorFunc);
}
}

Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> result = inFunc;
foreach (var it in results)
{
if (result == null)
{
result = it;
}
else
{
var temp = result;
result = f => it(temp(f));
}
}

return result;
}

private static Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> GetFunc(ISelector selector, ExSvgElementOps ops, Func<IEnumerable<SvgElement>, IEnumerable<SvgElement>> inFunc)
{
var func = selector switch
{
AllSelector allSelector => ops.Universal(),
AttrAvailableSelector attrAvailableSelector => ops.AttributeExists(attrAvailableSelector.Attribute),
AttrBeginsSelector attrBeginsSelector => ops.AttributePrefixMatch(attrBeginsSelector.Attribute, attrBeginsSelector.Value),
AttrContainsSelector attrContainsSelector => ops.AttributeSubstring(attrContainsSelector.Attribute, attrContainsSelector.Value),
AttrEndsSelector attrEndsSelector => ops.AttributeSuffixMatch(attrEndsSelector.Attribute, attrEndsSelector.Value),
AttrHyphenSelector attrHyphenSelector => ops.AttributeDashMatch(attrHyphenSelector.Attribute, attrHyphenSelector.Value),
AttrListSelector attrListSelector => ops.AttributeIncludes(attrListSelector.Attribute, attrListSelector.Value),
AttrMatchSelector attrMatchSelector => ops.AttributeExact(attrMatchSelector.Attribute, attrMatchSelector.Value),
AttrNotMatchSelector attrNotMatchSelector => ops.AttributeNotMatch(attrNotMatchSelector.Attribute, attrNotMatchSelector.Value),
ClassSelector classSelector => ops.Class(classSelector.Class),
ComplexSelector complexSelector => GetFunc(complexSelector, ops, inFunc),
CompoundSelector compoundSelector => GetFunc(compoundSelector, ops, inFunc),
FirstChildSelector firstChildSelector => GetFunc(firstChildSelector, ops),
LastChildSelector lastChildSelector => GetFunc(lastChildSelector, ops),
FirstColumnSelector firstColumnSelector => throw new NotImplementedException(),
LastColumnSelector lastColumnSelector => throw new NotImplementedException(),
FirstTypeSelector firstTypeSelector => GetFunc(firstTypeSelector, ops),
LastTypeSelector lastTypeSelector => GetFunc(lastTypeSelector, ops),
ChildSelector childSelector => ops.Child(),
ListSelector listSelector => GetFunc(listSelector, ops, inFunc),
NamespaceSelector namespaceSelector => throw new NotImplementedException(),
PseudoClassSelector pseudoClassSelector => GetFunc(pseudoClassSelector, ops, inFunc),
PseudoElementSelector pseudoElementSelector => throw new NotImplementedException(),
TypeSelector typeSelector => ops.Type(typeSelector.Name),
UnknownSelector unknownSelector => throw new NotImplementedException(),
IdSelector idSelector => ops.Id(idSelector.Id),
PageSelector pageSelector => throw new NotImplementedException(),
_ => throw new NotImplementedException(),
};

if (inFunc == null)
{
return func;
}

return f => func(inFunc(f));
}

#if NETSTANDARD2_0 || NET462_OR_GREATER
private static HashSet<T> ToHashSet<T>(this IEnumerable<T> enumarable)
{
var result = new HashSet<T>();
foreach (var it in enumarable)
{
result.Add(it);
}

return result;
}
#endif

public static int GetSpecificity(this ISelector selector)
{
var specificity = 0x0;
// ID selector
specificity |= (1 << 12) * selector.Specificity.Ids;
// class selector
specificity |= (1 << 8) * selector.Specificity.Classes;
// element selector
specificity |= (1 << 4) * selector.Specificity.Tags;
return specificity;
}
}
}
Loading