پیوند جسورانه جایی که قبلاً هیچ کس پیوند نداده است: تکه‌های متن

Text Fragments به شما امکان می دهد یک قطعه متن را در قطعه URL مشخص کنید. هنگام پیمایش به یک URL با چنین قطعه متنی، مرورگر می تواند بر آن تأکید کند و/یا توجه کاربر را جلب کند.

شناسه های قطعه

کروم 80 نسخه بزرگی بود. این شامل تعدادی از ویژگی های بسیار مورد انتظار مانند ماژول های ECMAScript در Web Workers ، ادغام بی اثر ، زنجیره اختیاری ، و موارد دیگر بود. انتشار طبق معمول از طریق یک پست وبلاگ در وبلاگ Chromium اعلام شد. شما می توانید گزیده ای از پست وبلاگ را در تصویر زیر مشاهده کنید.

پست وبلاگ Chromium با کادرهای قرمز رنگ اطراف عناصر با ویژگی id .

احتمالاً از خود می‌پرسید همه جعبه‌های قرمز به چه معنا هستند. آنها نتیجه اجرای قطعه زیر در DevTools هستند. تمام عناصری که دارای ویژگی id هستند را برجسته می کند.

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

به لطف شناسه قطعه که سپس در هش URL صفحه استفاده می کنم، می توانم یک پیوند عمیق به هر عنصری که با کادر قرمز برجسته شده است قرار دهم. با فرض اینکه می‌خواستم پیوند عمیقی به قسمت بازخورد دادن به ما در کادر تالار گفتمان محصولات ما در کناری بگذارم، می‌توانم این کار را با ایجاد URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1 انجام دهم. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1 . همانطور که در پنل عناصر Developer Tools می بینید، عنصر مورد نظر دارای یک ویژگی id با مقدار HTML1 است.

Dev Tools id یک عنصر را نشان می دهد.

اگر این URL را با سازنده URL() جاوا اسکریپت تجزیه کنم، اجزای مختلف آشکار می شوند. به ویژگی 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 نیست، به این معنی که هیچ راهی وجود ندارد که بتوانم به این عنوان پیوند دهم. این مشکلی است که Text Fragments حل می کند.

Dev Tools که عنوانی را بدون id نشان می دهد.

تکه های متن

پیشنهاد Text Fragments پشتیبانی برای مشخص کردن یک قطعه متن در هش URL را اضافه می کند. هنگام پیمایش به یک URL با چنین قطعه متنی، عامل کاربر می تواند بر آن تاکید کند و/یا توجه کاربر را جلب کند.

سازگاری با مرورگر

پشتیبانی مرورگر

  • کروم: 89.
  • لبه: 89.
  • فایرفاکس: 131.
  • پیش نمایش فناوری سافاری: پشتیبانی می شود.

منبع

به دلایل امنیتی ، این ویژگی نیاز دارد که پیوندها در یک زمینه noopener باز شوند. بنابراین، مطمئن شوید که rel="noopener" در <a> anchor markup خود اضافه کنید یا noopener به لیست Window.open() خود از ویژگی های عملکرد پنجره اضافه کنید.

start

در ساده‌ترین شکل آن، نحو قطعات متن به این صورت است: نماد هش # و به دنبال آن :~:text= و در نهایت start ، که نمایانگر متن کدگذاری شده‌ای است که می‌خواهم به آن پیوند دهم.

#:~:text=start

به عنوان مثال، بگویید که می‌خواهم به ماژول‌های ECMAScript در 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 . وقتی روی یک مرورگر پشتیبانی مانند کروم کلیک می‌کنید، کل بخش برجسته می‌شود و برای مشاهده اسکرول می‌شود:

قطعه متن به نمای پیمایش شد و برجسته شد.

اکنون ممکن است در مورد انتخاب من برای 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 استفاده کنم، می بینید که در مشکل هستم. نشانی اینترنتی 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 را به عنوان نمونه انتخاب کردم؟ پاسخ این است که در این نسخه Text Fragments معرفی شدند:

متن پست وبلاگ: تکه های URL متن. کاربران یا نویسندگان اکنون می توانند با استفاده از یک قطعه متن ارائه شده در URL به بخش خاصی از صفحه پیوند دهند. هنگامی که صفحه بارگیری می شود، مرورگر متن را برجسته می کند و قطعه را برای مشاهده اسکرول می کند. به عنوان مثال، URL زیر صفحه ویکی «Cat» را بارگیری می کند و به محتوای فهرست شده در پارامتر «متن» پیمایش می کند.
گزیده پست وبلاگ اعلام تکه های متن.

توجه کنید که چگونه در تصویر بالای صفحه کلمه "متن" چهار بار ظاهر می شود. رخداد چهارم با فونت کد سبز نوشته شده است. اگر بخواهم به این کلمه خاص پیوند دهم، start به text تنظیم می کنم. از آنجایی که کلمه "متن" فقط یک کلمه است، end وجود ندارد. حالا چی؟ نشانی وب https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #:~:text=text با اولین تکرار کلمه "Text" در حال حاضر مطابقت دارد عنوان:

تطبیق قطعه متن در اولین رخداد "متن".

خوشبختانه راه حلی وجود دارد. در مواردی مانند این، من می توانم یک prefix​- و یک -suffix مشخص کنم. کلمه قبل از فونت کد سبز "text" "the" و کلمه بعد "پارامتر" است. هیچ یک از سه رخداد دیگر کلمه "متن" کلمات اطراف یکسانی ندارند. با داشتن این دانش، می‌توانم 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 Fragments در زیر نشان داده شده است. (براکت های مربع یک پارامتر اختیاری را نشان می دهد.) مقادیر همه پارامترها باید به صورت درصد رمزگذاری شوند. این به ویژه برای نویسه‌های خط - ، علامت & علامت , و ویرگول مهم است، بنابراین آنها به عنوان بخشی از نحو دستور متن تفسیر نمی‌شوند.

#:~: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 های قطعه متن را فهرست می کند. ما یک افزونه مرورگر منبع باز به نام 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 داشته باشید، به عنوان مثال، برای ارائه یک بازگشت معنی دار در صورت تغییر متن اصلی در صفحه، به طوری که قطعه متن دیگر مطابقت نداشته باشد. نشانی وب 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 ). شیوه نامه user-agent حاوی CSS است که به شکل زیر است:

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

