Greasyfork - Add notes to the script

Add notes (aliases/tags) for scripts to help identify and search, and support WebDAV sync

Ekde 2023/04/09. Vidu La ĝisdata versio.

// ==UserScript==
// @name                Greasyfork - Add notes to the script
// @name:zh-CN          Greasyfork - 为脚本添加备注(别名/标签)
// @name:zh-TW          Greasyfork - 為指令碼新增備註(別名/標籤)
// @namespace           https://greatest.deepsurf.us/zh-CN/users/193133-pana
// @homepage            https://greatest.deepsurf.us/zh-CN/users/193133-pana
// @icon                data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+
// @version             3.1.1
// @description         Add notes (aliases/tags) for scripts to help identify and search, and support WebDAV sync
// @description:zh-CN   为脚本添加备注(别名/标签)功能,以帮助识别和搜索,并支持 WebDAV 同步功能
// @description:zh-TW   為指令碼新增備註(別名/標籤)功能,以幫助識別和搜尋,並支援 WebDAV 同步功能
// @author              pana
// @license             GNU General Public License v3.0 or later
// @compatible          chrome
// @compatible          firefox
// @match               *://*.greatest.deepsurf.us/*
// @match               *://*.sleazyfork.org/*
// @require             https://gcore.jsdelivr.net/gh/LightAPIs/greasy-fork-library@67b6b108dcea7594a8343b6501094fbb81fcf4a1/Note_Obj.js
// @connect            *
// @noframes
// @grant               GM_info
// @grant               GM_getValue
// @grant               GM_setValue
// @grant               GM_deleteValue
// @grant               GM_listValues
// @grant               GM_openInTab
// @grant               GM_addStyle
// @grant               GM_xmlhttpRequest
// @grant               GM_registerMenuCommand
// @grant               GM_unregisterMenuCommand
// @grant               GM_addValueChangeListener
// @grant               GM_removeValueChangeListener
// ==/UserScript==

