Title: [284143] trunk/Source
Revision
284143
Author
[email protected]
Date
2021-10-13 19:12:31 -0700 (Wed, 13 Oct 2021)

Log Message

Scroll To Text Fragment directive parsing
https://bugs.webkit.org/show_bug.cgi?id=231410

Reviewed by Chris Dumez.

Text directive parsing for
https://wicg.github.io/scroll-to-text-fragment/
Source/WebCore:

Make a new class to handle the parsing of the text directive.
The parsing is defined in the linked spec.
The directive should be stored on Document and in a future
patch the matching algorithm will find the text and scroll
and highlight it.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* dom/Document.h:
(WebCore::Document::setFragmentDirective):
(WebCore::Document::fragmentDirective const):
* dom/FragmentDirectiveParser.cpp: Added.
(WebCore::FragmentDirectiveParser::create):
(WebCore::FragmentDirectiveParser::FragmentDirectiveParser):
(WebCore::FragmentDirectiveParser::parseFragmentDirective):
* dom/FragmentDirectiveParser.h: Added.
(WebCore::FragmentDirectiveParser::parsedTextDirectives):
(WebCore::FragmentDirectiveParser::fragmentDirective):
(WebCore::FragmentDirectiveParser::urlFragment):
(WebCore::FragmentDirectiveParser::isValid):
* page/FrameView.cpp:
(WebCore::FrameView::scrollToFragment):
* platform/Logging.h:

Source/WTF:

* Scripts/Preferences/WebPreferencesExperimental.yaml:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (284142 => 284143)


--- trunk/Source/WTF/ChangeLog	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WTF/ChangeLog	2021-10-14 02:12:31 UTC (rev 284143)
@@ -1,3 +1,15 @@
+2021-10-13  Megan Gardner  <[email protected]>
+
+        Scroll To Text Fragment directive parsing
+        https://bugs.webkit.org/show_bug.cgi?id=231410
+
+        Reviewed by Chris Dumez.
+
+        Text directive parsing for 
+        https://wicg.github.io/scroll-to-text-fragment/
+
+        * Scripts/Preferences/WebPreferencesExperimental.yaml:
+
 2021-10-13  Chris Dumez  <[email protected]>
 
         Drop makeWeakPtr() and use WeakPtr { } directly

Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml (284142 => 284143)


--- trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml	2021-10-14 02:12:31 UTC (rev 284143)
@@ -1153,6 +1153,18 @@
       default: false
     WebCore:
       default: false
+      
+ScrollToTextFragmentEnabled:
+  type: bool
+  humanReadableName: "Scroll To Text Fragment"
+  humanReadableDescription: "Enable Scroll To Text Fragment"
+  defaultValue:
+    WebKitLegacy:
+      default: false
+    WebKit:
+      default: false
+    WebCore:
+      default: false
 
 ServerTimingEnabled:
   type: bool

Modified: trunk/Source/WebCore/ChangeLog (284142 => 284143)


--- trunk/Source/WebCore/ChangeLog	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/ChangeLog	2021-10-14 02:12:31 UTC (rev 284143)
@@ -1,3 +1,37 @@
+2021-10-13  Megan Gardner  <[email protected]>
+
+        Scroll To Text Fragment directive parsing
+        https://bugs.webkit.org/show_bug.cgi?id=231410
+
+        Reviewed by Chris Dumez.
+
+        Text directive parsing for 
+        https://wicg.github.io/scroll-to-text-fragment/
+ 
+        Make a new class to handle the parsing of the text directive.
+        The parsing is defined in the linked spec. 
+        The directive should be stored on Document and in a future
+        patch the matching algorithm will find the text and scroll
+        and highlight it.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * dom/Document.h:
+        (WebCore::Document::setFragmentDirective):
+        (WebCore::Document::fragmentDirective const):
+        * dom/FragmentDirectiveParser.cpp: Added.
+        (WebCore::FragmentDirectiveParser::create):
+        (WebCore::FragmentDirectiveParser::FragmentDirectiveParser):
+        (WebCore::FragmentDirectiveParser::parseFragmentDirective):
+        * dom/FragmentDirectiveParser.h: Added.
+        (WebCore::FragmentDirectiveParser::parsedTextDirectives):
+        (WebCore::FragmentDirectiveParser::fragmentDirective):
+        (WebCore::FragmentDirectiveParser::urlFragment):
+        (WebCore::FragmentDirectiveParser::isValid):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::scrollToFragment):
+        * platform/Logging.h:
+
 2021-10-13  Chris Dumez  <[email protected]>
 
         Drop makeWeakPtr() and use WeakPtr { } directly