همانطور که می بینید، مرورگر یک شبه انتخابگر ::target-text را نشان می دهد که می توانید از آن برای سفارشی کردن برجسته سازی اعمال شده استفاده کنید. به عنوان مثال، می توانید قطعات متن خود را به صورت متن سیاه روی پس زمینه قرمز طراحی کنید. مثل همیشه، حتما کنتراست رنگ را بررسی کنید تا استایل نادیده گرفته شده شما باعث مشکلات دسترسی نشود و مطمئن شوید که هایلایت واقعاً از نظر بصری از بقیه محتوا متمایز است.

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

قابلیت چندپر شدن

ویژگی Text Fragments را می توان تا حدی چند پر کرد. ما یک polyfill ارائه می دهیم که به صورت داخلی توسط برنامه افزودنی استفاده می شود، برای مرورگرهایی که پشتیبانی داخلی برای قطعات متنی که در جاوا اسکریپت اجرا می شود، ارائه نمی دهند.

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 قطعه متنی را فراخوانی نخواهد کرد.

حریم خصوصی

مهم است که پیاده‌سازی‌های مشخصات قطعات متنی درز نکنند، چه قطعه متنی در یک صفحه یافت شود یا نه. در حالی که قطعات عنصر به طور کامل تحت کنترل نویسنده اصلی صفحه هستند، قطعات متنی می تواند توسط هر کسی ایجاد شود. به یاد داشته باشید که چگونه در مثال بالا من هیچ راهی برای پیوند دادن به ماژول های ECMAScript در عنوان 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 گوش دهم و بنابراین بدانم چه زمانی تطابق رخ داده است. در کروم، تکست فرگمنت ها را به گونه ای پیاده سازی کرده ایم که سناریوی بالا نمی تواند اتفاق بیفتد.

حمله دیگر ممکن است سوء استفاده از ترافیک شبکه بر اساس موقعیت اسکرول باشد. فرض کنید من به گزارش‌های ترافیک شبکه قربانیم دسترسی داشتم، مثلاً به عنوان مدیر اینترانت شرکت. حالا تصور کنید که یک سند طولانی منابع انسانی وجود دارد که اگر از آن رنج می‌برید چه باید کرد... و سپس فهرستی از شرایطی مانند فرسودگی ، اضطراب ، و غیره وجود داشت. من می‌توانم یک پیکسل ردیابی را در کنار هر مورد در لیست قرار دهم. سپس اگر تشخیص دهم که بارگیری سند به طور موقت با بارگذاری پیکسل ردیابی در کنار، مثلاً مورد سوخته شده، همزمان اتفاق می افتد، می توانم به عنوان سرپرست اینترانت تعیین کنم که یک کارمند روی پیوند قطعه متن کلیک کرده است. با :~:text=burn%20out که ممکن است کارمند فرض کرده باشد محرمانه بوده و برای کسی قابل مشاهده نیست. از آنجایی که این مثال برای شروع تا حدی ساختگی است و از آنجایی که بهره برداری از آن نیازمند پیش شرط های بسیار خاصی است، تیم امنیتی Chrome خطر پیاده سازی اسکرول در ناوبری را به عنوان قابل مدیریت ارزیابی کرد. سایر عوامل کاربر ممکن است تصمیم بگیرند به جای آن یک عنصر اسکرول دستی UI را نشان دهند.

برای سایت‌هایی که می‌خواهند انصراف دهند، Chromium از مقدار سرصفحه خط‌مشی سند پشتیبانی می‌کند که می‌توانند آن را ارسال کنند تا نمایندگان کاربر نشانی‌های وب قطعه متن را پردازش نکنند.

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 Help را دنبال کنید.

برای برخی از جستجوها، موتور جستجوی گوگل پاسخ یا خلاصه ای سریع با یک قطعه محتوا از یک وب سایت مرتبط ارائه می دهد. این قطعه‌های برجسته به احتمال زیاد زمانی که جستجو در قالب یک سؤال است نشان داده می‌شوند. با کلیک بر روی یک قطعه برجسته، کاربر مستقیماً به متن قطعه برجسته در صفحه وب منبع می‌رود. این به لطف URL های قطعه متنی ایجاد شده به طور خودکار کار می کند.

صفحه نتایج موتور جستجوی گوگل که یک قطعه برجسته را نشان می دهد. نوار وضعیت نشانی وب قسمت‌های متن را نشان می‌دهد.
پس از کلیک کردن، بخش مربوطه از صفحه به نمایش اسکرول می شود.

نتیجه گیری

URL Fragments متن یک ویژگی قدرتمند برای پیوند دادن به متن دلخواه در صفحات وب است. جامعه علمی می تواند از آن برای ارائه پیوندهای استنادی یا مرجع بسیار دقیق استفاده کند. موتورهای جستجو می توانند از آن برای پیوند عمیق به نتایج متنی در صفحات استفاده کنند. سایت‌های شبکه‌های اجتماعی می‌توانند از آن استفاده کنند تا به کاربران اجازه دهند بخش‌های خاصی از یک صفحه وب را به‌جای اسکرین‌شات‌های غیرقابل دسترس به اشتراک بگذارند. امیدوارم شروع به استفاده از URL های تکست فرگمنت کنید و آنها را مانند من مفید بیابید. پسوند مرورگر Link to Text Fragment را حتما نصب کنید.

قدردانی

تکست فرگمنت ها توسط نیک بوریس و دیوید بوکان و با مشارکت گرانت وانگ پیاده سازی و مشخص شد. با تشکر از جو مدلی برای بررسی کامل این مقاله. تصویر قهرمان توسط گرگ راکوزی در Unsplash .

،

Text Fragments به شما امکان می دهد یک قطعه متن را در قطعه URL مشخص کنید. هنگام پیمایش به یک URL با چنین قطعه متنی، مرورگر می تواند بر آن تأکید کند و/یا توجه کاربر را جلب کند.

شناسه های قطعه

کروم 80 نسخه بزرگی بود. این شامل تعدادی از ویژگی های بسیار مورد انتظار مانند ماژول های ECMAScript در Web Workers ، ادغام بی اثر ، زنجیره اختیاری ، و موارد دیگر بود. انتشار طبق معمول از طریق یک پست وبلاگ در وبلاگ Chromium اعلام شد. شما می توانید گزیده ای از پست وبلاگ را در تصویر زیر مشاهده کنید.

پست وبلاگ Chromium با کادرهای قرمز رنگ اطراف عناصر با ویژگی id .

احتمالاً از خود می‌پرسید همه جعبه‌های قرمز به چه معنا هستند. آنها نتیجه اجرای قطعه زیر در DevTools هستند. تمام عناصری که دارای ویژگی id هستند را برجسته می کند.

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

به لطف شناسه قطعه که سپس در هش URL صفحه استفاده می کنم، می توانم یک پیوند عمیق به هر عنصری که با کادر قرمز برجسته شده است قرار دهم. با فرض اینکه می‌خواستم پیوند عمیقی به قسمت بازخورد دادن به ما در کادر تالار گفتمان محصولات ما در کناری بگذارم، می‌توانم این کار را با ایجاد URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1 انجام دهم. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1 . همانطور که در پنل عناصر Developer Tools می بینید، عنصر مورد نظر دارای یک ویژگی id با مقدار HTML1 است.

Dev Tools id یک عنصر را نشان می دهد.

اگر این URL را با سازنده URL() جاوا اسکریپت تجزیه کنم، اجزای مختلف آشکار می شوند. به ویژگی 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 نیست، به این معنی که هیچ راهی وجود ندارد که بتوانم به این عنوان پیوند دهم. این مشکلی است که Text Fragments حل می کند.

Dev Tools که عنوانی را بدون id نشان می دهد.

تکه های متن

پیشنهاد Text Fragments پشتیبانی برای مشخص کردن یک قطعه متن در هش URL را اضافه می کند. هنگام پیمایش به یک URL با چنین قطعه متنی، عامل کاربر می تواند بر آن تاکید کند و/یا توجه کاربر را جلب کند.

سازگاری با مرورگر

پشتیبانی مرورگر

  • کروم: 89.
  • لبه: 89.
  • فایرفاکس: 131.
  • پیش نمایش فناوری سافاری: پشتیبانی می شود.

منبع

به دلایل امنیتی ، این ویژگی نیاز دارد که پیوندها در یک زمینه noopener باز شوند. بنابراین، مطمئن شوید که rel="noopener" در <a> anchor markup خود اضافه کنید یا noopener به لیست Window.open() خود از ویژگی های عملکرد پنجره اضافه کنید.

start

در ساده‌ترین شکل آن، نحو قطعات متن به این صورت است: نماد هش # و به دنبال آن :~:text= و در نهایت start ، که نمایانگر متن کدگذاری شده‌ای است که می‌خواهم به آن پیوند دهم.

#:~:text=start

به عنوان مثال، بگویید که می‌خواهم به ماژول‌های ECMAScript در 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 . وقتی روی یک مرورگر پشتیبانی مانند کروم کلیک می‌کنید، کل بخش برجسته می‌شود و برای مشاهده اسکرول می‌شود:

قطعه متن به نمای پیمایش شد و برجسته شد.

اکنون ممکن است در مورد انتخاب من برای 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 استفاده کنم، می بینید که در مشکل هستم. نشانی اینترنتی 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 را به عنوان نمونه انتخاب کردم؟ پاسخ این است که در این نسخه Text Fragments معرفی شدند:

متن پست وبلاگ: تکه های URL متن. کاربران یا نویسندگان اکنون می توانند با استفاده از یک قطعه متن ارائه شده در URL به بخش خاصی از صفحه پیوند دهند. هنگامی که صفحه بارگیری می شود، مرورگر متن را برجسته می کند و قطعه را برای مشاهده اسکرول می کند. به عنوان مثال، URL زیر صفحه ویکی «Cat» را بارگیری می کند و به محتوای فهرست شده در پارامتر «متن» پیمایش می کند.
گزیده پست وبلاگ اعلام تکه های متن.

توجه کنید که چگونه در تصویر بالای صفحه کلمه "متن" چهار بار ظاهر می شود. رخداد چهارم با فونت کد سبز نوشته شده است. اگر بخواهم به این کلمه خاص پیوند دهم، start به text تنظیم می کنم. از آنجایی که کلمه "متن" فقط یک کلمه است، end وجود ندارد. حالا چی؟ نشانی وب https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #:~:text=text با اولین تکرار کلمه "Text" در حال حاضر مطابقت دارد عنوان:

تطبیق قطعه متن در اولین رخداد "متن".

خوشبختانه راه حلی وجود دارد. در مواردی مانند این، من می توانم یک prefix​- و یک -suffix مشخص کنم. کلمه قبل از فونت کد سبز "text" "the" و کلمه بعد "پارامتر" است. هیچ یک از سه رخداد دیگر کلمه "متن" کلمات اطراف یکسانی ندارند. با داشتن این دانش، می‌توانم 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 Fragments در زیر نشان داده شده است. (براکت های مربع یک پارامتر اختیاری را نشان می دهد.) مقادیر همه پارامترها باید به صورت درصد رمزگذاری شوند. این به ویژه برای نویسه‌های خط - ، علامت & علامت , و ویرگول مهم است، بنابراین آنها به عنوان بخشی از نحو دستور متن تفسیر نمی‌شوند.

#:~: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 های قطعه متن را فهرست می کند. ما یک افزونه مرورگر منبع باز به نام 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 داشته باشید، به عنوان مثال، برای ارائه یک بازگشت معنی دار در صورت تغییر متن اصلی در صفحه، به طوری که قطعه متن دیگر مطابقت نداشته باشد. نشانی وب 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 ). شیوه نامه user-agent حاوی CSS است که به شکل زیر است:

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

همانطور که می بینید، مرورگر یک شبه انتخابگر ::target-text را نشان می دهد که می توانید از آن برای سفارشی کردن برجسته سازی اعمال شده استفاده کنید. به عنوان مثال، می توانید قطعات متن خود را به صورت متن سیاه روی پس زمینه قرمز طراحی کنید. مثل همیشه، حتما کنتراست رنگ را بررسی کنید تا استایل نادیده گرفته شده شما باعث مشکلات دسترسی نشود و مطمئن شوید که هایلایت واقعاً از نظر بصری از بقیه محتوا متمایز است.

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

قابلیت چندپر شدن

ویژگی Text Fragments را می توان تا حدی چند پر کرد. ما یک polyfill ارائه می دهیم که به صورت داخلی توسط برنامه افزودنی استفاده می شود، برای مرورگرهایی که پشتیبانی داخلی برای قطعات متنی که در جاوا اسکریپت اجرا می شود، ارائه نمی دهند.

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 دارند ، به گونه ای که صفحه مقصد به اندازه کافی جدا شده است. دستورالعمل های قطعه متن فقط در قاب اصلی اعمال می شود. این بدان معنی است که متن در داخل Iframes جستجو نمی شود ، و Iframe Navigation یک قطعه متن را فراخوانی نمی کند.

