קישור מודגש במקום שבו אף אחד לא ביצע קישור לפני כן: קטעי טקסט

קטעי טקסט מאפשרים לציין קטע טקסט בקטע של כתובת האתר. כשמנווטים לכתובת URL עם מקטע טקסט כזה, הדפדפן יכול להדגיש ו/או להביא אותה לתשומת הלב של המשתמש.

מזהי מקטעים

Chrome 80 היה הפצה גדולה. הוא כלל כמה תכונות שכולם חיכו להם, כמו ECMAScript Modules in Web Workers , nullish colescing, יצירת שרשור אופציונלי ועוד. ההשקה פורסמה כרגיל באמצעות פוסט בבלוג בבלוג Chromium. אפשר לראות קטע מהפוסט בבלוג בצילום המסך שלמטה.

פוסט בבלוג Chromium עם תיבות אדומות מסביב לאלמנטים עם המאפיין id.

אתם בטח שואלים את עצמכם מה המשמעות של כל התיבות האדומות. הן התוצאה של הרצת קטע הקוד הבא בכלי הפיתוח. היא מדגישה את כל הרכיבים שיש להם מאפיין id.

document.querySelectorAll('[id]').forEach((el) => {
  el.style.border = 'solid 2px red';
});

תודה למזהה המקטע שבו אני משתמש ב-hash של כתובת ה-URL של הדף, כדי למקם קישור עומק לכל אלמנט שמודגש בתיבה אדומה. בהנחה שהייתי רוצה להוסיף קישור עומק לתיבה נשמח לקבל משוב בפורומים של המוצרים שבצד, אפשר לעשות זאת על ידי יצירה ידנית של כתובת ה-URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1. כפי שאפשר לראות בחלונית הרכיבים בכלים למפתחים, לאלמנט הרלוונטי יש מאפיין id עם הערך HTML1.

בכלי הפיתוח מוצגים id של רכיב.

אם מנתחים את כתובת ה-URL הזו באמצעות הבנאי URL() של JavaScript, הרכיבים השונים ייחשפו. שימו לב למאפיין hash עם הערך #HTML1.

new URL('https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1');
/* Creates a new `URL` object
URL {
  hash: "#HTML1"
  host: "blog.chromium.org"
  hostname: "blog.chromium.org"
  href: "https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1"
  origin: "https://blog.chromium.org"
  password: ""
  pathname: "/2019/12/chrome-80-content-indexing-es-modules.html"
  port: ""
  protocol: "https:"
  search: ""
  searchParams: URLSearchParams {}
  username: ""
}
*/

למרות שהייתי צריך לפתוח את הכלים למפתחים כדי למצוא את השדה id של רכיב, אפשר ללמוד על ההסתברות שהמחבר של הפוסט בבלוג קישר את הקטע הספציפי הזה בדף.

מה קורה אם אני רוצה לקשר למשהו בלי id? נניח שאני רוצה לקשר לכותרת ECMAScript Modules in Web Workers (מודולים של ECMAScript in Web Workers). כפי שאפשר לראות בצילום המסך שבהמשך, ל-<h1> הרלוונטי אין מאפיין id, ולכן אין אפשרות לקשר לכותרת הזו. זו הבעיה שקטעי טקסט פותרים.

כלי הפיתוח שמציגים כותרת ללא id.

קטעי טקסט

ההצעה קטעי טקסט מוסיפה תמיכה בהגדרת קטע טקסט בגיבוב של כתובת URL. כשמנווטים לכתובת URL עם מקטע טקסט כזה, סוכן המשתמש יכול להדגיש זאת ו/או להפנות את תשומת ליבו של המשתמש.

תאימות דפדפן

תמיכה בדפדפן

  • 89
  • 89
  • x
  • x

מקור

מטעמי אבטחה, כדי להשתמש בתכונה הזו צריך לפתוח קישורים בהקשר של noopener. לכן, חשוב לכלול את הערך rel="noopener" בתגי העיצוב של מודעות העוגן <a> או להוסיף את noopener לרשימת Window.open() התכונות של פונקציונליות החלון.