Modified: trunk/Source/WebCore/Sources.txt (284142 => 284143)


--- trunk/Source/WebCore/Sources.txt	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/Sources.txt	2021-10-14 02:12:31 UTC (rev 284143)
@@ -921,6 +921,7 @@
 dom/ExtensionStyleSheets.cpp
 dom/FocusEvent.cpp
 dom/FormDataEvent.cpp
+dom/FragmentDirectiveParser.cpp
 dom/FullscreenManager.cpp
 dom/GCReachableRef.cpp
 dom/HashChangeEvent.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (284142 => 284143)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-10-14 02:12:31 UTC (rev 284143)
@@ -8442,6 +8442,8 @@
 		443F04260E75C8FB007E5407 /* NetworkStateNotifierIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkStateNotifierIOS.mm; sourceTree = "<group>"; };
 		444D4E210F708B2E003158E0 /* WebCoreURLResponseIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponseIOS.mm; sourceTree = "<group>"; };
 		445210DD25D61EFF003A2ED8 /* AppHighlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppHighlight.h; sourceTree = "<group>"; };
+		445612AA270F6F3700758C97 /* FragmentDirectiveParser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FragmentDirectiveParser.cpp; sourceTree = "<group>"; };
+		445612AB270F6F3800758C97 /* FragmentDirectiveParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FragmentDirectiveParser.h; sourceTree = "<group>"; };
 		445775E420472F73008DCE5D /* LocalDefaultSystemAppearance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalDefaultSystemAppearance.h; sourceTree = "<group>"; };
 		445775E92047303B008DCE5D /* LocalDefaultSystemAppearance.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalDefaultSystemAppearance.mm; sourceTree = "<group>"; };
 		446DC64624A29D9B0061F390 /* PlaybackTargetClientContextIdentifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlaybackTargetClientContextIdentifier.h; sourceTree = "<group>"; };
@@ -30690,6 +30692,8 @@
 				2A66439126A006AF00C147A1 /* FormDataEvent.cpp */,
 				2A66439026A006AF00C147A1 /* FormDataEvent.h */,
 				2A66438E26A006AE00C147A1 /* FormDataEvent.idl */,
+				445612AA270F6F3700758C97 /* FragmentDirectiveParser.cpp */,
+				445612AB270F6F3800758C97 /* FragmentDirectiveParser.h */,
 				A853123C11D0471B00D4D077 /* FragmentScriptingPermission.h */,
 				CD92F5172261038200F87BB3 /* FullscreenManager.cpp */,
 				CD92F5162261038200F87BB3 /* FullscreenManager.h */,

Modified: trunk/Source/WebCore/dom/Document.h (284142 => 284143)


--- trunk/Source/WebCore/dom/Document.h	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/dom/Document.h	2021-10-14 02:12:31 UTC (rev 284143)
@@ -1639,6 +1639,9 @@
     const Editor& editor() const { return m_editor; }
     FrameSelection& selection() { return m_selection; }
     const FrameSelection& selection() const { return m_selection; }