حریم خصوصی

این مهم است که پیاده سازی مشخصات قطعات متن نشت نمی کند که آیا یک قطعه متن در یک صفحه یافت شده است یا خیر. در حالی که قطعات عنصر کاملاً تحت کنترل صفحه اصلی نویسنده هستند ، قطعات متن توسط هر کسی می توانند ایجاد شوند. به یاد داشته باشید که چگونه در مثال من در بالا هیچ راهی برای پیوند دادن به ماژول های ECMAScript در کارگران وب وجود ندارد ، زیرا <h1> id نداشت ، اما چگونه کسی ، از جمله من ، فقط می تواند با ساخت دقیق قطعه متن به هر جایی پیوند بزند. ?

تصور کنید که من یک شبکه تبلیغاتی شیطانی evil-ads.example.com را اجرا کردم. علاوه بر این تصور کنید که در یکی از ad iframes من به صورت پویا یک Iframe متقاطع مخفی را به dating.example.com ایجاد کردم dating.example.com #:~:text=Log%20Out . اگر متن "ورود به سیستم" پیدا شود ، می دانم که قربانی در حال حاضر به dating.example.com وارد شده است ، که می توانم از آن برای پروفایل کاربر استفاده کنم. از آنجا که یک اجرای قطعات متن ساده ممکن است تصمیم بگیرد که یک مسابقه موفق باید باعث ایجاد سوئیچ تمرکز شود ، در evil-ads.example.com من می توانم به رویداد blur گوش دهم و بنابراین بدانم چه زمانی یک مسابقه رخ داده است. در Chrome ، ما قطعات متنی را به گونه ای پیاده سازی کرده ایم که سناریوی فوق نمی تواند اتفاق بیفتد.

حمله دیگر ممکن است بهره برداری از ترافیک شبکه بر اساس موقعیت پیمایش باشد. فرض کنید من مانند مدیر یک شرکت اینترانت به گزارش ترافیک شبکه قربانی خود دسترسی داشتم. حال تصور کنید که اگر از آن رنج می برید ، یک سند منابع انسانی طولانی وجود داشته باشد ... و سپس لیستی از شرایطی مانند سوختگی ، اضطراب و غیره. من می توانم یک پیکسل ردیابی را در کنار هر مورد در لیست قرار دهم. اگر من تعیین کنم که بارگیری سند به طور موقت با بارگذاری پیکسل ردیابی در کنار ، مثلاً مورد سوختگی ، می توانم به عنوان مدیر اینترانت ، تعیین کنم که یک کارمند روی یک لینک قطعه متن کلیک کرده است با :~:text=burn%20out از اینکه ممکن است کارمند فرض کرده باشد محرمانه بوده و برای کسی قابل مشاهده نیست. از آنجا که این مثال تا حدودی مورد توجه قرار گرفته است و از آنجا که بهره برداری از آن نیاز به پیش شرط های بسیار خاصی دارد ، تیم امنیتی Chrome خطر اجرای پیمایش در ناوبری را ارزیابی کرد تا قابل کنترل باشد. سایر نمایندگان کاربر ممکن است به جای آن تصمیم بگیرند که یک عنصر UI پیمایش دستی را نشان دهند.

برای سایتهایی که مایل به امتناع هستند ، Chromium از یک هدر سیاست سند پشتیبانی می کند که می تواند ارسال کند تا نمایندگان کاربر URL های قطعه متن را پردازش نکنند.

Document-Policy: force-load-at-top

غیرفعال کردن قطعات متن

ساده ترین راه برای غیرفعال کردن ویژگی ، استفاده از پسوند است که می تواند عنوان های پاسخ HTTP ، به عنوان مثال ، Modheader (نه یک محصول Google) ، برای وارد کردن یک هدر پاسخ ( نه درخواست) به شرح زیر:

Document-Policy: force-load-at-top

یکی دیگر از راه های انتخابی دیگر برای امتناع ، استفاده از تنظیمات تنظیمات Enterprise ScrollToTextFragmentEnabled است. برای انجام این کار در MACOS ، دستور زیر را در ترمینال بچسبانید.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

در ویندوز ، مستندات موجود در سایت پشتیبانی Google Chrome Enterprise را دنبال کنید.

برای برخی از جستجوها ، موتور جستجوگر Google پاسخ سریع یا خلاصه ای را با یک قطعه محتوا از یک وب سایت مربوطه ارائه می دهد. این قطعه های برجسته به احتمال زیاد وقتی جستجو در قالب یک سؤال باشد ، ظاهر می شوند. با کلیک بر روی یک قطعه برجسته ، کاربر را مستقیماً به متن قطعه قطعه شده در صفحه وب منبع می برد. این به لطف URL های متن به طور خودکار ایجاد شده است.

صفحه نتایج موتور جستجوی Google که یک قطعه برجسته را نشان می دهد. نوار وضعیت URL قطعات متن را نشان می دهد.
پس از کلیک بر روی ، بخش مربوط به صفحه مشاهده می شود.

نتیجه گیری

URL قطعات متن یک ویژگی قدرتمند برای پیوند به متن دلخواه در صفحات وب است. جامعه علمی می تواند از آن برای ارائه پیوندهای استناد یا مرجع بسیار دقیق استفاده کند. موتورهای جستجو می توانند از آن برای deeplink برای نتایج متن در صفحات استفاده کنند. سایت های شبکه های اجتماعی می توانند از آن استفاده کنند تا کاربران به جای تصاویر غیرقابل دسترسی ، بخش های خاص از یک صفحه وب را به اشتراک بگذارند. امیدوارم که شما شروع به استفاده از URL های قطعه متن کنید و آنها را به همان اندازه مفید بدانید. حتماً لینک را به پسوند مرورگر قطعه متن نصب کنید.

قدردانی

قطعات متن توسط نیک بوریس و دیوید بوکان با کمک های گرانت وانگ اجرا و مشخص شد. با تشکر از جو مدلی برای بررسی دقیق این مقاله. تصویر قهرمان توسط گرگ راکوزی در Unsplash .

،

قطعات متنی به شما امکان می دهد یک قطعه متنی را در قطعه URL مشخص کنید. مرورگر هنگام پیمایش به URL با چنین قطعه متن ، می تواند تأکید و یا آن را به توجه کاربر برساند.

شناسه های تکه تکه

Chrome 80 یک نسخه بزرگ بود. این شامل تعدادی از ویژگی های بسیار پیش بینی شده مانند ماژول های ECMAScript در کارگران وب ، همبستگی تهی ، زنجیره ای اختیاری و موارد دیگر بود. این نسخه طبق معمول از طریق یک پست وبلاگ در وبلاگ Chromium اعلام شد. می توانید گزیده ای از پست وبلاگ را در تصویر زیر مشاهده کنید.

پست وبلاگ Chromium با جعبه های قرمز در اطراف عناصر با یک ویژگی id .

شما احتمالاً از خود می پرسید که تمام جعبه های قرمز به چه معنی است. آنها نتیجه اجرای قطعه زیر در Devtools است. این همه عناصری را که دارای یک ویژگی id هستند برجسته می کند.

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

من می توانم به لطف شناسه قطعه ای که سپس در هش URL صفحه استفاده می کنم ، یک پیوند عمیق به هر عنصر برجسته شده با یک جعبه قرمز قرار دهم. با فرض اینکه من می خواستم پیوند عمیق به بازخورد ما در جعبه انجمن های محصول خود در کنار ، با استفاده از url url https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1 . همانطور که در پانل عناصر ابزارهای توسعه دهنده مشاهده می کنید ، عنصر مورد نظر دارای یک ویژگی id با مقدار HTML1 است.

ابزارهای dev نشان دهنده 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 در کارگران وب پیوند دهم. همانطور که در تصویر زیر مشاهده می کنید ، <h1> مورد نظر یک ویژگی id ندارد ، به این معنی که هیچ راهی وجود ندارد که بتوانم به این عنوان پیوند دهم. این مشکلی است که قطعات متن حل می کنند.

ابزارهای DEV نشان می دهد بدون id .

قطعات متن

پیشنهاد قطعات متن پشتیبانی را برای مشخص کردن قطعه متن در هش URL می افزاید. هنگام پیمایش به URL با چنین قطعه متن ، نماینده کاربر می تواند بر توجه کاربر تأکید کند و یا آن را به خود جلب کند.

سازگاری با مرورگر

پشتیبانی مرورگر

  • کروم: 89.
  • لبه: 89.
  • Firefox: 131.
  • پیش نمایش فناوری سافاری: پشتیبانی می شود.

منبع

به دلایل امنیتی ، این ویژگی نیاز به پیوندها در یک زمینه noopener دارد. بنابراین ، اطمینان حاصل کنید که rel="noopener" در نشانه گذاری لنگرگاه <a> خود قرار دهید یا noopener به Window.open() لیست ویژگی های عملکرد پنجره.

start

در ساده ترین شکل خود ، نحو قطعات متن به شرح زیر است: نماد هش # به دنبال آن :~:text= و در آخر start ، که نشان دهنده متن رمزگذاری شده درصد است که می خواهم به آن پیوند دهم.

#:~:text=start

به عنوان مثال ، بگویید که من می خواهم به ماژول های ECMAScript در کارگران وب که در پست وبلاگ اعلام می کنند ، در پست وبلاگ اعلام می کنم و ویژگی های موجود در 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 در کارگران وب پیوند دهم ، نه فقط عنوان آن؟ درصد رمزگذاری کل متن بخش باعث می شود URL حاصل به طور غیرقابل تصور طولانی شود.

خوشبختانه راه بهتری وجود دارد. به جای کل متن ، می توانم متن مورد نظر را با استفاده از SYNTAX 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 متن. کاربران یا نویسندگان هم اکنون می توانند با استفاده از یک قطعه متن ارائه شده در یک URL ، به بخش خاصی از صفحه پیوند بزنند. هنگامی که صفحه بارگیری می شود ، مرورگر متن را برجسته می کند و قطعه را به نمایش می گذارد. به عنوان مثال ، URL زیر یک صفحه ویکی را برای "گربه" بارگیری می کند و به محتوای ذکر شده در پارامتر "متن" می پردازد.
ارسال قطعات متن اعلامیه وبلاگ گزیده ای.

توجه کنید که چگونه در تصویر بالای کلمه "متن" چهار بار ظاهر می شود. وقوع چهارم با یک قلم کد سبز نوشته شده است. اگر می خواستم به این کلمه خاص پیوند بزنم ، start به text می کردم. از آنجا که کلمه "متن" ، خوب ، فقط یک کلمه است ، نمی تواند end یابد. حالا چی؟ url https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #:~:text=text در اولین بار از کلمه "متن" در حال حاضر در آن مطابقت دارد عنوان:

تطبیق قطعه متن در اولین وقوع "متن".

خوشبختانه یک راه حل وجود دارد. در مواردی از این دست ، می توانم prefix​- و a -suffix مشخص کنم. کلمه قبل از قلم کد سبز "متن" "" است و کلمه پس از آن "پارامتر" است. هیچ یک از سه مورد دیگر کلمه "متن" همان کلمات اطراف را ندارد. مسلح با این دانش ، می توانم 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=[prefix-,]start[,end][,-suffix]

هر یک از prefix- ، start ، end و -suffix فقط متن را در یک عنصر سطح بلوک مطابقت می دهند ، اما start,end می توانند چندین بلوک داشته باشند. به عنوان مثال ، :~:text=The quick,lazy dog در مثال زیر مطابقت نخواهد داشت ، زیرا رشته شروع "سریع" در یک عنصر سطح بلوک و بدون وقفه ظاهر نمی شود:

<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 های قطعه متن لیست می کند. ما یک برنامه افزودنی مرورگر منبع باز به نام Link to Text Fragment را ارائه می دهیم که به شما امکان می دهد با انتخاب آن به هر متن پیوند دهید و سپس روی "کپی پیوند به متن انتخاب شده" در منوی زمینه کلیک کنید. این پسوند برای مرورگرهای زیر در دسترس است:

پیوند به پسوند مرورگر قطعه متن .

قطعات چند متن در یک URL

توجه داشته باشید که چند قطعه متن می تواند در یک URL ظاهر شود. قطعات متن خاص باید توسط یک شخصیت ampersand & . در اینجا پیوندی با سه قطعه متن وجود دارد: 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 که می توانید برای سفارشی سازی برجسته کاربردی استفاده کنید. به عنوان مثال ، شما می توانید قطعات متن خود را طراحی کنید تا متن سیاه در پس زمینه قرمز باشد. مثل همیشه ، حتماً کنتراست رنگ را بررسی کنید تا یک ظاهر طراحی شده Override باعث ایجاد مشکلات دسترسی نشود و مطمئن شوید که برجسته در واقع بصری از بقیه محتوا است.

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

قابل عبور

ویژگی قطعات متن را می توان تا حدی پر کرد. ما برای مرورگرهایی که پشتیبانی داخلی را برای قطعات متنی که عملکرد آن در JavaScript اجرا می شود ، یک Polyfill ارائه می دهیم ، که از طریق آن توسط برنامه افزودنی استفاده می شود.

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;

امنیت

دستورالعمل های قطعه متن فقط در ناوبری های کامل (غیر صفحه) که نتیجه فعال سازی کاربر است ، فراخوانی می شوند. علاوه بر این ، ناوبری هایی که از منشأ متفاوت از مقصد سرچشمه می گیرند ، نیاز به انجام ناوبری در یک زمینه noopener دارند ، به گونه ای که صفحه مقصد به اندازه کافی جدا شده است. دستورالعمل های قطعه متن فقط در قاب اصلی اعمال می شود. این بدان معنی است که متن در داخل Iframes جستجو نمی شود ، و Iframe Navigation یک قطعه متن را فراخوانی نمی کند.

حریم خصوصی

این مهم است که پیاده سازی مشخصات قطعات متن نشت نمی کند که آیا یک قطعه متن در یک صفحه یافت شده است یا خیر. در حالی که قطعات عنصر کاملاً تحت کنترل صفحه اصلی نویسنده هستند ، قطعات متن توسط هر کسی می توانند ایجاد شوند. به یاد داشته باشید که چگونه در مثال من در بالا هیچ راهی برای پیوند دادن به ماژول های ECMAScript در کارگران وب وجود ندارد ، زیرا <h1> id نداشت ، اما چگونه کسی ، از جمله من ، فقط می تواند با ساخت دقیق قطعه متن به هر جایی پیوند بزند. ?

تصور کنید که من یک شبکه تبلیغاتی شیطانی evil-ads.example.com را اجرا کردم. علاوه بر این تصور کنید که در یکی از ad iframes من به صورت پویا یک Iframe متقاطع مخفی را به dating.example.com ایجاد کردم dating.example.com #:~:text=Log%20Out . اگر متن "ورود به سیستم" پیدا شود ، می دانم که قربانی در حال حاضر به dating.example.com وارد شده است ، که می توانم از آن برای پروفایل کاربر استفاده کنم. از آنجا که یک اجرای قطعات متن ساده ممکن است تصمیم بگیرد که یک مسابقه موفق باید باعث ایجاد سوئیچ تمرکز شود ، در evil-ads.example.com من می توانم به رویداد blur گوش دهم و بنابراین بدانم چه زمانی یک مسابقه رخ داده است. در Chrome ، ما قطعات متنی را به گونه ای پیاده سازی کرده ایم که سناریوی فوق نمی تواند اتفاق بیفتد.

حمله دیگر ممکن است بهره برداری از ترافیک شبکه بر اساس موقعیت پیمایش باشد. فرض کنید من مانند مدیر یک شرکت اینترانت به گزارش ترافیک شبکه قربانی خود دسترسی داشتم. حال تصور کنید که اگر از آن رنج می برید ، یک سند منابع انسانی طولانی وجود داشته باشد ... و سپس لیستی از شرایطی مانند سوختگی ، اضطراب و غیره. من می توانم یک پیکسل ردیابی را در کنار هر مورد در لیست قرار دهم. اگر من تعیین کنم که بارگیری سند به طور موقت با بارگذاری پیکسل ردیابی در کنار ، مثلاً مورد سوختگی ، می توانم به عنوان مدیر اینترانت ، تعیین کنم که یک کارمند روی یک لینک قطعه متن کلیک کرده است با :~:text=burn%20out از اینکه ممکن است کارمند فرض کرده باشد محرمانه بوده و برای کسی قابل مشاهده نیست. از آنجا که این مثال تا حدودی مورد توجه قرار گرفته است و از آنجا که بهره برداری از آن نیاز به پیش شرط های بسیار خاصی دارد ، تیم امنیتی Chrome خطر اجرای پیمایش در ناوبری را ارزیابی کرد تا قابل کنترل باشد. سایر نمایندگان کاربر ممکن است به جای آن تصمیم بگیرند که یک عنصر UI پیمایش دستی را نشان دهند.

برای سایتهایی که مایل به امتناع هستند ، Chromium از یک هدر سیاست سند پشتیبانی می کند که می تواند ارسال کند تا نمایندگان کاربر URL های قطعه متن را پردازش نکنند.

Document-Policy: force-load-at-top

غیرفعال کردن قطعات متن

ساده ترین راه برای غیرفعال کردن ویژگی ، استفاده از پسوند است که می تواند عنوان های پاسخ HTTP ، به عنوان مثال ، Modheader (نه یک محصول Google) ، برای وارد کردن یک هدر پاسخ ( نه درخواست) به شرح زیر:

Document-Policy: force-load-at-top

یکی دیگر از راه های انتخابی دیگر برای امتناع ، استفاده از تنظیمات تنظیمات Enterprise ScrollToTextFragmentEnabled است. برای انجام این کار در MACOS ، دستور زیر را در ترمینال بچسبانید.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

در ویندوز ، مستندات موجود در سایت پشتیبانی Google Chrome Enterprise را دنبال کنید.

برای برخی از جستجوها ، موتور جستجوگر Google پاسخ سریع یا خلاصه ای را با یک قطعه محتوا از یک وب سایت مربوطه ارائه می دهد. این قطعه های برجسته به احتمال زیاد وقتی جستجو در قالب یک سؤال باشد ، ظاهر می شوند. با کلیک بر روی یک قطعه برجسته ، کاربر را مستقیماً به متن قطعه قطعه شده در صفحه وب منبع می برد. این به لطف URL های متن به طور خودکار ایجاد شده است.

صفحه نتایج موتور جستجوی Google که یک قطعه برجسته را نشان می دهد. نوار وضعیت URL قطعات متن را نشان می دهد.
پس از کلیک بر روی ، بخش مربوط به صفحه مشاهده می شود.

نتیجه گیری

URL قطعات متن یک ویژگی قدرتمند برای پیوند به متن دلخواه در صفحات وب است. جامعه علمی می تواند از آن برای ارائه پیوندهای استناد یا مرجع بسیار دقیق استفاده کند. موتورهای جستجو می توانند از آن برای deeplink برای نتایج متن در صفحات استفاده کنند. سایت های شبکه های اجتماعی می توانند از آن استفاده کنند تا کاربران به جای تصاویر غیرقابل دسترسی ، بخش های خاص از یک صفحه وب را به اشتراک بگذارند. امیدوارم که شما شروع به استفاده از URL های قطعه متن کنید و آنها را به همان اندازه مفید بدانید. حتماً لینک را به پسوند مرورگر قطعه متن نصب کنید.