start

בצורתו הפשוטה ביותר, התחביר של Text Fragments הוא: סמל הגיבוב # ואחריו :~:text=, ולבסוף start, שמייצג את הטקסט בקידוד אחוזים שאליו רוצים לקשר.

#:~:text=start

לדוגמה, נניח שאני רוצה לקשר אל ECMAScript Modules in Web Workers בפוסט בבלוג שמכריז על תכונות ב-Chrome 80, כתובת ה-URL במקרה הזה תהיה:

https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules%20in%20Web%20Workers

מקטע הטקסט מודגש כך. אם לוחצים על הקישור בדפדפן תומך כמו Chrome, מקטע הטקסט יודגש וגולל לתצוגה:

קטע הטקסט גלל והודגש.

start וגם end

מה קורה אם אני רוצה לקשר את כל הקטע שכותרתו ECMAScript Modules in Web Workers, ולא רק את הכותרת שלו? באמצעות קידוד באחוזים של כל הטקסט בקטע, כתובת ה-URL שתתקבל תהיה ארוכה באופן בלתי מעשי.

למרבה המזל, יש דרך טובה יותר. במקום כל הטקסט, אפשר למסגר את הטקסט הרצוי באמצעות התחביר start,end. לכן, ציינתי כמה מילים מקודדות באחוזים בתחילת הטקסט הרצוי, וכמה מילים מקודדות באחוזים בסוף הטקסט הרצוי, מופרדות בפסיק ,.

כך זה נראה:

https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules%20in%20Web%20Workers,ES%20Modules%20in%20Web%20Workers..

בשביל start, יש לי ECMAScript%20Modules%20in%20Web%20Workers, ואז פסיק , ואחריו ES%20Modules%20in%20Web%20Workers. בתור end. כשלוחצים בדפדפן תומך כמו Chrome, כל הקטע מודגש והוא נגלל לתצוגה:

קטע הטקסט גלל והודגש.

עכשיו יש לך שאלות לגבי start ו-end. למעשה, גם כתובת ה-URL הקצרה (https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers.) שמכילה רק שתי מילים בכל צד הייתה מתאימה. משווים את start ו-end לערכים הקודמים.

אם אקח את זה צעד אחד קדימה, ועכשיו אשתמש במילה אחת בלבד גם ב-start וגם במילה end, תוכלו לראות שאני בצרות. כתובת ה-URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers. קצרה עוד יותר, אבל מקטע הטקסט המודגש כבר לא זהה לכתובת הרצויה. ההדגשה מפסיקה במופע הראשון של המילה Workers., שהיא נכונה, אבל לא מה שהתכוונתי להדגיש. הבעיה היא שהקטע הרצוי לא מזוהה באופן ייחודי באמצעות הערכים start ו-end הנוכחיים, שכוללים רק מילה אחת:

קטע טקסט לא מכוון גלל לתצוגה והודגש.

prefix- וגם -suffix

שימוש בערכים ארוכים מספיק עבור start ו-end הוא פתרון אחד לקבלת קישור ייחודי. עם זאת, במצבים מסוימים אי אפשר לעשות זאת. תזכורת: למה בחרתי את הפוסט בבלוג על גרסה 80 של Chrome כדוגמה? התשובה היא שבמהדורה הזו הצגנו את קטעי הטקסט:

טקסט של הפוסט בבלוג: קטעי טקסט בכתובות URL. משתמשים או מחברים יכולים עכשיו לקשר לחלק ספציפי בדף באמצעות מקטע טקסט שסופק בכתובת URL. כשהדף נטען, הדפדפן מדגיש את הטקסט וגולל את המקטע כדי שהוא יוצג. לדוגמה, כתובת ה-URL שלמטה טוענת דף וויקי עבור &#39;Cat&#39; וגולל אל התוכן שרשום בפרמטר &#39;text&#39;.
קטע פוסט בבלוג של ההודעה לגבי מקטעי טקסט.

