DocumentExtensions
Useful methods for document objects.
using AngleSharp.Dom;
using AngleSharp.Dom.Collections;
using AngleSharp.Dom.Html;
using AngleSharp.Network;
using AngleSharp.Services;
using AngleSharp.Services.Media;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AngleSharp.Extensions
{
[DebuggerStepThrough]
internal static class DocumentExtensions
{
public static void ForEachRange(this Document document, Predicate<AngleSharp.Dom.Collections.Range> condition, Action<AngleSharp.Dom.Collections.Range> action)
{
if (document != null) {
foreach (AngleSharp.Dom.Collections.Range range in document.Ranges) {
if (condition(range))
action(range);
}
}
}
public static void AdoptNode(this IDocument document, INode node)
{
Node node2 = node as Node;
if (node2 == null)
throw new DomException(DomError.NotSupported);
if (node2.Parent != null)
node2.Parent.RemoveChild(node2, false);
node2.Owner = (document as Document);
}
public static void QueueTask(this Document document, Action action)
{
IEventService service = document.Options.GetService<IEventService>();
if (service != null)
service.Enqueue(new Task(action));
else
action();
}
public static void QueueTask(this Document document, Task task)
{
IEventService service = document.Options.GetService<IEventService>();
if (service != null)
service.Enqueue(task);
else if (task.Status == TaskStatus.Created) {
task.Start();
}
}
public static async Task SpinLoop(this Document document, Func<bool> predicate)
{
IEventService eventLoop = document.Options.GetService<IEventService>();
if (eventLoop == null) {
while (!predicate()) {
}
} else
await eventLoop.Spin(predicate).ConfigureAwait(false);
}
public static void QueueMutation(this Document document, MutationRecord record)
{
if (document != null) {
MutationObserver[] array = document.Mutations.Observers.ToArray();
if (array.Length != 0) {
IEnumerable<INode> inclusiveAncestors = record.Target.GetInclusiveAncestors();
foreach (MutationObserver mutationObserver in array) {
bool? nullable = null;
foreach (INode item in inclusiveAncestors) {
MutationObserverInit mutationObserverInit = mutationObserver.ResolveOptions(item);
if (mutationObserverInit != null && (item == record.Target || mutationObserverInit.IsObservingSubtree) && (!record.IsAttribute || mutationObserverInit.IsObservingAttributes.Value) && (!record.IsAttribute || mutationObserverInit.AttributeFilters == null || (mutationObserverInit.AttributeFilters.Contains(record.AttributeName) && record.AttributeNamespace == null)) && (!record.IsCharacterData || mutationObserverInit.IsObservingCharacterData.Value) && (!record.IsChildList || mutationObserverInit.IsObservingChildNodes) && (!nullable.HasValue || nullable.Value))
nullable = ((record.IsAttribute && !mutationObserverInit.IsExaminingOldAttributeValue.Value) || (record.IsCharacterData && !mutationObserverInit.IsExaminingOldCharacterData.Value));
}
if (nullable.HasValue)
mutationObserver.Enqueue(record.Copy(nullable.Value));
}
document.PerformMicrotaskCheckpoint();
}
}
}
public static void AddTransientObserver(this Document document, INode node)
{
if (document != null) {
IEnumerable<INode> ancestors = node.GetAncestors();
IEnumerable<MutationObserver> observers = document.Mutations.Observers;
foreach (INode item in ancestors) {
foreach (MutationObserver item2 in observers) {
item2.AddTransient(item, node);
}
}
}
}
public static void ApplyManifest(this Document document)
{
if (document.IsInBrowsingContext) {
IHtmlHtmlElement htmlHtmlElement = document.DocumentElement as IHtmlHtmlElement;
if (htmlHtmlElement != null) {
string manifest = htmlHtmlElement.Manifest;
Predicate<string> predicate = (string str) => false;
if (!string.IsNullOrEmpty(manifest))
predicate(manifest);
}
}
}
public static void PerformMicrotaskCheckpoint(this Document document)
{
document.Mutations.ScheduleCallback();
}
public static void ProvideStableState(this Document document)
{
}
public static bool HasScriptBlockingStyleSheet(this Document document)
{
if (document.IsInBrowsingContext && document.Context.Parent != null) {
Document document2 = document.Context.Parent.Active as Document;
if (document2 != null)
return document2.HasScriptBlockingStyleSheet();
}
return false;
}
public static async Task WaitForReady(this Document document)
{
if (document.HasScriptBlockingStyleSheet() || document.IsWaitingForScript())
await SpinLoop(predicate: delegate {
if (!document.HasScriptBlockingStyleSheet())
return !document.IsWaitingForScript();
return false;
}, document: document).ConfigureAwait(false);
}
public static IBrowsingContext GetTarget(this Document document, string target)
{
if (string.IsNullOrEmpty(target) || target.Equals("_self", StringComparison.Ordinal))
return document.Context;
if (target.Equals("_parent", StringComparison.Ordinal))
return document.Context.Parent ?? document.Context;
if (target.Equals("_top", StringComparison.Ordinal))
return document.Context;
return document.Options.FindContext(target);
}
public static IBrowsingContext CreateTarget(this Document document, string target)
{
Sandboxes security = Sandboxes.None;
if (target.Equals("_blank", StringComparison.Ordinal))
return document.Options.NewContext(security);
return document.NewContext(target, security);
}
public static IBrowsingContext NewContext(this Document document, string name, Sandboxes security)
{
IConfiguration options = document.Options;
IContextService service = options.GetService<IContextService>();
if (service == null)
return new BrowsingContext(document.Context, security);
return service.Create(document.Context, name, security);
}
public static IBrowsingContext NewChildContext(this Document document, Sandboxes security)
{
return document.NewContext(string.Empty, security);
}
public static IWindow CreateWindow(this Document document)
{
IWindowService service = document.Options.GetService<IWindowService>();
if (service == null)
return new Window(document);
return service.Create(document);
}
public static void ReleaseStorageMutex(this Document document)
{
}
public static IResourceLoader CreateLoader(this Document document)
{
return document.Options.GetService<ILoaderService>()?.CreateResourceLoader(document);
}
public static Task<TResource> LoadResource<TResource>(this Document document, ResourceRequest request) where TResource : IResourceInfo
{
IResourceLoader loader = document.Loader;
TResource resource = (TResource)default(TResource);
return document.Tasks.Add(async delegate(CancellationToken cancel) {
IResponse response = await loader.FetchAsync(request, cancel).ConfigureAwait(false);
if (response != null) {
IConfiguration options = document.Options;
IEnumerable<IResourceService<TResource>> resourceServices = ConfigurationExtensions.GetServices<IResourceService<TResource>>(options);
foreach (IResourceService<TResource> item in resourceServices) {
if (item.SupportsType(response.Headers[HeaderNames.ContentType])) {
resource = (TResource)(await item.CreateAsync(response, cancel).ConfigureAwait(false));
break;
}
}
response.Dispose();
}
return (TResource)resource;
});
}
}
}