While we are in mid-August optimisation and tweaking territory, glancing again at my JS code I notice a few things that could be adjusted or tightened up.
- If we're only looking for one match, no need to heat the CPU in boreal summer by searching for more. Instead of leaving it to the default XPathResult.ANY_TYPEand using.iterateNext()to collect just the first (if any) match, we can look up the Result Type constants, specifyXPathResult.FIRST_ORDERED_NODE_TYPE, and collect any match with.singleNodeValue().
- XPATH expressions are chains of alternating 'Steps' and 'Filters'. We can broaden out the filter here with as many 'or' operators as we need. The simplest example might be: ./ancestor-or-self::*[self::code or self::pre]
- We can include text collection inside the function with return oSeln.toString().
(and then perhaps, drop it into an Execute JS in Safari (and/or Chrome) action, directing the output to the clipboard).
Select and copy code.kmmacros (19.2 KB)
(function () {
  var oSeln = window.getSelection(),
    nodeCode = document.evaluate(
      './ancestor-or-self::*[self::code or self::pre]',
      oSeln.anchorNode,
      null, XPathResult.FIRST_ORDERED_NODE_TYPE, 0
    ).singleNodeValue,
    rngDoc = nodeCode ?
      document.createRange() : null;
  if (nodeCode) {
    oSeln.removeAllRanges();
    rngDoc.selectNode(nodeCode);
    oSeln.addRange(rngDoc);
  }
  
  return oSeln.toString();
})();