+        
+    void setFragmentDirective(const String& fragmentDirective) { m_fragmentDirective = fragmentDirective; }
+    const String& fragmentDirective() const { return m_fragmentDirective; }
 
     void prepareCanvasesForDisplayIfNeeded();
     void clearCanvasPreparation(HTMLCanvasElement&);
@@ -2234,6 +2237,8 @@
 
     UniqueRef<Editor> m_editor;
     UniqueRef<FrameSelection> m_selection;
+        
+    String m_fragmentDirective;
 
     ListHashSet<Ref<Element>> m_topLayerElements;
     UniqueRef<WhitespaceCache> m_whitespaceCache;

Added: trunk/Source/WebCore/dom/FragmentDirectiveParser.cpp (0 => 284143)


--- trunk/Source/WebCore/dom/FragmentDirectiveParser.cpp	                        (rev 0)
+++ trunk/Source/WebCore/dom/FragmentDirectiveParser.cpp	2021-10-14 02:12:31 UTC (rev 284143)
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FragmentDirectiveParser.h"
+
+#include "Logging.h"
+#include <wtf/URL.h>
+#include <wtf/text/TextStream.h>
+
+
+namespace WebCore {
+
+FragmentDirectiveParser::FragmentDirectiveParser(const URL& url)
+{
+    ASCIILiteral fragmentDirectiveDelimiter = ":~:"_s;
+    auto fragmentIdentifier = url.fragmentIdentifier();
+    
+    if (fragmentIdentifier.isEmpty()) {
+        m_remainingURLFragment = fragmentIdentifier;
+        return;
+    }
+        
+    auto fragmentDirectiveStart = fragmentIdentifier.find(StringView(fragmentDirectiveDelimiter));
+    
+    if (fragmentDirectiveStart == notFound) {
+        m_remainingURLFragment = fragmentIdentifier;
+        return;
+    }
+    
+    auto fragmentDirective = fragmentIdentifier.substring(fragmentDirectiveStart + fragmentDirectiveDelimiter.length());
+    
+    // FIXME: this needs to be set on the original URL
+    m_remainingURLFragment = fragmentIdentifier.left(fragmentDirectiveStart);
+    
+    parseFragmentDirective(fragmentDirective);
+    
+    m_fragmentDirective = fragmentDirective.toString();
+    m_isValid = true;
+}
+
+void FragmentDirectiveParser::parseFragmentDirective(StringView fragmentDirective)
+{
+    LOG_WITH_STREAM(TextFragment, stream << " parseFragmentDirective: ");
+    
+    Vector<ParsedTextDirective> parsedTextDirectives;
+    String textDirectivePrefix = "text="_s;
+
+    auto directives = fragmentDirective.split('&');
+    
+    LOG_WITH_STREAM(TextFragment, stream << " parseFragmentDirective: ");
+    
+    for (auto directive : directives) {
+        if (!directive.startsWith(textDirectivePrefix))
+            continue;
+        
+        auto textDirective = directive.substring(textDirectivePrefix.length());
+        
+        Deque<String> tokens;
+        bool containsEmptyToken = false;
+        for (auto token : textDirective.split(',')) {
+            if (token.isEmpty()) {
+                LOG_WITH_STREAM(TextFragment, stream << " empty token ");
+                containsEmptyToken = true;
+                break;
+            }
+            tokens.append(token.toString());
+        }
+        if (containsEmptyToken)
+            continue;
+        // FIXME: add decoding for % encoded strings.
+        if (tokens.size() > 4 || tokens.size() < 1) {
+            LOG_WITH_STREAM(TextFragment, stream << " wrong number of tokens ");
+            continue;
+        }
+        
+        ParsedTextDirective parsedTextDirective;
+        
+        if (tokens.first().endsWith('-') && tokens.first().length() > 1) {
+            tokens.first().truncate(tokens.first().length() - 2);
+            parsedTextDirective.prefix = tokens.first();
+            tokens.removeFirst();
+        }
+        
+        if (tokens.last().startsWith('-') && tokens.last().length() > 1) {
+            tokens.last().remove(0);
+            parsedTextDirective.suffix = tokens.takeLast();
+        }
+        
+        if (tokens.size() != 1 && tokens.size() != 2) {
+            LOG_WITH_STREAM(TextFragment, stream << " not enough tokens ");
+            continue;
+        }
+        
+        parsedTextDirective.textStart = tokens.first();
+        
+        if (tokens.size() == 2)
+            parsedTextDirective.textEnd = tokens.last();
+        
+        parsedTextDirectives.append(parsedTextDirective);
+    }
+    
+    m_parsedTextDirectives = parsedTextDirectives;
+}
+
+} // namespace WebCore

Added: trunk/Source/WebCore/dom/FragmentDirectiveParser.h (0 => 284143)


--- trunk/Source/WebCore/dom/FragmentDirectiveParser.h	                        (rev 0)
+++ trunk/Source/WebCore/dom/FragmentDirectiveParser.h	2021-10-14 02:12:31 UTC (rev 284143)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+struct ParsedTextDirective {
+    String textStart;
+    String textEnd;
+    String prefix;
+    String suffix;
+};
+
+class FragmentDirectiveParser {
+public:
+    explicit FragmentDirectiveParser(const URL&);
+    
+    const Vector<ParsedTextDirective>& parsedTextDirectives() const { return m_parsedTextDirectives; };
+    StringView fragmentDirective() const { return m_fragmentDirective; };
+    StringView remainingURLFragment() const { return m_remainingURLFragment; };
+    bool isValid() const { return  m_isValid; };
+    
+private:
+    FragmentDirectiveParser() = delete;
+    void parseFragmentDirective(StringView);
+    
+    Vector<ParsedTextDirective> m_parsedTextDirectives;
+    StringView m_remainingURLFragment;
+    StringView m_fragmentDirective;
+    bool m_isValid { false };
+};
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/page/FrameView.cpp (284142 => 284143)


--- trunk/Source/WebCore/page/FrameView.cpp	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/page/FrameView.cpp	2021-10-14 02:12:31 UTC (rev 284143)
@@ -47,6 +47,7 @@
 #include "EventNames.h"
 #include "FloatRect.h"
 #include "FocusController.h"
+#include "FragmentDirectiveParser.h"
 #include "Frame.h"
 #include "FrameFlattening.h"
 #include "FrameLoader.h"
@@ -2216,7 +2217,25 @@
 
 bool FrameView::scrollToFragment(const URL& url)
 {
+    ASSERT(frame().document());
+    Ref document = *frame().document();
+    
     auto fragmentIdentifier = url.fragmentIdentifier();
+    
+    if (document->settings().scrollToTextFragmentEnabled()) {
+        FragmentDirectiveParser fragmentDirectiveParser(url);
+        
+        if (fragmentDirectiveParser.isValid()) {
+            auto fragmentDirective = fragmentDirectiveParser.fragmentDirective().toString();
+            document->setFragmentDirective(fragmentDirective);
+            
+            auto parsedTextDirectives = fragmentDirectiveParser.parsedTextDirectives();
+            // FIXME: Scroll to the range specified by the directive.
+            
+        } else
+            fragmentIdentifier = fragmentDirectiveParser.remainingURLFragment();
+    }
+    
     if (scrollToFragmentInternal(fragmentIdentifier))
         return true;
 

Modified: trunk/Source/WebCore/platform/Logging.h (284142 => 284143)


--- trunk/Source/WebCore/platform/Logging.h	2021-10-14 01:46:22 UTC (rev 284142)
+++ trunk/Source/WebCore/platform/Logging.h	2021-10-14 02:12:31 UTC (rev 284143)
@@ -115,6 +115,7 @@
     M(StyleSheets) \
     M(SVG) \
     M(TextAutosizing) \
+    M(TextFragment) \
     M(TextShaping) \
     M(Tiling) \
     M(Threading) \
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to