(function () {
  'use strict';
  const UPDATED = '2023-04-09';
  const GF_ICON = {
    NOTE_BLACK: 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2IoMzgsIDM4LCAzOCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYigzOCwgMzgsIDM4KSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)'
  };
  const GF_STYLE = `
        .note-obj-gf-note-btn {
            background-image: ${GF_ICON.NOTE_BLACK};
            background-repeat: no-repeat;
            background-position: center;
            cursor: pointer;
            vertical-align: top;
        }
        .note-obj-gf-info-note-btn {
            background-size: 32px auto;
            width: 32px;
            height: 32px;
            margin-left: 20px;
            display: inline-block;
        }
        .note-obj-gf-library-note-btn {
            background-size: 24px auto;
            width: 24px;
            height: 24px;
            margin-left: 20px;
            display: inline-block;
        }
        .note-obj-gf-list-note-btn {
            background-size: 24px auto;
            width: 24px;
            height: 24px;
            margin-left: 10px;
            display: none;
        }
        .note-obj-gf-ts-note-btn {
            background-size: 16px auto;
            width: 16px;
            height: 16px;
            margin-left: 10px;
            display: none;
            vertical-align: sub;
        }
        ol.script-list li:hover .note-obj-gf-list-note-btn,
        #script-table tbody tr:hover .note-obj-gf-ts-note-btn {
            display: inline-block;
        }
        .note-obj-gf-note-tag,
        .note-obj-gf-ts-note-tag {
            background-color: #3c81df;
            color: #fff;
            display: inline-block;
            align-items: center;
            white-space: nowrap;
            border-radius: 50px;
            padding: 1px 10px;
            line-height: 1em;
        }
        .note-obj-gf-list-note-tag {
            text-decoration: none;
        }
    `;
  const noteObj = new Note_Obj({
    id: 'myGreasyForkNote',
    script: {
      author: {
        name: 'pana',
        homepage: 'https://greatest.deepsurf.us/zh-CN/users/193133-pana'
      },
      url: 'https://greatest.deepsurf.us/scripts/404275',
      updated: UPDATED
    },
    itemClick: key => `${location.origin}/scripts/${key}`,
    language: {
      userIdText: {
        en: 'Script ID',
        zhHans: '脚本 ID',
        zhHant: '指令碼 ID'
      },
      userNameText: {
        en: 'Script name',
        zhHans: '脚本名',
        zhHant: '指令碼名'
      }
    },
    changeEvent,
    style: GF_STYLE
  });
  function changeEvent(id) {
    const scriptId = getScriptIdFromPathname(location.pathname);
    if (scriptId) {
      infoPageNotes(scriptId, undefined, id);
    } else {
      listPageNotes(id);
      initTS(id);
    }
  }
  function initTS(changeId) {
    noteObj.fn.docQueryAll('#script-table tbody tr').forEach(item => {
      const scriptTitle = noteObj.fn.queryAnchor(item, '.thetitle a');
      if (scriptTitle) {
        const res = scriptTitle.href.match(/\d+$/);
        if (res) {
          const scriptId = res[0];
          const scriptName = scriptTitle.textContent?.trim();
          const thetitle = noteObj.fn.query(item, '.thetitle');
          if (thetitle && !noteObj.fn.query(thetitle, '.' + Note_Obj.btnClassName, 'none')) {
            thetitle.appendChild(noteObj.createNoteBtn(scriptId, scriptName, ['note-obj-gf-note-btn', 'note-obj-gf-ts-note-btn']));
          }
          if (!changeId || changeId === scriptId) {
            noteObj.handler(scriptId, scriptTitle, undefined, {
              add: 'span',
              className: ['note-obj-gf-ts-note-tag']
            }, scriptName);
          }
        }
      }
    });
  }
  function getScriptIdFromPathname(pathname) {
    const res = pathname.match(/^\/[\w-]+\/scripts\/(\d+)-/);
    if (res && res.length === 2) {
      return res[1];
    }
    return null;
  }
  function infoPageNotes(scriptId, scriptName, changeId) {
    const ele = noteObj.fn.docQuery('#script-info h2', 'info');
    if (ele) {
      if (!changeId || changeId === scriptId) noteObj.handler(scriptId, ele, undefined, {
        add: 'sapn',
        className: ['note-obj-gf-note-tag']
      }, scriptName);
    }
  }
  function listPageNotes(changeId) {
    const list = noteObj.fn.docQueryAll('ol.script-list li', 'info');
    for (const ele of list) {
      const scriptId = ele.dataset.scriptId;
      if (scriptId) {
        const description = noteObj.fn.query(ele, '.description');
        const scriptName = noteObj.fn.getText(ele, 'article > h2 > a', 'warn');
        if (description) {
          const desParent = description.parentElement;
          if (desParent && !noteObj.fn.query(desParent, '.' + Note_Obj.btnClassName, 'none')) {
            description.before(noteObj.createNoteBtn(scriptId, scriptName, ['note-obj-gf-note-btn', 'note-obj-gf-list-note-btn']));
          }
        }
        const header = noteObj.fn.query(ele, 'article > h2 > a');
        if (header) {
          if (!changeId || changeId === scriptId) noteObj.handler(scriptId, header, undefined, {
            add: 'span',
            className: ['note-obj-gf-note-tag', 'note-obj-gf-list-note-tag']
          }, scriptName);
        }
      }
    }
  }
  function init() {
    const scriptId = getScriptIdFromPathname(location.pathname);
    if (scriptId) {
      const installHelpLink = noteObj.fn.docQuery('#install-area .install-help-link:last-child', 'info');
      const scriptName = noteObj.fn.docGetText('header h2');
      if (installHelpLink) {
        installHelpLink.after(noteObj.createNoteBtn(scriptId, scriptName, ['note-obj-gf-note-btn', 'note-obj-gf-info-note-btn']));
      } else {
        const suggestion = noteObj.fn.docQuery('#script-feedback-suggestion');
        suggestion?.appendChild(noteObj.createNoteBtn(scriptId, scriptName, ['note-obj-gf-note-btn', 'note-obj-gf-library-note-btn']));
      }
      infoPageNotes(scriptId, scriptName);
    } else {
      listPageNotes();
      const scriptList = noteObj.fn.docQuery('#browse-script-list', 'info');
      if (scriptList) {
        const listObserver = new MutationObserver(() => {
          listPageNotes();
        });
        listObserver.observe(scriptList, {
          childList: true
        });
      }
      initTS();
      const tsTbody = noteObj.fn.docQuery('#script-table tbody', 'none');
      if (tsTbody) {
        const tsObserver = new MutationObserver(() => {
          initTS();
        });
        tsObserver.observe(tsTbody, {
          childList: true
        });
      }
    }
  }
  init();
})();