שימו לב איך בצילום המסך שמעל המילה "טקסט" מופיעה ארבע פעמים. האירוע הרביעי נכתב בגופן קוד ירוק. כדי לקשר למילה המסוימת הזו, צריך להגדיר את start ל-text. מכיוון שהמילה "text" היא, רק מילה אחת, לא יכול להיות end. מה הלאה? כתובת ה-URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text תואמת למופע הראשון של המילה "Text" (טקסט) שכבר מופיעה בכותרת:

התאמת מקטע טקסט באירוע הראשון של "Text".

למרבה המזל, יש פתרון. במקרים כאלה, אפשר לציין prefix​- וגם -suffix. המילה לפני גופן הקוד הירוק "text" היא "the", והמילה שאחריה היא "parameter". לאף אחד משלושת המופעים האחרים של המילה "טקסט" אין אותן מילים מסביב. בזכות הידע הזה, אני יכול לשנות את כתובת ה-URL הקודמת ולהוסיף את prefix- ואת -suffix. כמו שאר הפרמטרים, גם הם צריכים להיות מקודדים באחוזים ויכולים להכיל יותר ממילה אחת. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter. כדי לאפשר למנתח לזהות בבירור את prefix- ואת -suffix, צריך להפריד ביניהם מה-start ואת ה-end האופציונלי באמצעות מקף -.

התאמת מקטע טקסט באירוע הרצוי של "text".

התחביר המלא

התחביר המלא של מקטעי טקסט מוצג בהמשך. (הסוגריים המרובעים מציינים פרמטר אופציונלי). הערכים של כל הפרמטרים צריכים להיות מקודדים באחוזים. הדבר חשוב במיוחד לתווי מקף -, אמפרסנד & ופסיק ,, כדי שהם לא יפורשו כחלק מהתחביר של כיווני הטקסט.

#:~:text=[prefix-,]start[,end][,-suffix]

כל אחד מ-prefix-, start, end ו--suffix יתאים טקסט רק באלמנט יחיד ברמת הבלוק, אבל טווחים של start,end מלאים יכולים להתפרס על פני מספר בלוקים. לדוגמה, הערך :~:text=The quick,lazy dog לא יתאים בדוגמה הבאה, כי מחרוזת ההתחלה "The Fast" לא מופיעה בתוך רכיב אחד ברמת הבלוק ללא הפרעות:

<div>
  The
  <div></div>
  quick brown fox
</div>
<div>jumped over the lazy dog</div>

עם זאת, הוא תואם בדוגמה הבאה:

<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>

יצירת כתובות URL של קטעי טקסט באמצעות תוסף לדפדפן

קשה ליצור כתובות URL של קטעי טקסט באופן ידני, במיוחד כשמדובר בניסיון לוודא שהן ייחודיות. אם תרצו, תוכלו למצוא במפרט כמה טיפים ופירוט של השלבים המדויקים ליצירת כתובות URL של Text Fragment. אנחנו מספקים תוסף קוד פתוח לדפדפן שנקרא Link to Text Fragment (קישור למקטע טקסט) שמאפשר לקשר לטקסט כלשהו על ידי בחירה בו, ולאחר מכן לחיצה על Copy Link to selected Text (העתקת הקישור לטקסט שנבחר) בתפריט ההקשר. התוסף הזה זמין בדפדפנים הבאים:

קישור אל Text Fragment תוסף לדפדפן.

מספר קטעי טקסט בכתובת URL אחת

חשוב לשים לב שמספר קטעי טקסט יכולים להופיע בכתובת URL אחת. צריך להפריד בין מקטעי הטקסט הספציפיים באמצעות תו אמפרסנד &. הנה קישור לדוגמה עם שלושה קטעי טקסט: https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=Text%20URL%20Fragments&text=text,-parameter&text=:~:text=On%20islands,%20birds%20can%20contribute%20as%20much%20as%2060%25%20of%20a%20cat's%20diet.

שלושה קטעי טקסט בכתובת URL אחת.

