Giter Site home page Giter Site logo

scroll-to-text-fragment's Introduction

Text Fragments

Draft Spec
Web Platform Tests
ChromeStatus entry

Introduction

To enable users to easily link to specific content in a web page, we propose adding support for specifying a text snippet in the URL. When navigating to such a URL, the browser understands more precisely what the user is interested in on the destination page. It may then provide an improved experience, for example: visually emphasizing the text or automatically bringing it into view or allowing the user to jump directly to it.

Web standards currently specify support for scrolling to anchor elements with name attributes, as well as DOM elements with ids, when navigating to a fragment. While named anchors and elements with ids enable scrolling to limited specific parts of web pages, not all documents make use of these elements, and not all parts of pages are addressable by named anchors or elements with ids.

Current Status

This feature, as currently specified in this repo, is shipping to stable channel in Chrome M80.

Motivating Use Cases

When following a link to read a specific part of a web page, finding the relevant part of the document after navigating can be cumbersome. This is especially true on mobile devices, where it can be difficult to find specific content when scrolling through long pages or using the browser's "find in page" feature. Fewer than 1% of clients use the "Find in Page" feature in Chrome on Android.

To enable users to more quickly find the content they're interested in, we propose generalizing the existing support for scrolling to elements based on the fragment identifier. We believe this capability could be used by a variety of websites (e.g. search engine results pages, Wikipedia reference links), as well as by end users when sharing links from a browser.

Search Engines

Search engines, which link to pages that contain content relevant to user queries, would benefit from being able to scroll users directly to the part of the page most relevant to their query.

For example, Google Search currently links to named anchors and elements with ids when they are available. For the query "lincoln gettysburg address sources", Google Search provides a link to the named anchor #Lincoln’s_sources for the wikipedia page for Gettysburg Address as a "Jump to" link:

Example "Jump to" link in search results

However, there are many pages with relevant passages with no named anchor or id, and search engines cannot provide a "Jump to" link in such cases.

Citations / Reference links

Links are sometimes used as citations in web pages where the author wishes to substantiate a claim by referencing another page (e.g. references in Wikipedia). These reference pages can often be large, so finding the exact passage that supports the claim can be very time consuming. By linking to the passage that supports their underlying claim, authors can make it more efficient for readers to follow their overall argument.

Sharing a specific passage in a web page

When referencing a specific section of a web page, for example as part of sharing that content via email or on social media, it is desirable to be able to link directly to the specific section. If a section is not linkable by a named anchor or element with id, it is not currently possible to share a link directly to a specific section.

Users may work around this by sharing screenshots of the relevant portion of the document (preventing the recipient of the content from engaging with the actual web page that hosts the content), or by including extra instructions to scroll to a specific part of the document (e.g. "skip to the sixth paragraph").

We would like to enable users to link to the relevant section of a document directly. Linking directly to the relevant section of a document preserves attribution, and allows the user following the URL to engage directly with the original publisher.

Proposed Solution

tl;dr

Allow specifying text as part of the URL fragment:

https://example.com#:~:text=prefix-,startText,endText,-suffix

Using this syntax

:~:text=[prefix-,]textStart[,textEnd][,-suffix]

         context  |-------match-----|  context

(Square brackets indicate an optional parameter)

Navigating to such a URL will cause the browser to indicate the first instance of the matched text. The exact details of what a browser should do once it finds a match are mostly beyond the scope of this proposal. Browsers are mostly free to choose what kind of UI to surface, whether or not to scroll the text into view on load, and how to visually emphasize it.

To restrict an attacker's ability to exfiltrate information across origins, several restrictions are applied on when such an anchor is activated. A user activation is required and consumed; text matching can only occur on word boundaries. Additionally, the fragment will activate only if the document is sufficiently isolated from other pages (is the only one in its browsing context group, e.g. no window.opener or iframes).

The text directive is delimited from the rest of the fragment using the :~: token to indicate that it is a fragment directive that the user agent should process and then remove from the URL fragment that is exposed to the page. The directive syntax solves the issue of compatibility with page that rely on the URL fragment for routing/state, see issue #15.

Background

We propose generalizing existing support for scrolling to elements as part of a navigation by adding support for specifying a text snippet in the URL. We modify the indicated part of the document processing model to allow using a text snippet as the indicated part. The user agent may then follow the existing logic for scrolling to the fragment identifier and/or apply other UI effects.

This extends the existing support for scrolling to anchor elements with name attributes, as well as DOM elements with ids, to scrolling to other textual content on a web page. Browsers first attempt to find an element that matches the fragment using the existing support for elements with id attributes and anchor elements with name attributes. If no matches are found, browsers then will process the text snippet specification.

Usability Goals

  • Users should be able to specify multiple, non-contiguous passages. There are two reasons this is important. The first is intrinsic; users sometimes want to emphasise multiple snippets of a larger text. Examples abound on Twitter.

    The second is to deal with complicated DOM cases where DOM order and text order doesn't align. A common example would be a column in a table, or a contiguous paragraph with an inline ad.

  • The user may wish to specify text that spans multiple paragraphs, list items, table entries, and other structures. Our proposal aims to allow users to target test crossing arbitrary DOM and visual boundaries.

  • The text the user wishes to target may not be unique on the page. The solution must account for this by providing ways to disambiguate multiple matches on a page.

  • Such links should be creatable for arbitrary pages across the web. This means they must be compatible with the vast majority of existing and future web sites.

Identifying a Text Snippet

Here's an example URL encoding some text to indicate on the destination page:

https://en.wikipedia.org/w/index.php?title=Cat&oldid=916388819#:~:text=Claws-,Like%20almost,the%20Felidae%2C,-cats

:~:text=[prefix-,]textStart[,textEnd][,-suffix]

         context  |-------match-----|  context

(Square brackets indicate an optional parameter)