قدردانی

قطعات متن توسط نیک بوریس و دیوید بوکان با کمک های گرانت وانگ اجرا و مشخص شد. با تشکر از جو مدلی برای بررسی دقیق این مقاله. تصویر قهرمان توسط گرگ راکوزی در Unsplash .

،

قطعات متنی به شما امکان می دهد یک قطعه متنی را در قطعه URL مشخص کنید. مرورگر هنگام پیمایش به URL با چنین قطعه متن ، می تواند تأکید و یا آن را به توجه کاربر برساند.

شناسه های تکه تکه

Chrome 80 یک نسخه بزرگ بود. این شامل تعدادی از ویژگی های بسیار پیش بینی شده مانند ماژول های ECMAScript در کارگران وب ، همبستگی تهی ، زنجیره ای اختیاری و موارد دیگر بود. این نسخه طبق معمول از طریق یک پست وبلاگ در وبلاگ Chromium اعلام شد. می توانید گزیده ای از پست وبلاگ را در تصویر زیر مشاهده کنید.

پست وبلاگ Chromium با جعبه های قرمز در اطراف عناصر با یک ویژگی id .

شما احتمالاً از خود می پرسید که تمام جعبه های قرمز به چه معنی است. آنها نتیجه اجرای قطعه زیر در Devtools است. این همه عناصری را که دارای یک ویژگی id هستند برجسته می کند.

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

من می توانم به لطف شناسه قطعه ای که سپس در هش URL صفحه استفاده می کنم ، یک پیوند عمیق به هر عنصر برجسته شده با یک جعبه قرمز قرار دهم. با فرض اینکه من می خواستم پیوند عمیق به بازخورد ما در جعبه انجمن های محصول خود در کنار ، با استفاده از url url https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1 . همانطور که در پانل عناصر ابزارهای توسعه دهنده مشاهده می کنید ، عنصر مورد نظر دارای یک ویژگی id با مقدار HTML1 است.

ابزارهای dev نشان دهنده 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 در کارگران وب پیوند دهم. همانطور که در تصویر زیر مشاهده می کنید ، <h1> مورد نظر یک ویژگی id ندارد ، به این معنی که هیچ راهی وجود ندارد که بتوانم به این عنوان پیوند دهم. این مشکلی است که قطعات متن حل می کنند.

ابزارهای DEV نشان می دهد بدون id .

قطعات متن

پیشنهاد قطعات متن پشتیبانی را برای مشخص کردن قطعه متن در هش URL می افزاید. هنگام پیمایش به URL با چنین قطعه متن ، نماینده کاربر می تواند بر توجه کاربر تأکید کند و یا آن را به خود جلب کند.

سازگاری با مرورگر

پشتیبانی مرورگر

  • کروم: 89.
  • لبه: 89.
  • Firefox: 131.
  • پیش نمایش فناوری سافاری: پشتیبانی می شود.

منبع

به دلایل امنیتی ، این ویژگی نیاز به پیوندها در یک زمینه noopener دارد. بنابراین ، اطمینان حاصل کنید که rel="noopener" در نشانه گذاری لنگرگاه <a> خود قرار دهید یا noopener به Window.open() لیست ویژگی های عملکرد پنجره.

start

در ساده ترین شکل خود ، نحو قطعات متن به شرح زیر است: نماد هش # به دنبال آن :~:text= و در آخر start ، که نشان دهنده متن رمزگذاری شده درصد است که می خواهم به آن پیوند دهم.

#:~:text=start

به عنوان مثال ، بگویید که من می خواهم به ماژول های ECMAScript در کارگران وب که در پست وبلاگ اعلام می کنند ، در پست وبلاگ اعلام می کنم و ویژگی های موجود در 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 در کارگران وب پیوند دهم ، نه فقط عنوان آن؟ درصد رمزگذاری کل متن بخش باعث می شود URL حاصل به طور غیرقابل تصور طولانی شود.

خوشبختانه راه بهتری وجود دارد. به جای کل متن ، می توانم متن مورد نظر را با استفاده از SYNTAX 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 متن. کاربران یا نویسندگان هم اکنون می توانند با استفاده از یک قطعه متن ارائه شده در یک URL ، به بخش خاصی از صفحه پیوند بزنند. هنگامی که صفحه بارگیری می شود ، مرورگر متن را برجسته می کند و قطعه را به نمایش می گذارد. به عنوان مثال ، URL زیر یک صفحه ویکی را برای "گربه" بارگیری می کند و به محتوای ذکر شده در پارامتر "متن" می پردازد.
ارسال قطعات متن اعلامیه وبلاگ گزیده ای.

توجه کنید که چگونه در تصویر بالای کلمه "متن" چهار بار ظاهر می شود. وقوع چهارم با یک قلم کد سبز نوشته شده است. اگر می خواستم به این کلمه خاص پیوند بزنم ، start به text می کردم. از آنجا که کلمه "متن" ، خوب ، فقط یک کلمه است ، نمی تواند end یابد. حالا چی؟ url https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #:~:text=text در اولین بار از کلمه "متن" در حال حاضر در آن مطابقت دارد عنوان:

تطبیق قطعه متن در اولین وقوع "متن".

خوشبختانه یک راه حل وجود دارد. در مواردی از این دست ، می توانم prefix​- و a -suffix مشخص کنم. کلمه قبل از قلم کد سبز "متن" "" است و کلمه پس از آن "پارامتر" است. هیچ یک از سه مورد دیگر کلمه "متن" همان کلمات اطراف را ندارد. مسلح با این دانش ، می توانم 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=[prefix-,]start[,end][,-suffix]

هر یک از prefix- ، start ، end و -suffix فقط متن را در یک عنصر سطح بلوک مطابقت می دهند ، اما start,end می توانند چندین بلوک داشته باشند. به عنوان مثال ، :~:text=The quick,lazy dog در مثال زیر مطابقت نخواهد داشت ، زیرا رشته شروع "سریع" در یک عنصر سطح بلوک و بدون وقفه ظاهر نمی شود:

<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 های قطعه متن لیست می کند. We provide an open-source browser extension called Link to Text Fragment that lets you link to any text by selecting it, and then clicking "Copy Link to Selected Text" in the context menu. This extension is available for the following browsers:

Link to Text Fragment browser extension.

Multiple text fragments in one URL

Note that multiple text fragments can appear in one URL. The particular text fragments need to be separated by an ampersand character & . Here is an example link with three text fragments: 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 .

Three text fragments in one URL.

Mixing element and text fragments

Traditional element fragments can be combined with text fragments. It is perfectly fine to have both in the same URL, for example, to provide a meaningful fallback in case the original text on the page changes, so that the text fragment does not match anymore. The URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html #HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums. linking to the Give us feedback in our Product Forums section contains both an element fragment ( HTML1 ), as well as a text fragment ( text=Give%20us%20feedback%20in%20our%20Product%20Forums. ):

Linking with both element fragment and text fragment.

The fragment directive

There is one element of the syntax I have not explained yet: the fragment directive :~: . To avoid compatibility issues with existing URL element fragments as shown above, the Text Fragments specification introduces the fragment directive. The fragment directive is a portion of the URL fragment delimited by the code sequence :~: . It is reserved for user agent instructions, such as text= , and is stripped from the URL during loading so that author scripts cannot directly interact with it. User agent instructions are also called directives . In the concrete case, text= is therefore called a text directive .

Feature detection

To detect support, test for the read-only fragmentDirective property on document . The fragment directive is a mechanism for URLs to specify instructions directed to the browser rather than the document. It is meant to avoid direct interaction with author script, so that future user agent instructions can be added without fear of introducing breaking changes to existing content. One potential example of such future additions could be translation hints.

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

Feature detection is mainly intended for cases where links are dynamically generated (for example by search engines) to avoid serving text fragments links to browsers that do not support them.

Styling text fragments

By default, browsers style text fragments the same way they style mark (typically black on yellow, the CSS system colors for mark ). The user-agent stylesheet contains CSS that looks like this:

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

As you can see, the browser exposes a pseudo selector ::target-text that you can use to customize the applied highlighting. For example, you could design your text fragments to be black text on a red background. As always, be sure to check the color contrast so your override styling does not cause accessibility issues and make sure the highlighting actually visually stands out from the rest of the content.

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

Polyfillability

The Text Fragments feature can be polyfilled to some extent. We provide a polyfill , which is used internally by the extension , for browsers that do not provide built-in support for Text Fragments where the functionality is implemented in JavaScript.

The polyfill contains a file fragment-generation-utils.js that you can import and use to generate Text Fragment links. This is outlined in the code sample below:

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);
}

Obtaining Text Fragments for analytics purposes

Plenty of sites use the fragment for routing, which is why browsers strip out Text Fragments so as to not break those pages. There is an acknowledged need to expose Text Fragments links to pages, for example, for analytics purposes, but the proposed solution is not implemented yet. As a workaround for now, you can use the code below to extract the desired information.

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

امنیت

Text fragment directives are invoked only on full (non-same-page) navigations that are the result of a user activation . Additionally, navigations originating from a different origin than the destination will require the navigation to take place in a noopener context, such that the destination page is known to be sufficiently isolated. Text fragment directives are only applied to the main frame. This means that text will not be searched inside iframes, and iframe navigation will not invoke a text fragment.

حریم خصوصی

It is important that implementations of the Text Fragments specification do not leak whether a text fragment was found on a page or not. While element fragments are fully under the control of the original page author, text fragments can be created by anyone. Remember how in my example above there was no way to link to the ECMAScript Modules in Web Workers heading, since the <h1> did not have an id , but how anyone, including me, could just link to anywhere by carefully crafting the text fragment ?

Imagine I ran an evil ad network evil-ads.example.com . Further imagine that in one of my ad iframes I dynamically created a hidden cross-origin iframe to dating.example.com with a Text Fragment URL dating.example.com #:~:text=Log%20Out once the user interacts with the ad . If the text "Log Out" is found, I know the victim is currently logged in to dating.example.com , which I could use for user profiling. Since a naive Text Fragments implementation might decide that a successful match should cause a focus switch, on evil-ads.example.com I could listen for the blur event and thus know when a match occurred. In Chrome, we have implemented Text Fragments in such a way that the above scenario cannot happen.

Another attack might be to exploit network traffic based on scroll position. Assume I had access to network traffic logs of my victim, like as the admin of a company intranet. Now imagine there existed a long human resources document What to Do If You Suffer From… and then a list of conditions like burn out , anxiety , etc. I could place a tracking pixel next to each item on the list. If I then determine that loading the document temporally co-occurs with the loading of the tracking pixel next to, say, the burn out item, I can then, as the intranet admin, determine that an employee has clicked through on a text fragment link with :~:text=burn%20out that the employee may have assumed was confidential and not visible to anyone. Since this example is somewhat contrived to begin with and since its exploitation requires very specific preconditions to be met, the Chrome security team evaluated the risk of implementing scroll on navigation to be manageable. Other user agents may decide to show a manual scroll UI element instead.

For sites that wish to opt-out, Chromium supports a Document Policy header value that they can send so user agents will not process Text Fragment URLs.

Document-Policy: force-load-at-top

Disabling text fragments

The easiest way for disabling the feature is by using an extension that can inject HTTP response headers, for example, ModHeader (not a Google product), to insert a response ( not request) header as follows:

Document-Policy: force-load-at-top

Another, more involved, way to opt out is by using the enterprise setting ScrollToTextFragmentEnabled . To do this on macOS, paste the command below in the terminal.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

On Windows, follow the documentation on the Google Chrome Enterprise Help support site.

For some searches, the search engine Google provides a quick answer or summary with a content snippet from a relevant website. These featured snippets are most likely to show up when a search is in the form of a question. Clicking a featured snippet takes the user directly to the featured snippet text on the source web page. This works thanks to automatically created Text Fragments URLs.

Google search engine results page showing a featured snippet. The status bar shows the Text Fragments URL.
After clicking through, the relevant section of the page is scrolled into view.

نتیجه گیری

Text Fragments URL is a powerful feature to link to arbitrary text on webpages. The scholarly community can use it to provide highly accurate citation or reference links. Search engines can use it to deeplink to text results on pages. Social networking sites can use it to let users share specific passages of a webpage rather than inaccessible screenshots. I hope you start using Text Fragment URLs and find them as useful as I do. Be sure to install the Link to Text Fragment browser extension.

قدردانی

Text Fragments was implemented and specified by Nick Burris and David Bokan , with contributions from Grant Wang . Thanks to Joe Medley for the thorough review of this article. Hero image by Greg Rakozy on Unsplash .