שילוב של קטעי טקסט ואלמנטים

אפשר לשלב שברים של רכיבים מסורתיים עם מקטעי טקסט. אפשר בהחלט לכלול את שתיהן באותה כתובת URL, לדוגמה, כדי לספק חלופה משמעותית למקרה שהטקסט המקורי בדף ישתנה, כדי שקטע הטקסט לא יהיה תואם יותר. כתובת ה-URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums. מקשרת אל הקטע נשמח לקבל משוב בפורומים של המוצרים מכילה קטע רכיבים (HTML1) וגם מקטע טקסט (text=Give%20us%20feedback%20in%20our%20Product%20Forums.):

קישור למקטע טקסט וגם למקטע טקסט.

ההנחיה של המקטע

יש רכיב אחד בתחביר שעדיין לא הסברתי: הוראת המקטע :~:. כדי למנוע בעיות תאימות עם מקטעים קיימים של רכיבי כתובת URL כפי שמתואר למעלה, הוספנו את הכיוון של המפרט 'קטעי טקסט'. הוראת המקטע היא חלק מקטע כתובת ה-URL שמופרד על ידי רצף הקוד :~:. הוא שמור להוראות של סוכן משתמש, כמו text=, והוא נמחק מכתובת ה-URL במהלך הטעינה, כדי שסקריפטים של המחבר לא יוכלו לבצע בו פעולות ישירות. ההוראות של סוכן המשתמש נקראות גם הנחיות. במקרה המעשי, text= נקרא הוראת טקסט.

זיהוי תכונות

כדי לזהות תמיכה, צריך לבדוק את המאפיין fragmentDirective לקריאה בלבד ב-document. ההנחיה המקטעת היא מנגנון שמאפשר לכתובות URL לציין הוראות שמפנות לדפדפן במקום למסמך. המטרה היא למנוע אינטראקציה ישירה עם סקריפט של המחבר, כך שנוכל להוסיף בעתיד הוראות לסוכן משתמש בלי לחשוש מהוספת שינויים שעלולים לגרום לכשלים בתוכן קיים. אחת הדוגמאות לתוספות עתידיות כאלה יכולה להיות רמזים לתרגום.

if ('fragmentDirective' in document) {
  // Text Fragments is supported.
}

זיהוי תכונות מיועד בעיקר למקרים שבהם קישורים נוצרים באופן דינמי (למשל על ידי מנועי חיפוש) על מנת למנוע הצגת קישורים עם מקטעים של טקסט לדפדפנים שלא תומכים בהם.

עיצוב מקטעי טקסט

כברירת מחדל, מקטעי הטקסט מעוצבים בדפדפנים באותו אופן שבו הם מעצבים את mark (בדרך כלל שחור על צהוב, צבעי המערכת של CSS עבור mark). גיליון הסגנונות של סוכן המשתמש מכיל CSS שנראה כך:

:root::target-text {
  color: MarkText;
  background: Mark;
}

כמו שאפשר לראות, הדפדפן חושף פסאודו סלקטור ::target-text, שאפשר להשתמש בו כדי להתאים אישית את ההדגשה שהוחלה. לדוגמה, אפשר לעצב את מקטעי הטקסט כטקסט שחור על רקע אדום. כמו תמיד, חשוב לבדוק את ניגודיות הצבעים כדי ששינוי הסגנון לא יגרום לבעיות נגישות, וכדי לוודא שההדגשה בולטת משאר התוכן.

:root::target-text {
  color: black;
  background-color: red;
}

יכולת מילוי רבייה

ניתן למלא במידה מסוימת את התכונה 'קטעי טקסט'. אנחנו מספקים polyfill, שנמצא בשימוש פנימי של התוסף, לדפדפנים שלא מספקים תמיכה מובנית ל-Text Fragments שבהם הפונקציונליות מיושמת ב-JavaScript.

ה-polyfill מכיל קובץ fragment-generation-utils.js שניתן לייבא ולהשתמש בו כדי ליצור קישורים של Text Fragment. תוכלו להיעזר בדוגמת הקוד הבאה:

const { generateFragment } = await import('https://unpkg.com/text-fragments-polyfill/dist/fragment-generation-utils.js');
const result = generateFragment(window.getSelection());
if (result.status === 0) {
  let url = `${location.origin}${location.pathname}${location.search}`;
  const fragment = result.fragment;
  const prefix = fragment.prefix ?
    `${encodeURIComponent(fragment.prefix)}-,` :
    '';
  const suffix = fragment.suffix ?
    `,-${encodeURIComponent(fragment.suffix)}` :
    '';
  const start = encodeURIComponent(fragment.textStart);
  const end = fragment.textEnd ?
    `,${encodeURIComponent(fragment.textEnd)}` :
    '';
  url += `#:~:text=${prefix}${start}${end}${suffix}`;
  console.log(url);
}

קבלת מקטעי טקסט למטרות ניתוח נתונים

הרבה אתרים משתמשים בקטע הניתוב, ולכן הדפדפנים מסירים מקטעי טקסט כדי לא לשבור את הדפים האלה. קיים אישור שצריך לחשוף קישורים למקטעי טקסט לדפים, למשל למטרות ניתוח נתונים, אבל הפתרון המוצע עדיין לא מיושם. כפתרון זמני בשלב זה, תוכלו להשתמש בקוד שבהמשך כדי לחלץ את המידע הרצוי.

new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;

אבטחה

הוראות למקטעי טקסט מופעלות רק בניווטים מלאים (שאינם באותו דף) שנובעים מהפעלת משתמש. בנוסף, כדי להשתמש בניווטים שמגיעים ממקור שונה מהיעד, הניווט יתבצע בהקשר של noopener, כך שיהיה ידוע שדף היעד מבודד מספיק. הוראות למקטעי טקסט חלות רק על המסגרת הראשית. כלומר, לא יתבצע חיפוש של טקסט במסגרות iframe, והניווט ב-iframe לא יפעיל קטע טקסט.

פרטיות

חשוב שהטמעות של מפרט Text Fragments לא ידלפו אם נמצא קטע טקסט בדף או לא. מקטעי טקסט נמצאים בשליטתו המלאה של מחבר הדף המקורי, אבל כל אחד יכול ליצור קטעי טקסט. חשוב לזכור שבדוגמה שלמעלה לא הייתה דרך לקשר את הכותרת ECMAScript Modules in Web Workers, מאחר של-<h1> לא היה id, אבל איך כל אחד, כולל אני, יכול היה פשוט לקשר למקום כלשהו באמצעות בנייה קפדנית של מקטע הטקסט?

נניח שהפעלתי רשת מודעות זדונית evil-ads.example.com. נניח גם שבאחת ממסגרות ה-iframe של המודעות שלי יצרתי באופן דינמי iframe מוסתר ממקורות שונים אל dating.example.com עם כתובת URL של מקטע טקסט dating.example.com#:~:text=Log%20Out, אחרי שהמשתמש יצרו אינטראקציה עם המודעה. אם הטקסט 'התנתקות' נמצא, ברור לי שהקורבן מחובר כרגע ל-dating.example.com, ואני יכול להשתמש בו כדי ליצור פרופיל משתמשים. הטמעה נאיבית של קטעי טקסט עשויה להחליט שהתאמה מוצלחת צריכה לגרום להעברת המיקוד, ולכן במצב evil-ads.example.com יכולתי להאזין לאירוע blur ולדעת מתי התרחשה התאמה. ב-Chrome, הטמענו קטעי טקסט באופן שבו התרחיש שלמעלה לא יכול לקרות.

