获取第一个超链接及其文本值
Get the first hyperlink and its text value
希望大家身体健康,身体健康。
最近,我一直在使用应用程序脚本开发 Google 文档超链接,并一路学习。我试图获取所有超链接并对其进行编辑,为此我从这个 post 中找到了一个惊人的代码。我已经多次阅读代码,现在我对它的工作原理有了很好的理解。
我的困惑
我的困惑是这段代码中发生的递归过程,虽然我熟悉递归函数的概念但是当我尝试修改代码以仅从文档中获取第一个超链接时,我无法理解它如果没有我怎么能实现它打破递归函数。
这是我正在尝试的代码;
/**
* Get an array of all LinkUrls in the document. The function is
* recursive, and if no element is provided, it will default to
* the active document's Body element.
*
* @param {Element} element The document element to operate on.
* .
* @returns {Array} Array of objects, vis
* {element,
* startOffset,
* endOffsetInclusive,
* url}
*/
function getAllLinks(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
for (var ch=0; ch < text.length; ch++) {
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
var curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
links.push(curUrl); // add to links
curUrl = {};
}
}
}
if (inUrl) {
// in case the link ends on the same char that the element does
links.push(curUrl);
}
}
else {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
links = links.concat(getAllLinks(element.getChild(i)));
}
}
return links;
}
我试过添加
if (links.length > 0){
return links;
}
但它不会停止该函数,因为它是递归的,它 return 返回到之前的调用并继续 运行。
这是测试文档及其我正在处理的脚本。
https://docs.google.com/document/d/1eRvnR2NCdsO94C5nqly4nRXCttNziGhwgR99jElcJ_I/edit?usp=sharing
我希望你能理解我想表达的意思,谢谢你看我的post。保持快乐:D
我相信你的目标如下。
- 您想使用 Google Apps 脚本从共享文档中检索第一个 link 和 link 的文本。
- 您想在检索到第一个元素时停止递归循环。
修改点:
-
I tried adding
if (links.length > 0){
return links;
}
-
but it does not stop the function as it is recursive and it return back to its previous calls and continue running.
关于这个,不幸的是,我无法理解您将脚本放在脚本中的什么位置。在这种情况下,我认为需要在 links
有值时停止循环。而且,还需要检索文本。那么,修改如下如何?我修改了你脚本中的 3 个部分。
修改后的脚本:
function getAllLinks(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
for (var ch=0; ch < text.length; ch++) {
if (links.length > 0) break; // <--- Added
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
var curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
curUrl.text = text.slice(curUrl.startOffset, curUrl.endOffsetInclusive + 1); // <--- Added
links.push(curUrl); // add to links
curUrl = {};
}
}
}
if (inUrl) {
// in case the link ends on the same char that the element does
links.push(curUrl);
}
}
else {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
if (links.length > 0) { // <--- Added or if (links.length > 0) break;
return links;
}
links = links.concat(getAllLinks(element.getChild(i)));
}
}
return links;
}
- 在这种情况下,我认为
if (links.length > 0) {return links;}
可以修改为if (links.length > 0) break;
。
注:
顺便说一句,当使用Google Docs API时,links和文本也可以通过一个简单的脚本检索,如下所示.当你使用这个时,please enable Google Docs API at Advanced Google services.
function myFunction() {
const doc = DocumentApp.getActiveDocument();
const res = Docs.Documents.get(doc.getId()).body.content.reduce((ar, {paragraph}) => {
if (paragraph && paragraph.elements) {
paragraph.elements.forEach(({textRun}) => {
if (textRun && textRun.textStyle && textRun.textStyle.link) {
ar.push({text: textRun.content, url: textRun.textStyle.link.url});
}
});
}
return ar;
}, []);
console.log(res) // You can retrieve 1st link and test by console.log(res[0]).
}
希望大家身体健康,身体健康。
最近,我一直在使用应用程序脚本开发 Google 文档超链接,并一路学习。我试图获取所有超链接并对其进行编辑,为此我从这个 post 中找到了一个惊人的代码。我已经多次阅读代码,现在我对它的工作原理有了很好的理解。
我的困惑
我的困惑是这段代码中发生的递归过程,虽然我熟悉递归函数的概念但是当我尝试修改代码以仅从文档中获取第一个超链接时,我无法理解它如果没有我怎么能实现它打破递归函数。
这是我正在尝试的代码;
/**
* Get an array of all LinkUrls in the document. The function is
* recursive, and if no element is provided, it will default to
* the active document's Body element.
*
* @param {Element} element The document element to operate on.
* .
* @returns {Array} Array of objects, vis
* {element,
* startOffset,
* endOffsetInclusive,
* url}
*/
function getAllLinks(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
for (var ch=0; ch < text.length; ch++) {
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
var curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
links.push(curUrl); // add to links
curUrl = {};
}
}
}
if (inUrl) {
// in case the link ends on the same char that the element does
links.push(curUrl);
}
}
else {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
links = links.concat(getAllLinks(element.getChild(i)));
}
}
return links;
}
我试过添加
if (links.length > 0){
return links;
}
但它不会停止该函数,因为它是递归的,它 return 返回到之前的调用并继续 运行。
这是测试文档及其我正在处理的脚本。
https://docs.google.com/document/d/1eRvnR2NCdsO94C5nqly4nRXCttNziGhwgR99jElcJ_I/edit?usp=sharing
我希望你能理解我想表达的意思,谢谢你看我的post。保持快乐:D
我相信你的目标如下。
- 您想使用 Google Apps 脚本从共享文档中检索第一个 link 和 link 的文本。
- 您想在检索到第一个元素时停止递归循环。
修改点:
-
I tried adding
if (links.length > 0){ return links; }
-
but it does not stop the function as it is recursive and it return back to its previous calls and continue running.
关于这个,不幸的是,我无法理解您将脚本放在脚本中的什么位置。在这种情况下,我认为需要在 links
有值时停止循环。而且,还需要检索文本。那么,修改如下如何?我修改了你脚本中的 3 个部分。
修改后的脚本:
function getAllLinks(element) {
var links = [];
element = element || DocumentApp.getActiveDocument().getBody();
if (element.getType() === DocumentApp.ElementType.TEXT) {
var textObj = element.editAsText();
var text = element.getText();
var inUrl = false;
for (var ch=0; ch < text.length; ch++) {
if (links.length > 0) break; // <--- Added
var url = textObj.getLinkUrl(ch);
if (url != null) {
if (!inUrl) {
// We are now!
inUrl = true;
var curUrl = {};
curUrl.element = element;
curUrl.url = String( url ); // grab a copy
curUrl.startOffset = ch;
}
else {
curUrl.endOffsetInclusive = ch;
}
}
else {
if (inUrl) {
// Not any more, we're not.
inUrl = false;
curUrl.text = text.slice(curUrl.startOffset, curUrl.endOffsetInclusive + 1); // <--- Added
links.push(curUrl); // add to links
curUrl = {};
}
}
}
if (inUrl) {
// in case the link ends on the same char that the element does
links.push(curUrl);
}
}
else {
var numChildren = element.getNumChildren();
for (var i=0; i<numChildren; i++) {
if (links.length > 0) { // <--- Added or if (links.length > 0) break;
return links;
}
links = links.concat(getAllLinks(element.getChild(i)));
}
}
return links;
}
- 在这种情况下,我认为
if (links.length > 0) {return links;}
可以修改为if (links.length > 0) break;
。
注:
顺便说一句,当使用Google Docs API时,links和文本也可以通过一个简单的脚本检索,如下所示.当你使用这个时,please enable Google Docs API at Advanced Google services.
function myFunction() { const doc = DocumentApp.getActiveDocument(); const res = Docs.Documents.get(doc.getId()).body.content.reduce((ar, {paragraph}) => { if (paragraph && paragraph.elements) { paragraph.elements.forEach(({textRun}) => { if (textRun && textRun.textStyle && textRun.textStyle.link) { ar.push({text: textRun.content, url: textRun.textStyle.link.url}); } }); } return ar; }, []); console.log(res) // You can retrieve 1st link and test by console.log(res[0]). }