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

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

מזהי מקטעים

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

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

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

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

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

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

אם אנתח את כתובת ה-URL הזו באמצעות ה-constructor של 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 בכותרת Web Workers. כפי שאפשר לראות בצילום המסך למטה, ה-<h1> הנדון לא יש מאפיין id, כלומר לא ניתן לקשר לכותרת הזו. הבעיה הזו פתרון של מקטעי טקסט.

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

מקטעי טקסט

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

תאימות דפדפן

תמיכה בדפדפן

  • Chrome: 89.
  • קצה: 89.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

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

start

בצורתו הפשוטה ביותר, התחביר של מקטעי טקסט הוא כך: סמל הגיבוב # ואחריו :~: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 ב-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 הוא פתרון אחד לקבלת קישור ייחודי. עם זאת, יש מקרים שבהם הדבר לא אפשרי. בהערה צדדית, למה בחרתי דוגמה לפוסט בבלוג של Chrome 80? התשובה היא שבגרסה הזו, 'קטעי טקסט' הושקו:

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

שימו לב איך בצילום המסך שמעל למילה "text" מופיעה ארבע פעמים. המופע הרביעי הוא כתוב בגופן קוד ירוק. אם אני רוצה לקשר למילה המסוימת הזו, עליי להגדיר 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'. אף אחת מהאפשרויות שלושה מופעים אחרים של המילה "text" כולל את אותן מילים מסביב. מוצמד אני יכול לשנות את כתובת ה-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 Quick" לא מופיעה ברכיב אחד ברמת הבלוקים ללא הפסקות:

<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 של מקטעי טקסט. אנחנו מספקים תוסף קוד פתוח לדפדפן שנקרא קישור לקטע טקסט שמאפשר קישור לטקסט כלשהו על ידי בחירתו ולאחר מכן לחיצה על "העתקת קישור לטקסט שנבחר" בהקשר תפריט תוסף זה זמין בדפדפנים הבאים:

קישור לקטע טקסט לדפדפן.

כמה מקטעי טקסט בכתובת 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 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.):

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

הוראת המקטע

יש רכיב אחד בתחביר שעדיין לא הסברתי: הוראת המקטע :~:. כדי להימנע של בעיות תאימות עם קטעים קיימים של רכיבים בכתובת האתר כפי שמוצג למעלה, המפרט של מקטעי טקסט כולל את המקטע של Google. הוראת המקטע היא חלק ממקטע כתובת האתר שמופרד על ידי רצף הקוד :~: הכתובת הזו שמורה להוראות של סוכן משתמש, כמו 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, המשמש באופן פנימי על ידי התוסף, לדפדפנים שלא לספק תמיכה מובנית בקטעי טקסט שבהם הפונקציונליות מוטמעת ב-JavaScript.

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

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;

אבטחה

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

פרטיות

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

נניח שהפעלתי רשת מודעות זדונית evil-ads.example.com. נסו לדמיין שבאחת מהמודעות שלי iframes יצרתי באופן דינמי 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 Suffer From..., ולאחר מכן רשימה כמו שחיקה, חרדה וכו'. אני יכול למקם פיקסל מעקב ליד כל פריט חדשה. אם לאחר מכן אחליט שטעינת המסמך מתרחשת באופן זמני עם טעינת פיקסל מעקב שלצידו, למשל, הפריט שחיקה, אני יכול, בתור מנהל אינטראנט, לקבוע עובד לחץ על קישור של קטע טקסט עם :~:text=burn%20out, שהעובד עשוי היה להניח שהוא סודי ולא גלוי לאף אחד. מאחר שהדוגמה הזו במידה מסוימת בהתחלה, ומכיוון שהניצול שלו דורש עמידה בתנאים מוקדמים ספציפיים מאוד, צוות האבטחה של Chrome העריך את הסיכון ליישום של גלילה בניווט כך שיהיה אפשר לנהל אותה. סוכני משתמש אחרים יכולים להחליט להציג במקום זאת רכיב בממשק המשתמש של גלילה ידנית.

עבור אתרים שרוצים לבטל את הסכמתם, Chromium תומך מדיניות בנושא מסמכים את ערך הכותרת שהם יכולים לשלוח, כך שסוכני המשתמש לא יעבדו כתובות 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 של מקטעי טקסט' היא תכונה יעילה שמאפשרת לקשר לטקסט שרירותי בדפי אינטרנט. האקדמאי יכולים להשתמש בו כדי לספק ציטוטים או קישורי עזר מדויקים מאוד. מנועי חיפוש יכולים להשתמש כדי לבצע קישור עומק לתוצאות טקסט בדפים. אתרי רשתות חברתיות יכולים להשתמש בו כדי לאפשר למשתמשים לשתף בקטעים ספציפיים של דף אינטרנט ולא בצילומי מסך לא נגישים. אני מקווה שתתחיל שימוש בכתובות URL של קטעי טקסט והם יהיו שימושיים כמוני. חשוב להתקין את הדפדפן קישור ל-Text Fragment לתוסף.

אישורים

התכונה Text Fragments הוטמעה וצוינה על ידי Nick Burris דייוויד בוקאן, עם תרומות מאת גראנט וואנג. תודה לג'ו מדלי על על הסקירה היסודית של מאמר זה. התמונה הראשית (Hero) של גרג ראקוזי בפלטפורמת ביטול הפתיחה.