Google Docs — популярный редактор документов для создания и редактирования текстовых документов, электронных таблиц и презентаций. С помощью Google Apps Script, языка сценариев для автоматизации задач в Google Apps, пользователи могут расширить свои возможности редактирования документов, добавив пользовательские функции в Документы Google. Одной из таких функций является возможность проверки URL-адресов в документе Google.
Документы Google позволяют пользователям вставлять гиперссылки в свои документы, что может быть полезно для предоставления дополнительных ресурсов и информации. Однако с увеличением количества вредоносных веб-сайтов и неработающих ссылок важно проверить действительность этих ссылок, прежде чем делиться документом. Виджет для проверки URL-адресов в Google Docs может сделать этот процесс более эффективным и удобным.
Следующие шаги помогут вам создать виджет для проверки URL-адресов в Документах Google с помощью скрипта Google Apps.
Скрипт приложений
Откройте документ Google на Google Диске и щелкните меню «Расширения». В раскрывающемся меню выберите «Скрипт приложений».
В Apps Script скопируйте и вставьте следующие части кода:
- Добавить часть кода для создания пункта меню
/* Code to add submenu item */ function onOpen(e) { DocumentApp.getUi().createAddonMenu() .addItem('Show widget', 'showSidebar') .addToUi(); } /* Google script lifecycle */ function onInstall(e) { onOpen(e); }
Это приведет к чему-то вроде этого:
2.Функция Expose для отображения HTML-виджета на боковой панели
/* Code to add submenu item */ function showSidebar() { const ui = HtmlService.createHtmlOutputFromFile('sidebar') .setTitle('Link Checker'); DocumentApp.getUi().showSidebar(ui); }
3. Код для анализа ссылок текущего открытого Документа Google
Большое спасибо mogsdad за предоставленную суть: https://gist.github.com/mogsdad/6518632
Включив это в нашу логику
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 && ch != text.length - 1) { 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 = {}; } } } } else { // Get number of child elements, for elements that can have child elements. try { var numChildren = element.getNumChildren(); } catch (e) { numChildren = 0; } for (var i = 0; i < numChildren; i++) { links = links.concat(getAllLinks(element.getChild(i))); } } return links; }
4. Создайте функцию для вызова основного кода
Мы будем вызывать эту функцию из пользовательского интерфейса для запуска агрегации ссылок.
function obtainLinks() { const links = getAllLinks(); return links || []; }
5. Код для проверки статуса ссылок
Также будет вызываться из пользовательского интерфейса
async function checkLinks(links) { const requests = UrlFetchApp.fetchAll(links.map(({ url }) => ({ url, method: 'get', followRedirects: false }))) const results = requests.map(r => r.getResponseCode()); return links.map((link, index) => ({url: link.url, code: results[index] || 0})); }
6. Добавьте интерфейс
Не буду так подробно вдаваться:
- Создайте sidebar.html в редакторе проектов Apps Script.
- добавьте код ниже, чтобы указать и выполнить открытые функции
<!DOCTYPE html> <html> <head> <base target="_top"> <title></title> </head> <body> <div class="sidebar branding-below"> <form> <div class="block col-contain"> <table class="links"> <thead> <tr class="links_row"> <th class="links_heading links_cell--url">URL</th> <th class="links_heading links_cell--status">Status</th> </tr> </thead> <tbody id="links" class="links_body"></tbody> </table> </div> <div class="block" id="button-bar"> <button class="blue" id="obtain-links">Obtain links</button> <button class="green" id="check-links" disabled="disabled">Check links</button> </div> </form> </div> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script> /** * On document load, assign click handlers to each button and try to load the * user's origin and destination language preferences if previously set. */ let currentLinks = []; $(function() { $('#obtain-links').click(obtainLinks); $('#check-links').click(checkLinks); }); /** * Runs a server-side function to translate the user-selected text and update * the sidebar UI with the resulting translation. */ function obtainLinks() { setBlueState(true); $('#error').remove(); google.script.run .withSuccessHandler( function(links, element) { $('#links > *').remove(); currentLinks = links || []; links.map(function(link) { $('#links') .append(`<tr class="links_row"><td class="links_cell links_cell--url">${link.url}</td><td class="links_cell links_cell--status">?</td></tr>`); }); setGreenState(); setBlueState(false); }) .withFailureHandler( function(msg, element) { showError(msg, $('#button-bar')); setBlueState(false); }) .withUserObject(this) .obtainLinks(); } function setBlueState(disabled) { if(!disabled){ $('#obtain-links').removeAttr('disabled'); } else { $('#obtain-links').attr('disabled', 'disabled'); } } function setGreenState() { if(currentLinks.length > 0){ $('#check-links').removeAttr('disabled'); } else { $('#check-links').attr('disabled', 'disabled'); } } function checkLinks() { setBlueState(true); $('#error').remove(); google.script.run .withSuccessHandler( function(links, element) { $('#links > *').remove(); currentLinks = links || []; links.map(function(link) { $('#links') .append(`<tr class="links_row"><td class="links_cell links_cell--url">${link.url}</td><td class="links_cell links_cell--status">${link.code}</td></tr>`); }); setGreenState(); setBlueState(false); }) .withFailureHandler( function(msg, element) { showError(msg, $('#button-bar')); setBlueState(false); }) .withUserObject(this) .checkLinks(currentLinks); } function showError(msg, element) { const div = $('<div id="error" class="error">' + msg + '</div>'); $(element).after(div); } </script> </body> </html>
Демонстрационное время
И в волшебстве некоторого дополнительного CSS у вас есть виджет:
- Получает ссылки
- Получает статусы