Though existing HTML support for id and name attributes specifies the target element directly in the fragment, most other mime types make use of this x=y pattern in the fragment, such as Media Fragments (e.g. #track=audio&t=10,20), PDF (e.g. #page=12) or CSV (e.g. #row=4).

The text keyword will be used to identify a block of text that should be indicated. The provided text is percent-decoded before matching. Dash (-), ampersand (&), and comma (,) characters in text snippets must be percent-encoded to avoid being interpreted as part of the text fragment syntax.

The URL standard specifies that a fragment can contain URL code points, as well as UTF-8 percent encoded characters. Characters in the fragment percent encode set must be percent encoded.

There are two kinds of terms specified in the text directive: the match and the context. The match is the portion of text that’s to be indicated. The context is used only to disambiguate the match and is not highlighted.

Context is optional, it need not be provided. However, the text directive must always specify a match term.

Match

A match can be specified as either a single argument or as a pair.

If the match is provided using two arguments, the left argument is considered the starting snippet and the right argument is considered the ending snippet (e.g. text=_startText_,_endText_). In this case, the browser will perform a "range search" for a block of text that starts with startText and ends with endText. If multiple blocks match the first in DOM order is chosen (i.e. find the first occurrence of startText, from there find the first occurrence of endText). When a match is specified with two arguments, we allow highlighting text that spans multiple elements.

If the match is specified as a single argument, we consider it an "exact search" (e.g. text=_textSnippet_). The browser will highlight the first occurrence of exactly the textSnippet string. In this case, the specified text will be matched only if it is contained within a single node.

Range matches are useful when the desired text match is extremely long. For example, selecting multiple paragraphs of text using an exact match would result in a very long and cumbersome URL.

E.g. Given:
  • Text1
  • Text2
  • Text3
  • Text4

text=Text2,Text4 will highlight all items except the first:

  • Text1
  • Text2
  • Text3
  • Text4

text=Text2 will highlight just the second item:

  • Text1
  • Text2
  • Text3
  • Text4

Context

To disambiguate non-unique snippets of text on a page, arguments can specify optional prefix and suffix terms. If provided, the match term will only match text that is immediately preceded by the prefix text and/or immediately followed by the suffix text (allowing for an arbitrary amount of whitespace in between). Immediately preceded, in these cases, means there are no other text nodes between the match and the context term in DOM order. There may be arbitrary whitespace and the context text may be the child of a different element (i.e. searching for context crosses element boundaries).

If provided, the prefix must end (and suffix must begin) with a dash (-) character. This is to disambiguate the prefix and suffix in the presence of optional parameters. It also leaves open the possibility of extending the syntax in the future to allow multiple context terms, allowing more complicated context matching across elements.

If provided, the prefix must be the first argument to the text directive. Similarly, the suffix must be the last argument.

For example, suppose we want to perform the following highlight:

The highlighted text appears multiple times

Since the text “United States” is ambiguous, we must provide a suffix to disambiguate it:

text=United States,-Minnesota Timberwolves

Multiple Text Directives

Users can specify multiple snippets by providing additional text directives in the fragment directive, separated by the ampersand (&) character.

Each text= directive is considered independent in the sense that success or failure to match in one does not affect matching of any others. Each starts searching from the top of the document.

Only the left-most, successfully matched, directive will be the indicated part of the document (i.e. used as the CSS target, scrolled into view). That is, if “foo” did not appear anywhere on the page but “bar” does, we scroll “bar” into view. However, all matched directives will be visually indicated on the page.

For example:
example.com#:~:text=foo&text=bar&text=baz

will target each of “foo”, “bar”, and “baz” and use the “foo” result as the indicated part of the document, assuming all appear on the page.

Multiple terms can be useful when the desired text has unrelated inline elements like images, ads, tables, etc:

Highlighted text has an unrelated table inline

Users may also wish to emphasize multiple passages of a larger text. We've found many such examples online:

Example of an screenshot with multiple highlights

Fragment Directive

Some existing pages on the web use fragments for their own state/routing. These pages may break if an unexpected fragment is provided. See #15

Element-id based fragments also cause these pages to break; however, text fragments are much more likely to be user-generated and are thus more likely to cause unexpected breakage. Pages that rely on fragment routing are also unlikely to provide anchor points, whereas they are likely to have text.

Our solution to this is to introduce the concept of a fragment directive. The fragment directive is a specially-delimited part of the URL fragment that is meant for UA instructions only. It's stripped out from the URL during document loading so that it's completely invisible to the page.

This allows specifying UA instructions like a text fragment in a way that's guaranteed not to interfere with page script and ensures maximal compatibility with the existing web.

However, stripping arbitrary parts of a fragment may not be web compatible! We went through several ideas here:

The Double-Hash

We tried delimiting the fragment directive using ##. It's ergonomic and works well since, if the original URL doesn't have a fragment, the double-hash delimiter will already be parsed as a fragment!

However, # is not a valid code point in the URL spec. As was explained in a thread on the w3.org URI mailing list, some URL parsers parse from right to left. Having an additional # character will cause these parsers to break. Worse, we don't have a good way to measure the risk.

Use counters we added to Chrome in M77 showed that, on Windows, about 0.08% of page loads already have a # character in the fragment. While small, that's a non trivial percentage.

Enter :~:

A new delimiter would have to be both spec-compliant with the URL spec and have sufficiently low usage on the existing web such that this change would be web-compatible.

We assumed this would preclude any single or double character sequences and produced a list of candidates to consider:

  • !~!
  • !~~!
  • ~&~
  • :~:
  • ~@~
  • ~_~
  • _~_

We also considered using a more verbose delimiter:

  • &directive
  • @directive
  • $directive
  • /directive
  • -directive

Looking through links seen in the last 5 years by the Google Search crawler, we eliminated some of this list. None of the "verbose" list had been seen; however, given valid candidates in the first list, we prefered them for succinctness and to reduce English-centric keywords.

Of the above list, the following had never been seen in a URL fragment by the crawler:

  • ~&~ no hits
  • :~: no hits
  • ~@~ one hit

While this doesn't guarantee compatibility, it did give us some confidence. We chose :~: from this list somewhat arbitrarily. However, we've also added Chrome use-counters to M78 for all these delimiters. :~: is seen on fewer than 0.0000039% of page loads (or about 1 in 25 million) so we currently believe this is a safe choice.

Directives and Delimiters

When appending the :~: token to a URL, it must appear inside a fragment so a # must also be added:

https://example.com --> https://example.com#:~:text=foo

However, a URL with an existing fragment can simply be appended to:

https://example.com#fallback:~:text=foo

In this case, if the text match isn't found, the browser can fallback to scrolling the element-id specified in the fragment (e.g. id="fallback" in this case). Note that the text directive will always begin searching at the top of the document, even if a matching element-id fragment is provided.

Compatibility and Interop

User agents that haven't implemented this feature won't know how to process the fragment directive. Because it is part of the fragment, on most pages this will simply be processed as a non-existent fragment so the page will load scrolled to the top, as if a fragment weren't supplied. This is a graceful fallback.

A more risky scenario is apps that use the fragment for state and routing. In these cases, the page is using the fragment in an application-defined manner and adding any content to it impact how the page operates (this is one of the motivating cases for using the fragment delimiter for text=).

In the worst case, such a URL on an unimplementing UA may navigate to a broken page. However, most such pages we've seen handle this gracefully, e.g.:

https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/OOZIrtSPLeM:~:text=test

Is a Google Groups post with a directive appended. Loading it in an unimplementing UA displays an "The input is invalid." toast in the corner but the page otherwise loads as if without the directive. We expect many cases will behave similarly but the potential of more serious breakage does exist.

Note: the fragment directive behavior (stripping everything after and including the :~: delimiter from the fragment) can be implemented independently of the larger proposal.

Feature Detection and Future APIs

An author may wish to detect whether a UA has implemented support for text-fragments. This can be used by pages that generate such links to avoid generating fragment-directives for non-implementing UAs. It can also be used by libraries or authors to strip the fragment-directive from user or author generated links.

This proposal includes a new property on the document object:

document.fragmentDirective

Authors can check for the existence of this (currently empty) object to determine if a UA has implemented support for text-fragments.

This also serves as an extension point for future APIs. For example, we'd like to expose information about the text-fragments included in the URL so that authors can build functionality on it. See #128 for more details.

:target

For element-id based fragments (e.g. https://en.wikipedia.org/wiki/Cat#References), navigation causes the identified element to receive the :target CSS pseudo-class. This is a nice feature as it allows the page to add some customized highlighting or styling for an element that’s been targeted. For example, note that navigating to a citation on a Wikipedia page highlights the citation text: https://en.wikipedia.org/w/index.php?title=Cat&direction=prev&oldid=916388819#cite_note-Linaeus1758-1 The :target CSS pseudo-class can only apply to elements whereas a text snippet may only be a portion of the text in a node or span multiple nodes.

The :target pseudo-class is applied to the first common ancestor element that contains all the matching text, for the left-most matching text= directive.

Security Considerations

Some of the more detailed reasoning behind the security decisions is described in our security review doc

If an attacker can detect a side-effect of a successful match, this feature could be used to detect the presence of arbitrary text on the page. For example, if the UA scrolls to the targeted text on navigation, an attacker might be able to determine whether a scroll occurred by listening to network requests or using an IntersectionObserver from an attacker-controlled iframe embedded on the target page.

A related attack is possible if the existence of a match takes significantly more or less work than non-existence. An attacker can navigate to a text fragment directive and time how busy the JS thread is; a high load may imply the existence or non-existence of an arbitrary text snippet. This is a variation of a documented proof-of-concept.

UAs are free to determine how a successfully matched text fragment should be surfaced to the user based on their own assessment of how much risk certain actions present. For example, whether scrolling on navigation is likely to be detectable in enough cases.

To prevent brute force attacks from guessing important words on a page (e.g. passwords, pin codes), matches and prefix/suffix are only matched on word boundaries. E.g. “range” will match in “mountain range” but not in “color orange” nor “forest ranger”.

Word boundaries are simple in languages with spaces but can become more subtle in languages without breaks (e.g. Chinese). A library like ICU provides support for finding word boundaries across all supported languages based on the Unicode Text Segmentation standard. Some browsers already allow word-boundary matching for the window.find API which allows specifying wholeWord as an argument. We hope this existing usage can be leveraged in the same way.

Additionally, a text directive is invoked only if a user activation occurred and the loaded document is the only one in its browsing context group. The latter restriction is effectively requiring rel=noopener be specified on a navigation.

Visual emphasis is performed using a visual-only indicator (i.e. don’t cause selection), styled by the UA and undetectable from script. This helps prevents drag-and-drop or copy-paste attacks.

Client-Side Redirects

Due to the prevelance of client-side redirects (i.e. loading a document that navigates via e.g. window.location), special care is taken to enable these scenarios, despite the fact they lack a user activation. See redirects.md for details.

Opting Out

For product reasons, or acute privacy restrictions, pages may wish to disallow scrolling to a text fragment (or regular fragment) on load, see #80. To allow websites to opt out of text fragments, we propose adding a Document Policy named force-load-at-top that ensures the page is loaded without any form of scrolling, including via text fragments, regular element fragments, and scroll restoration. Websites can use this document policy by serving the HTTP header:

Document-Policy: force-load-at-top

Alternatives Considered

Text Fragment Directive 0.1

A prior revision of this document contained a somewhat similar proposal. The main difference in the updated proposal is that it adds context terms to the text directive. This helps to allow disambiguating text on a page as well as brings this proposal more in-line with the Open Annotation's TextQuoteSelector. Many use cases and details were considered while iterating on the initial revision. The updated proposal is a sum of lessons learned and improved understanding as we experimented with and considered the initial version and its limitations

CSS Selector Fragments

Our initial idea, explored in some detail, was to allow encoding a CSS selector in the URL fragment. The selector would determine which element on the page should be the "indicated element" in the navigating to a fragment steps. In fact, this explainer is based on @bryanmcquade's original CSS Selector Fragment explainer.

The main drawback with this approach was making it secure. Allowing scroll on load to a CSS selector allows several ways an attacker could exfiltrate hidden information (e.g. CSRF tokens) from the page. One such attack is demonstrated here but others were quickly discovered as well.

Trying to pare down the allowable set of primitives to make selectors secure turned out to be quite complex. Text snippets, which can be searched asynchronously and are generally less security sensitive, became our preferred solution. As an additional bonus, we expect text snippets to be more stable and easier to understand by non-technical users.

Increase use of elements with named anchors / id attributes in existing web pages

As an alternative, we could ask web developers to include additional named anchor tags in their pages, and reference those new anchors. There are two issues that make this less appealing. First, legacy content on the web won’t get updated, but users consuming that legacy content could still benefit from this feature. Second, it is difficult for web developers to reason about all of the possible points other sites might want to scroll to in their pages. Thus, to be most useful, we prefer a solution that supports scrolling to any point in a web page.

JavaScript-based API (instead of URL fragment)

We also considered specifying the target element via a JavaScript-based navigation API, such as via a new parameter to location.assign(). It was concluded that such an API is less useful, as it can only be used in contexts where JavaScript is available. Sharing a link to a specific part of a document is one use case that would not be possible if the target element was specified via a JavaScript API. Using a JavaScript API is also less consistent than existing cases where a scroll target is specified in a URL, such as the existing support in HTML, as well as support for other document formats such as PDF and CSV.

Future Work

One important use case that's not covered by this proposal is being able to scroll to an image. A nearby text snippet can be used to scroll to the image but it depends on the page and is indirect. We'd eventually like to support this use case more directly.

A potential option is to consider this just one of many available Open Annotation selectors. Future specification and implementation work could allow using selectors other than TextQuote to allow targetting various kinds of content.

Another avenue of exploration is allowing users to specify highlighting in more detail. There are also cases where the user may wish to prevent highlights altogether, as in the image search case described above.

We've thought about these cases insofar as making sure our proposed solution doesn't preclude these enhancements in the future. However, the work of actually realizing them will be left for future iterations of this effort.

Additional Considerations

Constructing Arguments to Text Fragments

We imagine URLs with text fragment directives to primarily be machine-generated rather than crafted by hand by users. At the same time, we believe there's a benefit to keeping the URL relatively human-readable: in most cases, simply copying and pasting the desired passage should generate a text fragment directive that will scroll and highlight the desired passage.

The two systems that we believe will generate the bulk of such URLs are browsers and search engines. We forsee users selecting text from the browser, with an option to "share a link to here". These links can then be shared further as wikipedia reference links or over channels like social media or email.

Search engines can also generate text directive URLs as links to search results for user queries; these links may scroll to and highlight relevant passages to the user's query. Note that even though using the selected text as the textStart argument to the text directive may work reasonably well in practice as a heuristic, generating URLs targetting arbitrary text requires access to the full document text up to the desired text. Both browsers and search engines have access to the entire visible text of the page, so it is indeed possible for these systems to generate proper URLs with text directive arguments that scroll and highlight any arbitrary text.

Web and Browser Compatibility

As noted in issue #15, web pages could potentially be using the fragment to store parameters, e.g. http://example.com/#name=test. If sites don't handle unexpected tokens when processing the fragment, this feature could break those sites. In particular, some frameworks use the fragment for routing. This is solved by the user agent hiding the :~:text part of the fragment from the site, but browsers that do not have this feature implemented would still break such sites.

For pages that don't process the fragment, a browser that doesn't yet support this feature will attempt to process the fragment and fragment directive (i.e. :~:text) using the existing logic to find a potential indicated element. If a fragment exists in the URL alongside the fragment directive, the browser may not scroll to the desired fragment due to the confusion with parsing the fragment directive. If a fragment does not exist alongside the fragment directive, the browser will just load the page and won't initiate any scrolling. In either case, the browser will just fall back to the default behavior of not scrolling the document.

Relation to existing support for navigating to a fragment

Browsers currently support scrolling to elements with ids, as well as anchor elements with name attributes. This proposal is intended to extend this existing support, to allow navigating to additional parts of a document. As Shaun Inman notes (in support of CSS selector fragments), this feature is "not meant to replace more concise, author-designed urls" using id attributes, but rather "enables a site’s users to address specific sub-content that the site’s author may not have anticipated as being interesting".

Related Work / Additional Resources

Using CSS Selectors as Fragment Identifiers

Simon St. Laurent and Eric Meyer proposed using CSS Selectors as fragment identifiers (last updated in 2012). Their proposal differs only in syntax used: St. Laurent and Meyer proposed specifying the CSS selector using a #css(...) syntax, for example #css(.myclass). This syntax is based on the XML Pointer Language (XPointer) Framework, an "extensible system for XML addressing" ... "intended to be used as a basis for fragment identifiers". XPointer does not appear to be supported by commonly used browsers, so we have elected to not depend on it in this proposal.

Shaun Inman and others later implemented browser extensions using this #css() syntax for Firefox, Safari, Chrome, and Opera, which shows that it is possible to implement this feature across a variety of browsers.

The Open Annotation Community Group aims to allow annotating arbitrary content. There is significant overlap in our goal of specifying a snippet of text in a resource. In fact, they've already specified a TextQuoteSelector for similar purposes.

This proposal has been made similar to the TextQuoteSelector in hopes that we can extend and reuse that processing model rather than inventing a new one, albeit with a stripped down syntax for ease of use in a URL. Our work has been informed specifically by prior efforts at selecting arbitrary textual content for an annotation.

Scroll Anchoring

Scroll to text

Other

Acknowledgements

Many people have contributed greatly to the ideas and content in this repo, both through excellent work on linking to text as well as direct feedback and comments in issues on this repo which helped to improve this feature. In particular, we'd like to thank:

  • @BigBlueHat
  • Ivan Herman
  • Randall Leeds
  • Kevin Marks
  • Isiah Meadows
  • Wes Turner
  • Dan Whaley
  • Gerben
  • And many others who've provided comments, questions, examples, and opinions. Thank you!

scroll-to-text-fragment's People

Contributors

bokand avatar ericlaw1979 avatar flackr avatar foolip avatar gjdubbs avatar grantjwang avatar harshkapadia2 avatar nickburris avatar nschonni avatar onishi-kohei avatar prayagverma avatar romain-gaillard avatar sideshowbarker avatar tomayac avatar treora avatar yoavweiss avatar yummybacon5 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scroll-to-text-fragment's Issues

Clarify how scroll to fragment is performed

https://wicg.github.io/ScrollToTextFragment/#navigating-to-text-fragment defers to HTML5 in order to perform the scroll to the fragment.

https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-the-fragment-identifier assumes that the indicated part of the document is an Element and then defers to CSSOMView.
However, https://wicg.github.io/ScrollToTextFragment/#find-a-target-text returns a Range.

Maybe what is wanted instead is to rely on window.find() but this is not standardized. See whatwg/html#3539

Support the fragmention syntax as fallback

Thank you for your link to Fragmention, and I appreciate the work here. As discussed in the original fragmention post linking by cited text is very resilient.

Have you looked at supporting the Fragmention model as a fallback - ie not requiring #targetText= as a prefix, but if there are multiple space separated words in the fragment, doing a search for them? (after any other special fragment resolution code runs).

Proposed solution makes link rot problem worse; points to non-navigational parts

The proposed scroll to text fragment URLs will be even more prone to link rot than normal links already are. In the case of normal (fragment) links, the owner of the webpage is in control of which fragments are available. When changing the page, they could to the diligent work and make sure all the expected links work as intended and either provide the original information, or a suggestion where the information has moved.

With the proposed solution, this is not the case - the proposed fragment links point to an arbitrary part of the webpage where the owner of the website has no idea these links even exist so there is no way the owner can keep the links working.

In the example:
www.example.com#targetText=the%20lazy%20dog,brown%20fox

Would match "The lazy dog jumped over the quick brown fox". However, if the owner of the site decided to add another snippit of text ("the lazy dog has a brown coat, and it looks just like a brown fox") that also matches the targetText, the link would be invalid and would actually point to another part of the document not intended by the link.

In the example pointing to PDF pages, audio tracks etc:
The difference with links in media fragments and PDFs, is that in those cases, the underlying content is a lot less likely to change. Links to a specific page number, track or row are all pointing to a part of the document or media that are already numbered. These numbers are already there with the intent of allowing (human) navigation to them, so it would stand to reason that linking to them would also be a good idea. Text passages in a web page are not intended as part of the navigational structure of the page, which makes linking to them unexpected behaviour.

tl;dr:

  • linking should point to things that are part of the navigational structure. This makes it OK to point to chapters, pages, sections, rows etc, but not OK to link to fragments of text.
  • the owner of a page should have control on what links "work" on that page. This ensures that they have the ability to make changes to the page without breaking any links to the page.

Add formal conformance/writing requirements for web developers

You have the most important part, the URL record and the parsing modifications. This is all browsers need. But it's also important to update the definition of a URL for web developers, in https://url.spec.whatwg.org/#url-writing

Maybe nothing changes in that section actually, since the same set of strings is valid before and after?

However, it may be good to have a section describing, in a similar rigorous fashion, the validity of the targetText directive in particular. Some of this is done informally in https://wicg.github.io/ScrollToTextFragment/#syntax. Such a section would probably end up in HTML (or wherever the actual targetText directive is defined), instead of being part of the general URL infrastructure.

Add recommendation in spec for UAs that generate :~:text= links

We should add some guidelines/recommendations to the spec for best-practices around generating :~:text= links. We shouldn't make these MUST statements since UAs should be free to experiment and iterate on how they generate links, so long as they conform to the specified syntax; however, having some guide-rails will help ensure a basic level of user friendliness.

Some examples:

  • Stripping fragment-ids from the URL before appending a :~:text= directive. This could be done optionally, if the element fragment has been scrolled far enough off-screen
  • Guidelines around when to prefer including the entire snippet vs. range-based
  • How/When to use context terms

Editorial: increase the number of cross-links

It'd make the spec easier to read if there were a liberal sprinkling of cross links to relevant concepts. For example:

  • Lots of Infra concepts are used. Although it's less important to link to basic things like "string starts with" or "remove from a list" or similar, some of the stuff around position variables would be helpful.
  • "Find an exact match with context" is italicized, not linked
  • "Each document has an associated fragment directive" should have a <dfn>, and further references should link to it. Similarly for URL record.
  • References to "c" in the URL parser should go to https://url.spec.whatwg.org/#c

One heuristic is that you seem to have italicized a lot of things that should be links. Maybe do an audit of all your italicizations.

XPointer Framework syntaxt *style* fragments

Thinking through the "mixing with SPA's" issue in #15, I wonder if the XPointer Framework syntax's style might be useful to avoid collisions and enable "mixing."

We used this approach in the Web Annotation WG's Selectors and States note. The same syntax style can be seen in SVG's fragment identifiers like #svgView()

This style is less frequently used (other than the standardized ones like svgView()) by JS developers building SPAs. Additionally, these can more easily accommodate mixing and more clearly be "functional"--which avoids confusion between which client this fragment was intended for (the browser or the Web app).

For example using find() rather than targetText= avoids collision with site key/value pairs while also feeling more functional/active.

http://example.com/spa#page_id=5&find("on sale")

Structuring the URL has the interesting side-effect that when the location.hash is parsed (sans-#) with URLSearchParams the results shake out into two groups:

  • the key/value pairs (i.e. page_id=5)
  • the non-key/value pairs (i.e. find("on sale")):

Current JS demo below....

let u = new URL('http://example.com/#page_id=5&find("on sale")');
let usp = new URLSearchParams(u.hash.substr(1));
for (let p of usp.entries()) console.log(p);
# Array [ "page_id", "5" ]
# Array [ "find(\"on sale\")", ""]

This avoids "magic strings" (like targetText) polluting the key space, while still making these easily shimmable via JS.

Additionally, once there is a find() (or targetText() or selector() or whatever) these could be gleaned by the browser engine (possibly removing it from the hash) and kept for its own use--while still following existing URL design and extensibility patterns.

It would also open the door to a more extensible space and patterns for future development, by suggesting that # values may be & delimited and may contain "functional fragments" which may be ignored or implemented by the client (whether browser or Web app).

Thoughts?

Unified syntax for URL and selector fragment identifier?

Just a thought quickly typed down—could the idea to also use CSS for fragment identifiers be merged with this draft?

What about, already buying into the name change suggestion in #25, providing for both

  • ##target=prefix-,startText,endText,-suffix and
  • ##target(selector)?

This may be reasonably clear and allow for maximum flexibility. A quick thought.

[Spec] Don't restrict unknown directives

In Fragment Directive Grammar we have:

FragmentDirective ::= (TextDirective | UnknownDirective) ("&" FragmentDirective)?
UnknownDirective ::= CharacterString
CharacterString ::= (ExplicitChar | PercentEncodedChar)+
ExplicitChar ::= [a-zA-Z0-9] | "!" | "$" | "'" | "(" | ")" | "*" | "+" | "." | "/" | ":" | ";" | "=" | "?" | "@" | "_" | "~"

With the note: "A ExplicitChar may be any URL code point that is not explicitly used in the TextDirective syntax, that is "&", "-", and ",", which must be percent-encoded."

I believe this implies that we're placing the percent-encode restrictions from the text= directive on any potential future directives. I think we should make it clear that UnknownDirective doesn't require percent encoding "-" or ",".

How to deal with text that's initially hidden

To give an example, see any mobile Wikipedia page: e.g. https://en.m.wikipedia.org/wiki/Cat.

Sections after the first one start off in collapsed headings. The text is available in the DOM but isn't displayed to the user unless they expand the relevant section.

These features are author-coded and there's no way in general to detect this case or have the browser automatically expand/display the section. I think there's just 2 options here:

  1. Ignore text that's in a display:none subtree or hidden obscured/clipped out (this could be done with IntersectionObserver)
  2. Allow pages to account for this and automatically expand/display any targeted text. In the example above, Wikipedia automatically expands sections that are linked using an element-id hash: e.g. https://en.m.wikipedia.org/wiki/Cat#Senses.

Option 1 seems unsatisfying so I think we should pursue 2. The most straightforward way would be to apply the CSS :target pseudo-class. This ties in with issue #1 which proposes target-within since we cannot apply a pseudo-class to text.

Fix fragility

The proposed kind of URIs is fragile. It can be broken by minor changes in text. It would cause dead links.

The proposed solution:

  1. require a mandatory fallback id of the immediate parent element. Treat links without it as ordinary links. Search only inside of that element for performance optimization. Use parent element id as a fallback when the match is not found.

  2. introduce fuzzy searches, for example some limited language-morphology based regex, fuzzy hash or even sentence embedding vector.

`##text=` instead of `##targetText=` ?

I understand the desire to avoid clashing with existing ids, but it seems like the ## delimiter handles that problem already.

##text= seems just as clear and a lot briefer, which is important in URLs.

Prevent invocation from popup

For security, we want to avoid invoking the text directive on windows that can be scripted by another origin. It was pointed out in w3ctag/design-reviews#392 (comment) that our current set of restrictions doesn't work in all cases, an attacker could:

  • Top-Level window A1 Opens a popup A2
  • popup A2 navigates A1 to V with :~:text

Since V is top-level and has no opener, origin A is now able to cause text directive invocations in V which is bad because it persists past the navigation.

Add opt-in/opt-out mechanism

As shown in #76 and #79, there are ways to leak information across origins due to the initial scroll. They rely on specific circumstances on a page so they aren't general but they are possible so we should consider ways to mitigate them.

I think it'd be useful to add a mechanism for a page to opt out of fragment navigation. i.e. Guarantee it'll load at the initial scroll offset. This can opt-out of element-id and name based fragments as well, which are susceptible to the same issues.

IMHO, it'd also be reasonable for UAs to weigh the trade-offs differently so I'd like to explore adding an auto|on|off switch. By default (auto), the UA can decide whether or not to scroll into view. "On" would be a signal that the page has explicitly deemed it ok to scroll on load and allow all UAs to scroll to a fragment whereas "off" would block all UAs from scrolling into view.

The highlights themselves, if implemented according to spec, aren't detectable by pages so I think this opt-in/out need only apply to the scrolling aspect.

A meta tag seems like a good start to me but I'm open to alternatives. e.g.

<meta name="allow-navigation-scroll" content="auto|block|allow">

Proposal: restrict matches to not span containment elements

As currently specified, it appears a text fragment identifier can match elements across a very wide swath of DOM, including the entire document, in one match. WICG/display-locking#125 on the display locking repo gives a real-world example where the match is very broad.

That issue also describes why this is a problem for semantics and usability of the beforematch event. It may also be a usability issue of scroll to text fragment, because the scroll will not show the entire match.

I propose that text fragment identifiers not be allowed to cross elements with contain: style layout. This specific restriction is chosen to match semantics of subtree-visibility, and resolve WICG/display-locking#125. Additional restrictions for other types of layout may be appropriate as well.

/cc @bokand @nickburris

--

One potential concern was raised by @vmpstr when discussing this proposal offline, which is that a site could "opt out" of scroll to text fragment by putting every word in a contain: style layout div. However, I don't think this is a significant problem because (a) I don't think it's a problem to worry about if sites go out of their way to avoid text fragments via extreme hacks, and (b) the site will have poor performance and layout behavior if they attempt it.

Searching inside specific element

The current spec supports fallback syntax, like #comments:~:word. The string word is searched on the whole page and if not found, the browser will fallback to the regular id #comments.

I think we should consider another approach if not done yet. We could search inside the element matched by the regular id fragment (here #comments) instead of the whole page. The fallback would be unchanged, the whole element.

Targeting text that spans an element boundary

From the find a target text algorithm steps (section 2.4.3), it seems as though the TreeWalker is used to iterate over text nodes and the search is performed on their innerText. This seems to mean that no direct search for text that spans an element boundary would ever match.

The easiest way to address this would be to say that this is intentional and that any such match should use a range fragment, specifying the start and end text.

There are maybe other ways to address it, but I think that they immediately bring complications with the innerText algorithm.

"all of the visible text on the page"

This is not sufficiently well-defined.

Maybe this is intentional, and we mean to use similar user-agent discretion as is done for find-in-page, which has some per-UA heuristics. But I'll provide some advice assuming the desire is complete interoperability.

Here are some potential axes which need to be considered:

  • textContent-style vs. innerText-style. textContent is essentially the raw text node content, whereas innerText does a variety of styling-derived transformations, e.g. CSS uppercasing translates to uppercase characters, hiding things with CSS removes them from the text, <br>s and other linebreaks become \n, and so on.

  • Does this search inside shadow trees, or only the light DOM? Probably it should, although this means that existing definitions are not going to be helpful and we'll need to create our own.

  • Similarly, do we use DOM order or flat tree order? This is primarily impacted by shadow DOM slotting.

If you have some thoughts on the answers that would be most useful here, I can try to give some guidance on how to precisely define this. Also, if there are other subtleties to consider, that'd be good to know; the above is just off the top of my head.

Is there any way to only target headers and not content?

I couldn't tell you how many times I had to say "Click this page and scroll to X" because there was no way to select a header and get its click ID. Prior to Markdown and related tools, having IDs for headers was exceedingly rare, and it still is fairly uncommon on blog posts to convert headers into anchors.

It'd be nice to be able to search only by header, and most of the time that's all I would want to search.

What if you want to select the nth occurrence of text?

If the page has more than one instance of text, it might be useful to select a particular occurrence of text. For example, you might have a page structure like this (pretend each of these are headers, where indentation signifies hierarchy):

  • Product 1
    • Description
    • Parts included
    • Reviews
  • Product 2
    • Description
    • Parts included
    • Reviews
  • Product 3
    • Description
    • Parts included
    • Reviews

Now suppose you want to link the parts included within Product 2 to someone. How would you do that, rather than accidentally linking "Parts included" for Product 1?

Why reinvent the wheel?

All browsers already have the ability to find and/or highlight multiple iterations of a text phrase via their search functions.
Why not simply have the browser recognise the URL tag as a request for page search, using it's internal search function, with an iteration identifier?
e.g. #search=Phrase%to%find,3

The long phrase search would be more practical by simply adding a 'searchEnd' option that includes the iteration variable thus also enabling provision to allow for multiple iterations to be highlighted.
e.g. #search=Phrase%to%find,3,searchEnd=end%phrase.,3
or
#search=Phrase%to%find,3,searchEnd=end%phrase.,4

Possibly include a forced highlight option that overrides the browser's setting:
e.g. #search=Phrase%to%find,3,h

Far simpler, usable and easily memorable than all of that 'targetX' nonsense, and doesn't break if it's not the first iteration you want to link to.

I'm honestly surprised there's been coding time given to implement this using such easily broken methodology...

I'm sure there will be instances of conflicts with '#search', so have it substitute with '#search1' if a conflict arises.

As stated in other feedback, there is still the issue with page edits breaking links.
So while imperfect, a simple link to 'x% of page vertical pixels' may prove to be a more reliable solution.
e.g. #vertPct=42
A highlight option could be provided by specifying two percentages.
e.g. #vertPct=42,45

An included value for aspect ratio could be used to work around layout differences.
Certainly simpler to implement and continues to work at least with some degree of accuracy regardless of changes to the page content.

Don't break the hash

Disclaimer: it's WIP issue, I will update it later, it's not finished, just sketching some ideas.

Hash is already defined and we don't want to break it. As mentioned in the readme, there might be a collision with ids and routes in SPAs. So, while I like the goal, I don't really like breaking compatibility.

Potential solutions:

  1. HTML attribute. We already have HTML attributes for <a href="..."> to tell the browser how to open the page. For example, we have target=_blank, rel=noopener and others. So, let's create a new attribute, let it be target-text="...". So, one would use it like this:
    <a href="https://example.com" target-text="text to highlight">Link</a>
    It will allow us to send links wherever we can use HTML: in emails, chats, or in search engine results.
    But this solution will not allow to open URLs with highlights from other programs, outside of the browser, I think.
  2. Another URI scheme. We have a lot of URI schemes. Probably, most known is mailto: and Chrome is able to handle it perfectly, to open gmail whenever I click on it. So, why don't we create a new URI sceme, which will be something like this (similar to Magnet URI):
    targetTextOnPage:?targetText=text to highlight&url=https://example.com
    Which will open https://example.com and highlight text to highlight. Spaces probably should be URL-encoded, doesn't really matter right now.
    But this solution don't have a fallback. So, if user with old system clicks on that "magnet" link, it won't open nothing.

Side notes:

  • [ and ] are reserved gen-delims (src) and still are not used, I think. So, probably we can do https://example.com/page#header[text to highlight]
  • css selectors are not stable, especially because of complicated building proccess of modern web apps that use minification and obfuscation to prevent parsing, so it's not a good option.

P.S. While it's still WIP, let me know what you think about it.

Specify behavior on hidden and display:none text

The behavior we've found useful is that visibility:hidden or display:none text that we find in the DOM should be matched but not scrolled into view. That way, if the page makes it visible after load it is indicated.

One use case we're thinking of here is mobile Wikipedia. If the link has a classic element-id fragment so that it expands a section based on page script, we want the highlight to still appear. In these cases, we don't want to scroll-into-view though.

We need to make sure this is precisely specified.

Spec source file uses "section autolinks" incorrectly, they'll start breaking

The .bs source uses section autolinks ([[spec#heading-id]]) for a lot of places where it intends to just link to definitions in those specs. This is incorrect markup; if the specs' heading data isn't in Bikeshed, Bikeshed just throws up its hands and assumes you know what you're linking to. (Which means that the links are fragile/unsafe, with no guarantee that the ID exists at all in the destination document.)

However, these specs were in Bikeshed, I just wasn't processing the spec names properly; now that I've fixed that, Bikeshed is (correctly) reporting that those IDs don't correspond to any headings in the spec, and no longer generating a link. The next time you (or your CI) generates the spec, you'll get a number of fatal errors, and the output will lose several links.

Please replace these with proper autolinks, such as [=term here=] or {{Foo/method()}}: see https://tabatkins.github.io/bikeshed/#autolink-microsyntax for guidance on syntax, or feel free to contact me in IRC at Freenode#whatwg or W3C#css.

privacy concerns with proposal through inducing network requests

The proposal seems to enable some privacy attacks, by exposing new types of information to new types of observers.

For example: Consider a situation where I can view DNS traffic (e.g. company network), and I send a link to the company health portal, with #:~:text=cancer. On certain page layouts, i might be able tell if the employee has cancer by looking for lower-on-the-page resources being requested

Deter use of this kind of anchors instead of id-based anchors

It is proposed to make this kind of links unworkable for the content within the same page.

Rationale: code-monkeys would abuse it for referencing content in own applications instead of ids. It can cause performance, efficiency and resource consumption problems. But code-monkeys don't care. Unfortunately sometimes even large web resources hire code-monkeys. So the standard should be foolproof.

Integration with W3C Web Annotations

It would be great to be able to comment on the linked resource text fragment. W3C Web Annotations [implementations] don't recognize the targetText parameter, so AFAIU comments are then added to the document#fragment and not the specified text fragment.

I see that W3C Web Annotation Data Model is linked to under 'Other'.

https://hypothes.is , for example, implements W3C Web Annotations for highlighting and commenting on lots of things; including text fragments. WA is a JSONLD spec: it's definitely possible to encode JSONLD in a URI fragment. urlencoded without newlines is easy, if maybe unnecessarily verbose.

WA already solves for referencing in-page images and things; but hasn't (yet?) defined a IRI fragment syntax.

Is there a simplified mapping of W3C Web Annotations to URI fragment parameters?

https://www.w3.org/TR/2017/REC-annotation-model-20170223/#bodies-and-targets

https://www.w3.org/TR/annotation-model/#bodies-and-targets

https://www.w3.org/TR/annotation-model/#embedded-textual-body

https://www.w3.org/TR/annotation-model/#css-selector (CSS Selector)

https://www.w3.org/TR/annotation-model/#xpath-selector (XPath Selector)

Target JavaScript generated content

User might share content that is generated by JavaScript.
How would targetText target/scrollTo text that isn't yet painted or is painted after some delay?

"Increment c"?

Increment c by the length of the fragment-directive delimiter minus 1.

Nothing in the URL spec increments c. It's unclear what this would mean; c is a character, so is incrementing it by 1 suppose to give the character that's 1 larger in the Unicode code point space?

I suspect you want to "increase pointer by..." which is a phrase that is used elsewhere.

When both fragment and fragment directive are specified, text search should start at the fragment anchor

When both fragment and fragment directive are specified, text search should start at the fragment anchor. Currently, the spec says to completely ignore the fragment in UAs that support text fragments. But it would babe a. useful extra capability in the case of multiple matches, and could allow links to more similar locations in supporting and non-supporting browsers. (Search could wrap to ensure this never entirely misses a text match).

Avoid breaking pages that use the URL fragment for routing/state

Edit: s/client instruction/processing instruction/g


Currently, URIs treat %% as invalid. Should we maybe extend accepted URIs to support this use case using that token, as effectively "processing instructions" (like "scroll to text") rather than necessarily seeing it as a fragment? These "processing instructions" would not be exposed to users, at least initially, and it wouldn't be included in what's sent to servers.

I'm thinking maybe view it as this:

  • https://example.com#!/route%%q=some%20text - Search for some text
  • https://example.com#!/route%%q=some%20text%%n=2 - Search for second occurrence of some text
  • I could see other potential additions like delaying the search (for JS), selecting or filtering by CSS selector, etc.
  • Of course, order doesn't matter. %%q=some%20text%%n=2 and %%n=2%%q=some%20text are equivalent.

Alternatively, you could wrap each "processing instruction" in brackets like [q=some%20text] as suggested in #13, but I feel a double percent sign is probably a little easier to explain and use. (I see potential use in both technical and non-technical circles, so accessibility to non-technical people is a concern of mine.)

This would resolve and/or address numerous existing issues already filed:

  • #2 - This could be as simple as a %%delay=int_ms or %%delay=float_s instruction.
  • #4 - This could be recast as a way to specify Web Annotation "target" selectors, but I don't agree we should be bound to their format - it's a bit more verbose than what's necessary for this. We're just selecting crap, and we could include all their functionality with less boilerplate and more flexibility.
  • #5 - The long prefix is instead a simple %%q=, something even non-technical users could potentially recognize right away due to familiarity with the common convention used by search engines.
  • #7 - This doesn't clash. Problem solved. 😉
  • #8 - This could be as simple as a %%select=div>:nth-child(2)>span.whatever instruction.
  • #9 - This could be as simple as a %%n=int_n instruction, as proposed above. We could also include range support here like 1-3 for first three or similar. (Other concerns like "last 4" or "all but first two" need considered.)
  • #10 - Unintentionally similar to this, but this is a bit more deliberate and focused where that misses the point of the proposal and goes slightly off-topic.
  • #11 - This keeps it inaccessible to CSS, so you can't write complicated selectors to select based on target. This should keep abuse down a bit. (The other complaint of using text instead of IDs is an issue this deliberately shouldn't fix, as a proper fix would interfere with user-level use.)
  • #13 - This is a concrete proposal driven by similar reasons to that issue, but aims to be simpler and more extensible and flexible.

Needs to spec security mitigations

The explainer's Security section discusses several restrictions on the feature; however, they're not mentioned at all in the spec.

At the least, the spec should add some implementer notes around the security issues here but it might make sense to make these normative requirements, given that not implementing them could be harmful to users.

Possible side-channel information leak using IntersectionObserver

If an attacker has an iframe embedded in the victim page, they can determine some information from the victim page across origins. Using an intersection observer, the attacker can determine if the iframe intersects the viewport and use that to guess whether a followed link resolved to the text fragment.

URL API

While these text fragments will often be created by user agents it would be nice to be able to construct these easily in JS so that custom sharing options can be created.

For example Medium does this with selected text:
Screen Shot 2019-12-09 at 6 14 44 pm

It would be nice to be able to do similar with fragment directives using the URL API.

e.g. Example API surface:

const url = new URL(location.href);
url.fragmentDirectives.add('text', window.getSelection().toString());

showShareUrl(url);

Need a way to feature detect

In #15 we're discussing ways to spec the feature such that it doesn't break pages that use the hash fragment for their own purposes. If we succeed in doing that, this means that UAs implementing this feature can follow links with the targetText to pages that would otherwise break with a hand-crafted fragment. The canonical example from that issue is https://www.webmd.com/skin-problems-and-treatments/lice-treatment#anything.

However, this would mean that a page sending a user to https://www.webmd.com/skin-problems-and-treatments/lice-treatment##targetText=sometext will load and work correctly in UAs that support the feature, but completely break the page for UAs that don't.

We should support some method of feature detection so pages can check whether adding a targetText has the potential to break the link and avoid adding it for UAs that don't support it.

Commas in the targetText, and other design issues

What if I want to link to targetText that contains a comma?

What does whitespace mean in targetText? Browsers frequently do not display whitespace the same as the source html, for example \n might be rendered as a space. Or two spaces in the html might be rendered as a single space.

Looks like the web annotation community has already thought about the whitespace issue, here's one example discussion: w3c/web-annotation#221

Specify multiple text directives

We need to specify the parsing and behavior of multiple text directives, where each of the text directives is visually indicated (e.g. highlighted) and the first one that's found is scrolled into view.

location.hash alternative

If we will decide to go with URL-based solution, we should consider adding an alternative to location.hash that will retrieve targetText from the URL.

Initializing the `TreeWalker`

From the find a target text algorithm steps (section 2.4.3), step 13 initializes a TreeWalker but does not specify what the root node or the whatToFind filter should be.

How this affects CSS target pseudo-class :target, propose :target-within

Currently target element https://drafts.csswg.org/selectors-4/#the-target-pseudo is capturable with CSS :target that applies to elements having attribute id.

Since Scroll-To-Text may target text inside element and not directly text,
I recommend to take an example from CSS :focus, :focus-within and to implement a new target pseudo-class :target-within that would capture element within is the targeted text part.

@tabatkins, any suggestions?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.