מתקפה נוספת עלולה להיות ניצול התנועה ברשת על סמך מיקום הגלילה. נניח שהייתה לי גישה ליומני התנועה ברשת של הקורבן שלי, למשל כמנהל/ת רשת אינטראנט של חברה. עכשיו נניח שיש מסמך ארוך של משאבי אנוש What to Do If You Sufer From... ואז רשימה של מצבים כמו שחיקה, חרדה וכו'. אפשר למקם פיקסל למעקב ליד כל פריט ברשימה. אם אגיע למסקנה שטעינת המסמך מתרחשת באופן זמני בזמן הטעינה של פיקסל המעקב לצד הפריט השחיקה, למשל, כאדמין אינטראנט אוכל לקבוע שעובד לחץ על קישור למקטע טקסט עם :~:text=burn%20out שהעובד הניח שהוא סודי ולא גלוי לאף אחד. מכיוון שהדוגמה הזו קצת מובנת בהתחלה, ומכיוון שהניצול של המידע דורש מאוד תנאים מוקדמים ספציפיים, צוות האבטחה של Chrome העריך את הסיכון בהטמעה של גלילה בניווט. סוכני משתמש אחרים יכולים להחליט אם להציג במקום זאת רכיב של גלילה ידנית בממשק המשתמש.

באתרים שרוצים לבטל את ההסכמה לשימוש בהם, Chromium תומך בערך כותרת Document Policy שניתן לשלוח, כדי שסוכני המשתמש לא יעבדו כתובות URL של מקטעי טקסט.

Document-Policy: force-load-at-top

השבתה של קטעי טקסט

הדרך הקלה ביותר להשבית את התכונה היא באמצעות תוסף שיכול להחדיר כותרות של תגובת HTTP, למשל ModHeader (לא מוצר של Google), כדי להוסיף כותרת תגובה (לא בקשה) באופן הבא:

Document-Policy: force-load-at-top

דרך נוספת ומעורבת יותר לבטל את ההסכמה היא באמצעות ההגדרה הארגונית ScrollToTextFragmentEnabled. כדי לעשות את זה ב-macOS, צריך להדביק את הפקודה שלמטה במסוף.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

ב-Windows, עוקבים אחר ההוראות באתר התמיכה של Google Chrome Enterprise.

בחיפושים מסוימים, מנוע החיפוש Google מספק תשובה או סיכום מהירים עם קטע תוכן מאתר רלוונטי. יש את הסיכוי הגבוה ביותר שתקצירי תוצאות החיפוש הראשונות האלה יופיעו כשהחיפוש הוא בצורת שאלה. לחיצה על תקציר תוצאת החיפוש הראשונה מעבירה את המשתמש ישירות אל תקציר תוצאת החיפוש הראשונה בדף האינטרנט של המקור. זה פועל הודות לכתובות URL של מקטעי טקסט שנוצרו באופן אוטומטי.

דף התוצאות של מנוע החיפוש של Google המציג תקציר תוצאת החיפוש הראשונה. בשורת הסטטוס מוצגת כתובת ה-URL של מקטעי הטקסט.
אחרי הלחיצה למעבר, גלילה ומוצגת הקטע הרלוונטי בדף.

סיכום

'כתובת אתר של מקטעי טקסט' היא תכונה יעילה שמאפשרת לקשר לטקסט שרירותי בדפי אינטרנט. הקהילה האקדמית יכולה להשתמש בו כדי לספק קישורים למקורות מידע או ציטוטים ביבליוגרפיים או הפניות מדויקים ביותר. מנועי חיפוש יכולים להשתמש בו כדי ליצור קישור עומק לתוצאות טקסט בדפים. אתרי רשתות חברתיות יכולים להשתמש בו כדי לאפשר למשתמשים לשתף קטעים ספציפיים של דף אינטרנט במקום צילומי מסך שאינם נגישים. אני מקווה שתתחילו להשתמש בכתובות URL של Text Fragment, והן יהיו מועילות כמוני. הקפידו להתקין את תוסף הדפדפן Link to Text Fragment.

אישורים

Text Fragments יושם וסופק על ידי ניק בוריס ודייוויד בוקאן, עם תרומות מאת גרנט וואנג. תודה ל-Joe Medley על הביקורת היסודית של מאמר זה. תמונה ראשית (Hero) מאת Greg Rakozy באתר UnFlood.