原文地址:Extracting Text from Content Using HTML Slot, HTML Template and Shadow DOMundefined日期:2019-03-06undefined作者:Preethi
书本上的章节名称、演讲的引用、文章里的关键字、报告上的统计信息,这些都是有助于提炼和转化成高度总结的摘要的内容。
比如, 你是否看到过 "Business Insider" 在展示文章内容之前提供的文章的关键点?
这些就是我们要做的事情,尝试使用HTML Slot, HTML Template和Shadow DOM直接从文章中提取出关键点。
这三个名词是Web Components规范的一部分,用于在网页中使用自定义的组件模块。
现在我们的目标是文本提取,并不需要自定义组件,但是它可以利用这三种技术。有一个很基础的办法来达到目的,例如我们可以用一些基本的js脚本就可以提取文本,而不需要使用slot和template。既然我们已经有一些熟悉的方法,那么为什么还要用他们呢?
使用这些技术的原因是他们允许我们为从HTML中提取的文本预设标记(也可以选择style或script)。本文后面的内容会介绍到这些。
现在, 对我们要用到的技术做一个简单的定义:
当我们开始编码后,就能更深入的了解他们。现在我们要做的是创造一个article标签,它的文本内容包含了若干个关键。你可能猜到了, 这些关键点是从文章中提取出来的, 并编译到了keyPoints节点。
<iframe name="cp_embed_1" src="https://codepen.io/rpsthecoder/embed/gZqVBO?height=430&theme-id=1&default-tab=result&user=rpsthecoder&slug-hash=gZqVBO&pen-title=Text%20Extraction%20with%20HTML%20Slot%20and%20HTML%20Template&name=cp_embed_1" scrolling="no" frameborder="0" height="430" allowtransparency="true" allowfullscreen="true" allowpaymentrequest="true" title="Text Extraction with HTML Slot and HTML Template" class="cp_embed_iframe " style="width: 100%; overflow: hidden; display: block; height: 100%;" id="cp_embed_gZqVBO"></iframe>
这些关键点需要被展示成一个列表。所以我们首先为这个列表创建一个模板, 并指定一个展示的位置。
<article><!-- Article content --></article>
<!-- Section where the extracted keypoints will be displayed -->
<section id='keyPointsSection'>
<h2>Key Points:</h2>
<ul><!-- Extracted key points will go in here --></ul>
</section>
<!-- Template for the key points list -->
<template id='keyPointsTemplate'>
<li><slot name='keyPoints'></slot></li>
<li style="text-align: center;">⤙—⤚</li>
</template>
我们使用包含了ul标签的section标签去展示关键点列表。然后, 我们使用template做为li标签的父元素,这两个li标签一个拥有文章中关键点的 <slot> 占位符, 另一个被设计成居中的分界线。
关于布局你可以随便一点,重点是放置一个slot去提取关键点。在我们使用js脚本把template添加到页面之前, 页面上什么都不会渲染出来。
值得一提的是,template中的标记也可以是行内的style或者使用style标签的css:
<template id='keyPointsTemplate'>
<li><slot name='keyPoints'></slot></li>
<li style="text-align: center;">⤙—⤚</li>
<style>
li{/* Some style */}
</style>
</template>
接下来是有趣的部分了,从文章中提取出关键点。需要注意template中的slot标签上的name属性的值(keyPoints), 因为我们需要它。
<article>
<h1>Bears</h1>
<p>Bears are carnivoran mammals of the family Ursidae. <span><span slot='keyPoints'>They are classified as caniforms, or doglike carnivorans</span></span>. Although only eight species of bears <!-- more content --> and partially in the Southern Hemisphere. <span><span slot='keyPoints'>Bears are found on the continents of North America, South America, Europe, and Asia</span></span>.<!-- more content --></p>
<p>While the polar bear is mostly carnivorous, <!-- more content -->. Bears use shelters, such as caves and logs, as their dens; <span><span slot='keyPoints'>Most species occupy their dens during the winter for a long period of hibernation</span></span>, up to 100 days.</p>
<!-- More paragraphs -->
</article>
关键点包含在span标签中,带有一个属性值为keyPoints的slot,它和template中的有相同name属性的slot标签相匹配。
再次注意,我们使用了span标签作为关键点的父元素。原因是slot的name通常是唯一且不重复的, 因为一个slot只使用一个name属性去匹配一个元素。如果有多个元素具有相同的slot name,那么slot占位符将被所有这些元素接连替换, 最后一个会覆盖之前所有的slot。因此, 如果我们对段落或文章中具有相同slot属性值 (关键点) 的所有span元素进行匹配, 我们最终只会匹配到段落或文章中最后一个关键点slot。
这不是我们想得到的结果,我们需要匹配到所有的关键点,于是我们可以用一个span元素作为父元素来包含这些关键点来匹配每一个单独的slot标签属性,看看代码怎么做:
const keyPointsTemplate = document.querySelector('#keyPointsTemplate').content;
const keyPointsSection = document.querySelector('#keyPointsSection > ul');
/* Loop through elements with 'slot' attribute */
document.querySelectorAll('[slot]').forEach((slot)=>{
let span = slot.parentNode.cloneNode(true);
span.attachShadow({ mode: 'closed' }).appendChild(keyPointsTemplate.cloneNode(true));
keyPointsSection.appendChild(span);
});
首先我们遍历每一个拥有slot属性的span元素并且复制它们的父元素(外层span),当然我们也可以直接遍历外层span,但是这样就要给外层span提供一些共有的class属性便于query到。接下来给外层span附上了一个由模板内容组成的shadow tree(span.attachShadow), 这个绑定在外层上的 "附件" 会导致shadow tree中模板list也会接受并匹配有相同slot name值(也就是我们的关键点)的span元素。再把这些关键点就添加到页面底部(keyPointsSection.appendChild)。我们在遍历中处理所有的关键点。
大功告成,我们已经提取出了文章中的所有关键点, 并复制了它们的内容, 然后把内容填充到模板list中, 便于把所有关键点组合在一起来提供一个像笔记一样的文章摘要。
这是最终的demo:
<iframe name="cp_embed_2" src="https://codepen.io/rpsthecoder/embed/gZqVBO?height=430&theme-id=1&default-tab=result&user=rpsthecoder&slug-hash=gZqVBO&pen-title=Text%20Extraction%20with%20HTML%20Slot%20and%20HTML%20Template&name=cp_embed_2" scrolling="no" frameborder="0" height="430" allowtransparency="true" allowfullscreen="true" allowpaymentrequest="true" title="Text Extraction with HTML Slot and HTML Template" class="cp_embed_iframe " style="width: 100%; overflow: hidden; display: block; height: 100%;" id="cp_embed_gZqVBO"></iframe>
你是怎么看待这个技术呢?它在处理一些有大量内容的场景, 如博客, 新闻, 或者维基百科词条时是有用的?或者你还想到了什么其他使用场景?