【问题标题】:Get the first hyperlink and its text value获取第一个超链接及其文本值
【发布时间】:2021-01-06 04:35:19
【问题描述】:

我希望每个人都身体健康,身体健康。 最近,我一直在使用应用程序脚本和学习 Google Docs 超链接。我试图获取所有超链接并对其进行编辑,为此我从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;
}

但它不会停止函数,因为它是递归的,它会返回到之前的调用并继续运行。 这是我正在处理的测试文档及其脚本。
https://docs.google.com/document/d/1eRvnR2NCdsO94C5nqly4nRXCttNziGhwgR99jElcJ_I/edit?usp=sharing

希望您能理解我要传达的内容,感谢您查看我的帖子。保持快乐:D

【问题讨论】:

    标签: google-apps-script hyperlink google-docs


    【解决方案1】:

    我相信你的目标如下。

    • 您想使用 Google Apps 脚本从共享文档中检索第一个链接和链接文本。
    • 您希望在检索到第一个元素时停止递归循环。

    修改点:

    • 我尝试添加

        if (links.length > 0){
             return links;
        }
      
    • 但它不会停止函数,因为它是递归的,它会返回到之前的调用并继续运行。

    关于这个,很遗憾,我无法理解您将脚本放在脚本中的哪个位置。在这种情况下,我认为当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 &gt; 0) {return links;}可以修改为if (links.length &gt; 0) break;

    注意:

    • 顺便说一句,当使用 Google Docs API 时,链接和文本也可以通过一个简单的脚本来检索,如下所示。当你使用这个时,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]).
        }
      

    【讨论】:

    • 好的,感谢代码提供了所需的输出,但我仍然不明白你是如何设法打破递归循环的。您还提到我们可以使用if (links.length &gt; 0) break; 而不是if (links.length &gt; 0) {return links;} 这两者有什么区别。谢谢:D
    • @abdulsamad 感谢您的回复。对于给您带来的不便和我糟糕的英语水平,我深表歉意。在您的脚本中,有 2 个循环。所以我认为当检索到 1 个值时需要停止这些。例如,当删除if (links.length &gt; 0) break; 之一时,将从一个段落中检索链接。在您的示例文档中,检索到 3 个链接。所以我建议使用 2 if (links.length &gt; 0) break; 进行上述修改。
    • @abdulsamad 并且,当使用if (links.length &gt; 0) {return links;} 时,循环到此结束。当使用if (links.length &gt; 0) break; 时,使用最后一行的return links;。所以可以得到同样的结果。我再次为我糟糕的英语水平道歉。
    • 哦,我现在明白了,而且我目前正在了解您使用文档 API 尝试的代码,它更快但对我来说也是新的,但我正在掌握它。此外,我清楚地了解您的英语,并感谢您的所有澄清。永远保持快乐:)
    • 还有一个问题,我可以在哪里找到 Google Doc API 的完整文档,例如我想为选定的超链接文本设置新的 url textRun 中有一个函数可以做到这一点如果是,你在哪里找到它来自,请分享来源。
    猜你喜欢
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    相关资源
    最近更新 更多