Skip to content

Instantly share code, notes, and snippets.

@majido
Last active March 23, 2020 22:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save majido/2e8ad5623edb0f98b8a105ccdb9b6361 to your computer and use it in GitHub Desktop.
Save majido/2e8ad5623edb0f98b8a105ccdb9b6361 to your computer and use it in GitHub Desktop.
Gerrit CL to Markdown
// Small bookmarklet to pring CLs from gerrit in Markdown format.
// Used and tested on https://chromium-review.googlesource.com
// To make this a bookmarklet put the content below into a
// bookmark's link field.
javascript:(function() {
const cls = getCLs();
const desc = Array.prototype.map.call(cls, format);
console.log(desc.join('\n'));
function format(a) {
return `* ${a.textContent.trim()} [CL](${a.href})`;
}
function getCLs() {
if (true || document.body.querySelector('gr-app-p2')) {
/* v2 uses shadow DOM so we cannot use regular shodow piercing selector*/
const items = querySelectorAllDeep('gr-change-list-item', document.body );
let cls = [];
items.forEach((i) => {
cls.push(i.shadowRoot.querySelector('.cell.subject a'))
});
return cls;
} else {
/* Use a simple selector for v1*/
return document.querySelectorAll("gr-change-list-item td.subject a.gr-change-list-item");
}
}
/* Using deep selector to help with shadow dom https://github.com/Georgegriff/query-selector-shadow-dom/blob/master/src/querySelectorDeep.js */
function querySelectorAllDeep(selector, root = document) {
return _querySelectorDeep(selector, true, root);
}
function querySelectorDeep(selector, root = document) {
return _querySelectorDeep(selector, false, root);
}
function _querySelectorDeep(selector, findMany, root) {
let lightElement = root.querySelector(selector);
if (document.head.createShadowRoot || document.head.attachShadow) {
if (!findMany && lightElement) {
return lightElement;
}
const selectionsToMake = splitByCharacterUnlessQuoted(selector, ',');
return selectionsToMake.reduce((acc, minimalSelector) => {
if (!findMany && acc) {
return acc;
}
const splitSelector = splitByCharacterUnlessQuoted(minimalSelector
.replace(/^\s+/g, '')
.replace(/\s*([>+~]+)\s*/g, '$1'), ' ')
.filter((entry) => !!entry);
const possibleElementsIndex = splitSelector.length - 1;
const possibleElements = collectAllElementsDeep(splitSelector[possibleElementsIndex], root);
const findElements = findMatchingElement(splitSelector, possibleElementsIndex, root);
if (findMany) {
acc = acc.concat(possibleElements.filter(findElements));
return acc;
} else {
acc = possibleElements.find(findElements);
return acc || null;
}
}, findMany ? [] : null);
} else {
if (!findMany) {
return lightElement;
} else {
return root.querySelectorAll(selector);
}
}
}
function findMatchingElement(splitSelector, possibleElementsIndex, root) {
return (element) => {
let position = possibleElementsIndex;
let parent = element;
let foundElement = false;
while (parent && !isDocumentNode(parent)) {
const foundMatch = parent.matches(splitSelector[position]);
if (foundMatch && position === 0) {
foundElement = true;
break;
}
if (foundMatch) {
position--;
}
parent = findParentOrHost(parent, root);
}
return foundElement;
};
}
function splitByCharacterUnlessQuoted(selector, character) {
return selector.match(/\\?.|^$/g).reduce((p, c) => {
if (c === '"' && !p.sQuote) {
p.quote ^= 1;
p.a[p.a.length - 1] += c;
} else if (c === '\'' && !p.quote) {
p.sQuote ^= 1;
p.a[p.a.length - 1] += c;
} else if (!p.quote && !p.sQuote && c === character) {
p.a.push('');
} else {
p.a[p.a.length - 1] += c;
}
return p;
}, { a: [''] }).a;
}
function isDocumentNode(node) {
return node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.DOCUMENT_NODE;
}
function findParentOrHost(element, root) {
const parentNode = element.parentNode;
return (parentNode && parentNode.host && parentNode.nodeType === 11) ? parentNode.host : parentNode === root ? null : parentNode;
}
function collectAllElementsDeep(selector = null, root) {
const allElements = [];
const findAllElements = function(nodes) {
for (let i = 0, el; el = nodes[i]; ++i) {
allElements.push(el);
if (el.shadowRoot) {
findAllElements(el.shadowRoot.querySelectorAll('*'));
}
}
};
if(root.shadowRoot) {
findAllElements(root.shadowRoot.querySelectorAll('*'));
}
findAllElements(root.querySelectorAll('*'));
return selector ? allElements.filter(el => el.matches(selector)) : allElements;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment