Added hyperlink tab search
Added webpack implementation
This commit is contained in:
parent
417da22c71
commit
705bd684fb
12
popup.css
12
popup.css
@ -16,3 +16,15 @@ input[type="text"].display, input[type="text"].display:active, input[type="text"
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cursor-default {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
6
popup.dist.js
Normal file
6
popup.dist.js
Normal file
File diff suppressed because one or more lines are too long
76
popup.html
76
popup.html
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
<script src="vue-js/dist/core.dist.js"></script>
|
<script src="vue-js/dist/core.dist.js"></script>
|
||||||
|
|
||||||
<script src="popup.js"></script>
|
<!-- <script src="popup.js"></script> -->
|
||||||
|
<script src="popup.dist.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="bootstrap/5.3.3/css/bootstrap.min.css">
|
<link rel="stylesheet" href="bootstrap/5.3.3/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="popup.css">
|
<link rel="stylesheet" href="popup.css">
|
||||||
@ -28,20 +29,64 @@
|
|||||||
<div class="tab-pane py-3 fade" id="nav-hyperlinks" role="tabpanel" aria-labelledby="nav-hyperlinks-tab" tabindex="0">
|
<div class="tab-pane py-3 fade" id="nav-hyperlinks" role="tabpanel" aria-labelledby="nav-hyperlinks-tab" tabindex="0">
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row pb-2" role="options"></div>
|
<div class="pt-2 pb-2 mb-2 border-bottom">
|
||||||
<div class="row pb-3 mb-3 border-bottom">
|
<div class="row mb-2">
|
||||||
<div class="col">
|
<label for="textBox1" class="col-sm-3 col-form-label fw-bold">Search Term</label>
|
||||||
<button type="button" class="btn btn-primary btn-sm">Load Results</button>
|
<div class="col-sm-7">
|
||||||
<button type="button" class="btn btn-outline-secondary btn-sm">Load CSV</button>
|
<div class="input-group input-group-sm">
|
||||||
|
<input type="text" class="form-control" placeholder="Keyword" role="textbox" id="textBox1" />
|
||||||
|
<button type="button" class="btn btn-secondary input-group-text">✕</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 cursor-default fw-bold">Search Field</div>
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="radioGroup1" id="radioBox1" value="anchor">
|
||||||
|
<label class="form-check-label" for="radioBox1">Anchor Text</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="radioGroup1" id="radioBox2" value="link" checked>
|
||||||
|
<label class="form-check-label" for="radioBox2">Link Address</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 cursor-default fw-bold">Display Type</div>
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="radioGroup2" id="radioBox3" value="table" checked>
|
||||||
|
<label class="form-check-label" for="radioBox3">Table</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="radioGroup2" id="radioBox4" value="csv">
|
||||||
|
<label class="form-check-label" for="radioBox4">CSV</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-check-inline">
|
||||||
|
<input class="form-check-input" type="radio" name="radioGroup2" id="radioBox5" value="links">
|
||||||
|
<label class="form-check-label" for="radioBox5">Links</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-2 mb-2">
|
||||||
|
<div class="col-sm-3"></div>
|
||||||
|
<div class="col-sm-7">
|
||||||
|
<button type="button" class="btn btn-primary btn-sm">Load Results</button>
|
||||||
|
<span class="ps-1" role="label"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pb-1">
|
<div class="fw-bold clearfix cursor-pointer" data-bs-toggle="collapse" data-bs-target="#collapsPanel1" aria-expanded="false" aria-controls="collapsPanel1">⯈ Options</div>
|
||||||
<div class="col">
|
<div class="row pt-2 pb-2 mb-2 border-bottom collapse" role="options" id="collapsPanel1"></div>
|
||||||
<span class="fw-bold" role="table-heading">Results</span>
|
|
||||||
</div>
|
<div class="fw-bold clearfix cursor-pointer" data-bs-toggle="collapse" data-bs-target="#collapsPanel2" aria-expanded="false" aria-controls="collapsPanel2">⯈ Filters</div>
|
||||||
</div>
|
<div class="row pt-2 collapse" role="filters" id="collapsPanel2"></div>
|
||||||
<div class="row">
|
|
||||||
|
<div class="row pb-2 mb-2 border-bottom"></div>
|
||||||
|
|
||||||
|
<div class="row pt-2 mb-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
|
||||||
<table class="table table-bordered table-hover table-sm table-striped">
|
<table class="table table-bordered table-hover table-sm table-striped">
|
||||||
@ -49,18 +94,13 @@
|
|||||||
<tbody></tbody>
|
<tbody></tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<textarea class="form-control font-monospace text-sm px-1 py-1" rows="16"></textarea>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade" id="nav-images" role="tabpanel" aria-labelledby="nav-images-tab" tabindex="0">...</div>
|
<div class="tab-pane fade" id="nav-images" role="tabpanel" aria-labelledby="nav-images-tab" tabindex="0">...</div>
|
||||||
<div class="tab-pane fade" id="nav-disabled" role="tabpanel" aria-labelledby="nav-disabled-tab" tabindex="0">...</div>
|
<div class="tab-pane fade" id="nav-disabled" role="tabpanel" aria-labelledby="nav-disabled-tab" tabindex="0">...</div>
|
||||||
|
644
popup.js
644
popup.js
@ -1,644 +0,0 @@
|
|||||||
class PopupService {
|
|
||||||
|
|
||||||
|
|
||||||
async SendMessage(eventName, callback) {
|
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
|
|
||||||
chrome.tabs.sendMessage(tabs[0].id, { event: eventName }, callback);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async GetHyperlinks() {
|
|
||||||
const a = this;
|
|
||||||
const baseUrl = await a.GetLocation();
|
|
||||||
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
a.SendMessage("GetNodes", async function(payload) {
|
|
||||||
// let result = {
|
|
||||||
// items: payload.copy(),
|
|
||||||
// totalCount: payload.length,
|
|
||||||
// distinctCount: 0
|
|
||||||
// };
|
|
||||||
|
|
||||||
// result.items = result.items.orderBy("innerText");
|
|
||||||
// result.items = result.items.distinct();
|
|
||||||
|
|
||||||
// result.distinctCount = result.items.length;
|
|
||||||
|
|
||||||
// Populate occurrence counter
|
|
||||||
// for (let i=0; i<result.items.length; i++) {
|
|
||||||
// result.items[i].occurrence = payload.filter(item => JSON.stringify(item) === JSON.stringify(result.items[i])).length;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// resolve(result);
|
|
||||||
|
|
||||||
// console.log(payload);
|
|
||||||
|
|
||||||
resolve(payload.copy());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async GetLocation() {
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
a.SendMessage("GetLocation", function(payload) {
|
|
||||||
resolve(payload);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ContentService {
|
|
||||||
|
|
||||||
GenerateCheckBox(num, label, checked) {
|
|
||||||
let html = "";
|
|
||||||
html += "<div class=\"form-check form-switch\">";
|
|
||||||
html += "<input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"checkbox" + num + "\" " + (checked ? "checked" : "") + ">";
|
|
||||||
html += "<label class=\"form-check-label\" for=\"checkbox" + num + "\">" + label + "</label>";
|
|
||||||
html += "</div>";
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateCols(...args) {
|
|
||||||
let html = "";
|
|
||||||
|
|
||||||
for (let i=0; i<args.length; i++) {
|
|
||||||
html += "<div class=\"col\">" + args[i] + "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateRow(...args) {
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
if (args.length === 1) {
|
|
||||||
if (Object.getDataType(args[0]) == "array") {
|
|
||||||
args = args[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let result = "";
|
|
||||||
for (let i=0; i<args.length; i++) {
|
|
||||||
result = result + a.GenerateRowCell(args[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return "<tr>" + result + "</tr>";
|
|
||||||
}
|
|
||||||
|
|
||||||
GenerateRowCell(value) {
|
|
||||||
return "<td class=\"\"><input type=\"text\" class=\"display\" readonly=\"readonly\" value=\"" + value + "\" /></td>";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class AContentService extends ContentService {
|
|
||||||
ContainerPanel = null;
|
|
||||||
Panel1 = null;
|
|
||||||
Button1 = null;
|
|
||||||
Button2 = null;
|
|
||||||
Label1 = null;
|
|
||||||
Table1 = null;
|
|
||||||
|
|
||||||
#PopupService = null;
|
|
||||||
#TableLabel = "Results";
|
|
||||||
|
|
||||||
|
|
||||||
constructor(popupService) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.#PopupService = popupService;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitialiseComponents(){
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
a.ContainerPanel = document.getElementById("nav-hyperlinks");
|
|
||||||
a.Panel1 = a.ContainerPanel.querySelectorAll("div[role='options']")[0];
|
|
||||||
a.Button1 = a.ContainerPanel.querySelectorAll("button")[0];
|
|
||||||
a.Button2 = a.ContainerPanel.querySelectorAll("button")[1];
|
|
||||||
a.Label1 = a.ContainerPanel.querySelectorAll("span[role='table-heading']")[0];
|
|
||||||
a.Table1 = a.ContainerPanel.querySelectorAll("table")[0];
|
|
||||||
|
|
||||||
a.Clear();
|
|
||||||
|
|
||||||
let col1 = "";
|
|
||||||
col1 += a.GenerateCheckBox(1, "Show Anchor as HTML", false);
|
|
||||||
col1 += a.GenerateCheckBox(3, "Sort By Anchor Text", true);
|
|
||||||
col1 += a.GenerateCheckBox(2, "Trim Anchor Text", true);
|
|
||||||
col1 += a.GenerateCheckBox(4, "Resolve Relative URL", false);
|
|
||||||
col1 += a.GenerateCheckBox(12, "Hide External Links", true);
|
|
||||||
|
|
||||||
let col2 = "";
|
|
||||||
col2 += a.GenerateCheckBox(5, "Hide Duplicates", true);
|
|
||||||
col2 += a.GenerateCheckBox(14, "Hide Blank Anchors", true);
|
|
||||||
col2 += a.GenerateCheckBox(15, "Hide Blank Links", true);
|
|
||||||
col2 += a.GenerateCheckBox(11, "Hide Fragments", true);
|
|
||||||
col2 += a.GenerateCheckBox(13, "Hide Mailto/Tel", true);
|
|
||||||
|
|
||||||
let col3 = "";
|
|
||||||
col3 += a.GenerateCheckBox(6, "Show Title", true);
|
|
||||||
col3 += a.GenerateCheckBox(7, "Show Target", false);
|
|
||||||
col3 += a.GenerateCheckBox(8, "Show Rel", false);
|
|
||||||
col3 += a.GenerateCheckBox(9, "Show Type", false);
|
|
||||||
col3 += a.GenerateCheckBox(10, "Show Occurrence", false);
|
|
||||||
|
|
||||||
let html = a.GenerateCols(col1, col2, col3);
|
|
||||||
|
|
||||||
a.#writeOptionsPanel(html);
|
|
||||||
|
|
||||||
a.Button1.addEventListener('click', async function (e) {
|
|
||||||
a.Button1.disabled = true;
|
|
||||||
|
|
||||||
await a.Search();
|
|
||||||
|
|
||||||
a.Button1.disabled = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Clear() {
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
a.#writeOptionsPanel("");
|
|
||||||
|
|
||||||
a.#clearTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
async Search() {
|
|
||||||
const a = this;
|
|
||||||
const thead = a.Table1.querySelectorAll("thead")[0];
|
|
||||||
const tbody = a.Table1.querySelectorAll("tbody")[0];
|
|
||||||
|
|
||||||
a.#clearTable();
|
|
||||||
|
|
||||||
// Write thead
|
|
||||||
thead.innerHTML = "<tr>" + a.#generateTHeader() + "</tr>";
|
|
||||||
|
|
||||||
const result = await a.#PopupService.GetHyperlinks();
|
|
||||||
const totalCount = result.length;
|
|
||||||
|
|
||||||
a.Label1.innerText = a.#TableLabel + " (" + totalCount + ")";
|
|
||||||
|
|
||||||
const newResults = await a.#filterSearch(result.copy());
|
|
||||||
|
|
||||||
if (newResults.length != totalCount) {
|
|
||||||
a.Label1.innerText = a.#TableLabel + " (" + newResults.length + "/" + totalCount + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i=0; i<newResults.length; i++) {
|
|
||||||
const item = newResults[i];
|
|
||||||
|
|
||||||
let row = [ item.text, item.href ];
|
|
||||||
|
|
||||||
if (a.#getCheckBox(6)) {
|
|
||||||
row.push(item.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.#getCheckBox(7)) {
|
|
||||||
row.push(item.target);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.#getCheckBox(8)) {
|
|
||||||
row.push(item.rel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.#getCheckBox(9)) {
|
|
||||||
row.push(item.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a.#getCheckBox(10)) {
|
|
||||||
row.push(item.occurrence);
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody.innerHTML += a.GenerateRow(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#clearTable() {
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
a.Label1.innerText = a.#TableLabel;
|
|
||||||
|
|
||||||
const thead = a.Table1.querySelectorAll("thead")[0];
|
|
||||||
const tbody = a.Table1.querySelectorAll("tbody")[0];
|
|
||||||
thead.innerHTML = "";
|
|
||||||
tbody.innerHTML = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
async #filterSearch(items) {
|
|
||||||
const a = this;
|
|
||||||
const currentUrl = await popupService.GetLocation();
|
|
||||||
const currentHostname = (new URL(currentUrl)).hostname;
|
|
||||||
|
|
||||||
let result = [];
|
|
||||||
|
|
||||||
for (let i=0; i<items.length; i++) {
|
|
||||||
const item = items[i];
|
|
||||||
|
|
||||||
// Hide fragments
|
|
||||||
if (a.#getCheckBox(11)) {
|
|
||||||
if (item.href.startsWith("#")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide Blank Links
|
|
||||||
if (a.#getCheckBox(15)) {
|
|
||||||
if (String.isNullOrWhitespace(item.href)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide mailto/tel
|
|
||||||
if (a.#getCheckBox(13)) {
|
|
||||||
if (item.href.toLowerCase().startsWith("telno:") || item.href.toLowerCase().startsWith("mailto:")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const absoluteUrl = new URL(item.href, currentUrl);
|
|
||||||
|
|
||||||
// Hide external links
|
|
||||||
if (a.#getCheckBox(12)) {
|
|
||||||
if (currentHostname != absoluteUrl.hostname) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show anchor as html
|
|
||||||
let text = (a.#getCheckBox(1) ? item.innerHTML : item.innerText);
|
|
||||||
|
|
||||||
// Hide Blank Anchors
|
|
||||||
if (a.#getCheckBox(14)) {
|
|
||||||
if (String.isNullOrWhitespace(text)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve relative url
|
|
||||||
const href = (a.#getCheckBox(4) ? absoluteUrl.href : item.href);
|
|
||||||
|
|
||||||
// Trim anchor text
|
|
||||||
if (a.#getCheckBox(2)) {
|
|
||||||
text = text.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push({
|
|
||||||
text: text,
|
|
||||||
href: href,
|
|
||||||
title: (a.#getCheckBox(6) ? item.title : ""),
|
|
||||||
target: (a.#getCheckBox(7) ? item.target : ""),
|
|
||||||
rel: (a.#getCheckBox(8) ? item.rel : ""),
|
|
||||||
type: (a.#getCheckBox(9) ? item.type : ""),
|
|
||||||
occurrence: ""
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show occurrence
|
|
||||||
if (a.#getCheckBox(10)) {
|
|
||||||
// Calc occurrences, store in cache
|
|
||||||
let occurrenceCache = [];
|
|
||||||
for (let i=0; i<result.length; i++) {
|
|
||||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
|
||||||
|
|
||||||
occurrenceCache.push(occurrence);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update result with occurrence
|
|
||||||
for (let i=0; i<result.length; i++) {
|
|
||||||
result[i].occurrence = occurrenceCache[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide duplicates
|
|
||||||
if (a.#getCheckBox(5)) {
|
|
||||||
result = result.distinct();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort by anchor text
|
|
||||||
if (a.#getCheckBox(3)) {
|
|
||||||
result = result.orderBy("text");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#generateTHeader() {
|
|
||||||
const a = this;
|
|
||||||
const columns = [
|
|
||||||
{ id: 6, name: "Title" },
|
|
||||||
{ id: 7, name: "Target" },
|
|
||||||
{ id: 8, name: "Rel" },
|
|
||||||
{ id: 9, name: "Type" },
|
|
||||||
{ id: 10, name: "Occurrence" }
|
|
||||||
];
|
|
||||||
|
|
||||||
let html = "";
|
|
||||||
html += "<th>Anchor Text</th>";
|
|
||||||
html += "<th>Address</th>";
|
|
||||||
|
|
||||||
for (let i=0; i<columns.length; i++) {
|
|
||||||
if (a.#getCheckBox(columns[i].id)) {
|
|
||||||
html += "<th>" + columns[i].name + "</th>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
#getCheckBox(num) {
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
if (a.Panel1 == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = a.Panel1.querySelectorAll("input[id='checkbox" + num + "']");
|
|
||||||
if (result.length <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result[0].checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
#writeOptionsPanel(htmlContent) {
|
|
||||||
const a = this;
|
|
||||||
|
|
||||||
if (a.Panel1 == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Panel1.innerHTML = htmlContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const popupService = new PopupService();
|
|
||||||
const aContentService = new AContentService(popupService);
|
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", async function(event) {
|
|
||||||
|
|
||||||
aContentService.InitialiseComponents();
|
|
||||||
|
|
||||||
// aContentService.Button1.addEventListener('click', async function (e) {
|
|
||||||
// const body = aContentService.Table1.querySelectorAll("tbody")[0];
|
|
||||||
// body.innerHTML = "";
|
|
||||||
|
|
||||||
// const result = await popupService.GetHyperlinks();
|
|
||||||
|
|
||||||
// for (let i=0; i<result.length; i++) {
|
|
||||||
// const item = result[i];
|
|
||||||
|
|
||||||
// // const absoluteUrl = new URL(item.href, url);
|
|
||||||
|
|
||||||
// // memoBox1.innerText = absoluteUrl.hash;
|
|
||||||
// // console.log(absoluteUrl);
|
|
||||||
|
|
||||||
// body.innerHTML += aContentService.GenerateRow(item.innerHTML, item.href, item.title, item.target);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// PageAssetsCRX.HomeApp.mount("#App1");
|
|
||||||
|
|
||||||
// const panel2 = document.getElementById("nav-hyperlinks");
|
|
||||||
|
|
||||||
// const optionsPanel = panel2.querySelectorAll("div[role='options']")[0];
|
|
||||||
|
|
||||||
// optionsPanel.innerHTML = "";
|
|
||||||
|
|
||||||
// let html = "";
|
|
||||||
// html += contentService.GenerateCheckBox(1, "Show Anchor as HTML", false);
|
|
||||||
// html += contentService.GenerateCheckBox(2, "Trim Anchor Text", true);
|
|
||||||
// html += contentService.GenerateCheckBox(3, "Sort By Anchor Text", true);
|
|
||||||
// html += contentService.GenerateCheckBox(4, "Resolve Relative URL", true);
|
|
||||||
// html += contentService.GenerateCheckBox(5, "Hide Duplicates", true);
|
|
||||||
|
|
||||||
// html += contentService.GenerateCheckBox(6, "Show Title", true);
|
|
||||||
// html += contentService.GenerateCheckBox(7, "Show Target", true);
|
|
||||||
// html += contentService.GenerateCheckBox(8, "Show Rel", true);
|
|
||||||
// html += contentService.GenerateCheckBox(9, "Show Type", true);
|
|
||||||
// html += contentService.GenerateCheckBox(10, "Show Occurrence", true);
|
|
||||||
|
|
||||||
// optionsPanel.innerHTML = html;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const label1 = document.getElementById("label1");
|
|
||||||
// const button1 = document.getElementById("button1");
|
|
||||||
// const checkbox1 = document.getElementById("checkbox1");
|
|
||||||
// const table1 = document.getElementById("table1");
|
|
||||||
// const memoBox1 = document.getElementById("memoBox1");
|
|
||||||
|
|
||||||
// const messageService = new MessageService();
|
|
||||||
|
|
||||||
// memoBox1.focus();
|
|
||||||
|
|
||||||
|
|
||||||
// button1.addEventListener('click', async function (e) {
|
|
||||||
// const body = table1.getElementsByTagName("tbody")[0];
|
|
||||||
// body.innerHTML = "";
|
|
||||||
|
|
||||||
// const result = await popupService.GetHyperlinks();
|
|
||||||
|
|
||||||
// for (let i=0; i<result.items.length; i++) {
|
|
||||||
// const item = result.items[i];
|
|
||||||
|
|
||||||
// // const absoluteUrl = new URL(item.href, url);
|
|
||||||
|
|
||||||
// // memoBox1.innerText = absoluteUrl.hash;
|
|
||||||
// // console.log(absoluteUrl);
|
|
||||||
|
|
||||||
// body.innerHTML += popupService.GenerateRow(item.innerHTML, item.href, item.title, item.target);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// memoBox1.innerText = await popupService.GetLocation();
|
|
||||||
|
|
||||||
// const body = table1.getElementsByTagName("tbody")[0];
|
|
||||||
// body.innerHTML = "";
|
|
||||||
|
|
||||||
// const result = await popupService.GetHyperlinks();
|
|
||||||
|
|
||||||
// for (let i=0; i<result.items.length; i++) {
|
|
||||||
// const item = result.items[i];
|
|
||||||
|
|
||||||
// // const absoluteUrl = new URL(item.href, url);
|
|
||||||
|
|
||||||
// // memoBox1.innerText = absoluteUrl.hash;
|
|
||||||
// // console.log(absoluteUrl);
|
|
||||||
|
|
||||||
// body.innerHTML += popupService.GenerateRow(item.text, item.href, item.title, item.target);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (let i=0; i<result.items.length; i++) {
|
|
||||||
// const item = result.items[i];
|
|
||||||
|
|
||||||
// body.innerHTML += popupService.GenerateRow(item.text, item.href, item.title, item.occurrence);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
popupService.SendMessage("GetNodes", async function(payload) {
|
|
||||||
const body = table1.getElementsByTagName("tbody")[0];
|
|
||||||
body.innerHTML = "";
|
|
||||||
|
|
||||||
let result = payload;
|
|
||||||
const totalCount = result.length;
|
|
||||||
|
|
||||||
result = result.distinct();
|
|
||||||
result = result.orderBy("text");
|
|
||||||
|
|
||||||
const distinctCount = result.length;
|
|
||||||
|
|
||||||
if (totalCount <= 0) {
|
|
||||||
label1.innerHTML = "Hyperlinks (0)";
|
|
||||||
} else if (totalCount == distinctCount) {
|
|
||||||
label1.innerHTML = "Hyperlinks (" + totalCount + ")";
|
|
||||||
} else {
|
|
||||||
label1.innerHTML = "Hyperlinks (" + distinctCount + "/" + totalCount + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
// memoBox1.innerText = JSON.stringify(e);
|
|
||||||
|
|
||||||
for( let i=0; i<result.length; i++) {
|
|
||||||
body.innerHTML += popupService.GenerateRow(result[i].text, result[i].href, result[i].title);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
|
|
||||||
chrome.tabs.sendMessage(tabs[0].id, { event: "GetNodes" }, async function(payload) {
|
|
||||||
|
|
||||||
const body = table1.getElementsByTagName("tbody")[0];
|
|
||||||
body.innerHTML = "";
|
|
||||||
|
|
||||||
let result = payload;
|
|
||||||
const totalCount = result.length;
|
|
||||||
|
|
||||||
result = result.distinct();
|
|
||||||
result = result.orderBy("text");
|
|
||||||
|
|
||||||
const distinctCount = result.length;
|
|
||||||
|
|
||||||
if (totalCount <= 0) {
|
|
||||||
label1.innerHTML = "Hyperlinks (0)";
|
|
||||||
} else if (totalCount == distinctCount) {
|
|
||||||
label1.innerHTML = "Hyperlinks (" + totalCount + ")";
|
|
||||||
} else {
|
|
||||||
label1.innerHTML = "Hyperlinks (" + distinctCount + "/" + totalCount + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// memoBox1.innerText = JSON.stringify(e);
|
|
||||||
|
|
||||||
|
|
||||||
for( let i=0; i<result.length; i++) {
|
|
||||||
body.innerHTML += popupService.GenerateRow(result[i].text, result[i].href, result[i].title);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// chrome.tabs.sendMessage(tabs[0].id, { data: "hello" }, response => {
|
|
||||||
|
|
||||||
// Print response on popup.html
|
|
||||||
|
|
||||||
// var msg = document.createElement("h3");
|
|
||||||
|
|
||||||
// msg.innerHTML = "H1:" + response;
|
|
||||||
|
|
||||||
// document.getElementById("container”).appendChild(msg);
|
|
||||||
|
|
||||||
// memoBox1.innerHTML = response;
|
|
||||||
|
|
||||||
// alert("!");
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// document.getElementsByTagName("a").array.forEach(e => {
|
|
||||||
// memoBox1.innerHTML += e.href + "\n";
|
|
||||||
// });
|
|
||||||
|
|
||||||
// var switch1 = document.getElementById("switch1");
|
|
||||||
// var switch2 = document.getElementById("switch2");
|
|
||||||
// var switch3 = document.getElementById("switch3");
|
|
||||||
// var switch4 = document.getElementById("switch4");
|
|
||||||
// var switch5 = document.getElementById("switch5");
|
|
||||||
// var switch6 = document.getElementById("switch6");
|
|
||||||
|
|
||||||
// // read local storage
|
|
||||||
// chrome.storage.local.get(['switch1'], function(result) {
|
|
||||||
// switch1.checked = result.switch1;
|
|
||||||
// });
|
|
||||||
// chrome.storage.local.get(['switch2'], function(result) {
|
|
||||||
// switch2.checked = result.switch2;
|
|
||||||
// });
|
|
||||||
// chrome.storage.local.get(['switch3'], function(result) {
|
|
||||||
// switch3.checked = result.switch3;
|
|
||||||
// });
|
|
||||||
// chrome.storage.local.get(['switch4'], function(result) {
|
|
||||||
// switch4.checked = result.switch4;
|
|
||||||
// });
|
|
||||||
// chrome.storage.local.get(['switch5'], function(result) {
|
|
||||||
// switch5.checked = result.switch5;
|
|
||||||
// });
|
|
||||||
// chrome.storage.local.get(['switch6'], function(result) {
|
|
||||||
// switch6.checked = result.switch6;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // set values
|
|
||||||
// switch1.addEventListener('change', function (e) {
|
|
||||||
// chrome.storage.local.set({ switch1: e.target.checked}, function() {
|
|
||||||
// // do nothing
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// switch2.addEventListener('change', function (e) {
|
|
||||||
// chrome.storage.local.set({ switch2: e.target.checked}, function() {
|
|
||||||
// // do nothing
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// switch3.addEventListener('change', function (e) {
|
|
||||||
// chrome.storage.local.set({ switch3: e.target.checked}, function() {
|
|
||||||
// // do nothing
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// switch4.addEventListener('change', function (e) {
|
|
||||||
// chrome.storage.local.set({ switch4: e.target.checked}, function() {
|
|
||||||
// // do nothing
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// switch5.addEventListener('change', function (e) {
|
|
||||||
// chrome.storage.local.set({ switch5: e.target.checked}, function() {
|
|
||||||
// // do nothing
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// switch6.addEventListener('change', function (e) {
|
|
||||||
// chrome.storage.local.set({ switch6: e.target.checked}, function() {
|
|
||||||
// // do nothing
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
});
|
|
2
src/.gitignore
vendored
Normal file
2
src/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/dist
|
||||||
|
/node_modules
|
16
src/package.json
Normal file
16
src/package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "peji-inspektor-popup",
|
||||||
|
"version": "0.1.0.110",
|
||||||
|
"devDependencies": {
|
||||||
|
"css-loader": "^7.1.2",
|
||||||
|
"sass": "^1.77.8",
|
||||||
|
"sass-loader": "^16.0.0",
|
||||||
|
"style-loader": "^4.0.0",
|
||||||
|
"webpack": "^5.93.0",
|
||||||
|
"webpack-cli": "^5.1.4"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack",
|
||||||
|
"watch": "webpack --watch"
|
||||||
|
}
|
||||||
|
}
|
14
src/src/popup.js
Normal file
14
src/src/popup.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// src/popup.js
|
||||||
|
import PopupService from './popup/popup-service.js';
|
||||||
|
import AContentService from './popup/acontent-service.js';
|
||||||
|
|
||||||
|
|
||||||
|
const popupService = new PopupService();
|
||||||
|
const acontentService = new AContentService(popupService);
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", async function(event) {
|
||||||
|
|
||||||
|
acontentService.InitialiseComponents();
|
||||||
|
|
||||||
|
});
|
493
src/src/popup/acontent-service.js
Normal file
493
src/src/popup/acontent-service.js
Normal file
@ -0,0 +1,493 @@
|
|||||||
|
import '../../../literyz-js/extensions.dist.js';
|
||||||
|
|
||||||
|
import ContentService from './content-service.js';
|
||||||
|
|
||||||
|
|
||||||
|
class AContentService extends ContentService {
|
||||||
|
#containerPanel = null;
|
||||||
|
#popupService = null;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(popupService) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.#popupService = popupService;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitialiseComponents() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
a.Clear();
|
||||||
|
|
||||||
|
a.#initialiseComponents_Options();
|
||||||
|
a.#initialiseComponents_Filters();
|
||||||
|
|
||||||
|
a.Button1.addEventListener('click', async function (e) {
|
||||||
|
a.Button2.disabled = true;
|
||||||
|
|
||||||
|
a.TextBox1.value = "";
|
||||||
|
|
||||||
|
await a.Search();
|
||||||
|
|
||||||
|
a.Button2.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
a.Button2.addEventListener('click', async function (e) {
|
||||||
|
a.Button2.disabled = true;
|
||||||
|
|
||||||
|
await a.Search();
|
||||||
|
|
||||||
|
a.Button2.disabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#initialiseComponents_Options() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
let col1 = "";
|
||||||
|
col1 += a.GenerateCheckBox(1, "Show Anchor as HTML", false);
|
||||||
|
col1 += a.GenerateCheckBox(4, "Resolve Relative URL", false);
|
||||||
|
|
||||||
|
let col2 = "";
|
||||||
|
col2 += a.GenerateCheckBox(3, "Sort By Anchor Text", true);
|
||||||
|
col2 += a.GenerateCheckBox(2, "Trim Anchor Text", true);
|
||||||
|
|
||||||
|
let col3 = "";
|
||||||
|
|
||||||
|
let html = a.GenerateCols(col1, col2, col3);
|
||||||
|
|
||||||
|
a.SetHtml(a.Panel1, html);
|
||||||
|
}
|
||||||
|
|
||||||
|
#initialiseComponents_Filters() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
let col1 = "";
|
||||||
|
col1 += a.GenerateCheckBox(12, "Hide External Links", true);
|
||||||
|
col1 += a.GenerateCheckBox(5, "Hide Duplicates", true);
|
||||||
|
col1 += a.GenerateCheckBox(14, "Hide Blank Anchors", true);
|
||||||
|
col1 += a.GenerateCheckBox(15, "Hide Blank Links", true);
|
||||||
|
|
||||||
|
let col2 = "";
|
||||||
|
col2 += a.GenerateCheckBox(11, "Hide Fragments", true);
|
||||||
|
col2 += a.GenerateCheckBox(13, "Hide Mailto/Tel", true);
|
||||||
|
col2 += a.GenerateCheckBox(16, "Hide Javascript", true);
|
||||||
|
|
||||||
|
let col3 = "";
|
||||||
|
col3 += a.GenerateCheckBox(6, "Show Title", true);
|
||||||
|
col3 += a.GenerateCheckBox(7, "Show Target", false);
|
||||||
|
col3 += a.GenerateCheckBox(8, "Show Rel", false);
|
||||||
|
col3 += a.GenerateCheckBox(9, "Show Type", false);
|
||||||
|
col3 += a.GenerateCheckBox(10, "Show Count", false);
|
||||||
|
|
||||||
|
let html = a.GenerateCols(col1, col2, col3);
|
||||||
|
|
||||||
|
a.SetHtml(a.Panel2, html);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
get Button1() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("button")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get Button2() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("button")[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
get Container() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.#containerPanel == null) {
|
||||||
|
a.#containerPanel = document.getElementById("nav-hyperlinks");
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.#containerPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
get Label1() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("span[role='label']")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get MemoBox1() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("textarea")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get Panel1() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("div[role='options']")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get Panel2() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("div[role='filters']")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get Table1() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("table")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
get TextBox1() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.Container.querySelectorAll("input[role='textbox']")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Clear() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
a.Table1.style.display = 'none';
|
||||||
|
a.MemoBox1.style.display = 'none';
|
||||||
|
|
||||||
|
a.SetHtml(a.Panel1, "");
|
||||||
|
a.SetHtml(a.Panel2, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
async Search() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
a.Label1.innerText = "";
|
||||||
|
|
||||||
|
a.Table1.style.display = 'none';
|
||||||
|
a.MemoBox1.style.display = 'none';
|
||||||
|
|
||||||
|
const result = await a.#popupService.GetHyperlinks();
|
||||||
|
const totalCount = result.length;
|
||||||
|
|
||||||
|
const newResults = await a.#filterResult(result.copy());
|
||||||
|
|
||||||
|
if (newResults.length == totalCount) {
|
||||||
|
a.Label1.innerText = "Showing " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||||
|
} else {
|
||||||
|
a.Label1.innerText = "Showing " + newResults.length + " of " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a.#getRadioGroup(2)) {
|
||||||
|
case "table":
|
||||||
|
a.#renderTable(newResults);
|
||||||
|
break;
|
||||||
|
case "csv":
|
||||||
|
a.#renderCSV(newResults);
|
||||||
|
break;
|
||||||
|
case "links":
|
||||||
|
a.#renderLinks(newResults);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async #filterResult(items) {
|
||||||
|
const a = this;
|
||||||
|
const currentUrl = await a.#popupService.GetLocation();
|
||||||
|
const currentHostname = (new URL(currentUrl)).hostname;
|
||||||
|
|
||||||
|
const radioGroup1 = a.#getRadioGroup(1);
|
||||||
|
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
for (let i=0; i<items.length; i++) {
|
||||||
|
const item = items[i];
|
||||||
|
|
||||||
|
// Hide fragments
|
||||||
|
if (a.#getCheckBox(11)) {
|
||||||
|
if (item.href.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide Blank Links
|
||||||
|
if (a.#getCheckBox(15)) {
|
||||||
|
if (String.isNullOrWhitespace(item.href)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide mailto/tel
|
||||||
|
if (a.#getCheckBox(13)) {
|
||||||
|
if (item.href.toLowerCase().startsWith("telno:") || item.href.toLowerCase().startsWith("mailto:")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide javascript
|
||||||
|
if (a.#getCheckBox(16)) {
|
||||||
|
if (item.href.toLowerCase().startsWith("javascript:")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const absoluteUrl = new URL(item.href, currentUrl);
|
||||||
|
|
||||||
|
// Hide external links
|
||||||
|
if (a.#getCheckBox(12)) {
|
||||||
|
if (currentHostname != absoluteUrl.hostname) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show anchor as html
|
||||||
|
let text = (a.#getCheckBox(1) ? item.innerHTML : item.innerText);
|
||||||
|
|
||||||
|
// Hide Blank Anchors
|
||||||
|
if (a.#getCheckBox(14)) {
|
||||||
|
if (String.isNullOrWhitespace(text)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve relative url
|
||||||
|
const href = (a.#getCheckBox(4) ? absoluteUrl.href : item.href);
|
||||||
|
|
||||||
|
// Trim anchor text
|
||||||
|
if (a.#getCheckBox(2)) {
|
||||||
|
text = text.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search term
|
||||||
|
if (!String.isNullOrWhitespace(a.TextBox1.value)) {
|
||||||
|
if (radioGroup1.value == "anchor") {
|
||||||
|
if (!text.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!href.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push({
|
||||||
|
text: text,
|
||||||
|
href: href,
|
||||||
|
title: (a.#getCheckBox(6) ? item.title : ""),
|
||||||
|
target: (a.#getCheckBox(7) ? item.target : ""),
|
||||||
|
rel: (a.#getCheckBox(8) ? item.rel : ""),
|
||||||
|
type: (a.#getCheckBox(9) ? item.type : ""),
|
||||||
|
occurrence: ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show occurrence
|
||||||
|
if (a.#getCheckBox(10)) {
|
||||||
|
// Calc occurrences, store in cache
|
||||||
|
let occurrenceCache = [];
|
||||||
|
for (let i=0; i<result.length; i++) {
|
||||||
|
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||||
|
|
||||||
|
occurrenceCache.push(occurrence);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update result with occurrence
|
||||||
|
for (let i=0; i<result.length; i++) {
|
||||||
|
result[i].occurrence = occurrenceCache[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide duplicates
|
||||||
|
if (a.#getCheckBox(5)) {
|
||||||
|
result = result.distinct();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by anchor text
|
||||||
|
if (a.#getCheckBox(3)) {
|
||||||
|
result = result.orderBy("text");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#generateTHeader() {
|
||||||
|
const a = this;
|
||||||
|
const columns = [
|
||||||
|
{ id: 6, name: "Title" },
|
||||||
|
{ id: 7, name: "Target" },
|
||||||
|
{ id: 8, name: "Rel" },
|
||||||
|
{ id: 9, name: "Type" },
|
||||||
|
{ id: 10, name: "Count" }
|
||||||
|
];
|
||||||
|
|
||||||
|
let html = "";
|
||||||
|
html += "<th>Anchor Text</th>";
|
||||||
|
html += "<th>Address</th>";
|
||||||
|
|
||||||
|
for (let i=0; i<columns.length; i++) {
|
||||||
|
if (a.#getCheckBox(columns[i].id)) {
|
||||||
|
html += "<th>" + columns[i].name + "</th>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
#getCheckBox(num) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = a.Container.querySelectorAll("input[id='checkbox" + num + "']");
|
||||||
|
if (result.length <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result[0].checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
#getRadioGroup(num) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (a.Container == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = a.Container.querySelectorAll("input[name='radioGroup" + num + "']:checked");
|
||||||
|
if (result.length <= 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderTable(results) {
|
||||||
|
const a = this;
|
||||||
|
const thead = a.Table1.querySelectorAll("thead")[0];
|
||||||
|
const tbody = a.Table1.querySelectorAll("tbody")[0];
|
||||||
|
|
||||||
|
thead.innerHTML = "";
|
||||||
|
tbody.innerHTML = "";
|
||||||
|
|
||||||
|
a.Table1.style.display = 'table';
|
||||||
|
|
||||||
|
// Write thead
|
||||||
|
thead.innerHTML = "<tr>" + a.#generateTHeader() + "</tr>";
|
||||||
|
|
||||||
|
// Write tbody
|
||||||
|
for (let i=0; i<results.length; i++) {
|
||||||
|
const item = results[i];
|
||||||
|
|
||||||
|
let row = [ item.text, item.href ];
|
||||||
|
|
||||||
|
if (a.#getCheckBox(6)) {
|
||||||
|
row.push(item.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(7)) {
|
||||||
|
row.push(item.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(8)) {
|
||||||
|
row.push(item.rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(9)) {
|
||||||
|
row.push(item.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(10)) {
|
||||||
|
row.push(item.occurrence);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody.innerHTML += a.GenerateRow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderCSV(results) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
a.MemoBox1.value = "";
|
||||||
|
a.MemoBox1.style.display = 'inline-block';
|
||||||
|
|
||||||
|
for (let i=0; i<results.length; i++) {
|
||||||
|
const item = results[i];
|
||||||
|
|
||||||
|
let row = [ item.text, item.href ];
|
||||||
|
|
||||||
|
if (a.#getCheckBox(6)) {
|
||||||
|
row.push(item.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(7)) {
|
||||||
|
row.push(item.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(8)) {
|
||||||
|
row.push(item.rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(9)) {
|
||||||
|
row.push(item.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.#getCheckBox(10)) {
|
||||||
|
row.push(item.occurrence);
|
||||||
|
}
|
||||||
|
|
||||||
|
a.MemoBox1.value += a.GenerateCSVLine("\t", row);
|
||||||
|
a.MemoBox1.value += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#renderLinks(results) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
a.MemoBox1.value = "";
|
||||||
|
a.MemoBox1.style.display = 'inline-block';
|
||||||
|
|
||||||
|
for (let i=0; i<results.length; i++) {
|
||||||
|
const item = results[i];
|
||||||
|
|
||||||
|
a.MemoBox1.value += a.GenerateCSVLine("\t", [ item.href ]);
|
||||||
|
a.MemoBox1.value += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default AContentService;
|
88
src/src/popup/content-service.js
Normal file
88
src/src/popup/content-service.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// import '../references/extensions.dist.js';
|
||||||
|
|
||||||
|
class ContentService {
|
||||||
|
|
||||||
|
GenerateCheckBox(num, label, checked) {
|
||||||
|
let html = "";
|
||||||
|
html += "<div class=\"form-check form-switch\">";
|
||||||
|
html += "<input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"checkbox" + num + "\" " + (checked ? "checked" : "") + ">";
|
||||||
|
html += "<label class=\"form-check-label\" for=\"checkbox" + num + "\">" + label + "</label>";
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateCols(...args) {
|
||||||
|
let html = "";
|
||||||
|
|
||||||
|
for (let i=0; i<args.length; i++) {
|
||||||
|
html += "<div class=\"col\">" + args[i] + "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateCSVLine(delimiter, ...args) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (args.length === 1) {
|
||||||
|
if (Object.getDataType(args[0]) == "array") {
|
||||||
|
args = args[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = "";
|
||||||
|
for (let i=0; i<args.length; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
result += delimiter
|
||||||
|
}
|
||||||
|
|
||||||
|
result += args[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateRadioBox(groupNo, num, label, value, checked) {
|
||||||
|
let html = "";
|
||||||
|
html += "<div class=\"form-check\">";
|
||||||
|
html += "<input class=\"form-check-input\" type=\"radio\" name=\"radioGroup" + groupNo + "\" id=\"radioBox" + num + "\" value=\"" + value + "\" " + (checked ? "checked" : "") + ">";
|
||||||
|
html += "<label class=\"form-check-label\" for=\"radioBox" + num + "\">" + label + "</label>";
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateRow(...args) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (args.length === 1) {
|
||||||
|
if (Object.getDataType(args[0]) == "array") {
|
||||||
|
args = args[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = "";
|
||||||
|
for (let i=0; i<args.length; i++) {
|
||||||
|
result = result + a.GenerateRowCell(args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "<tr>" + result + "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateRowCell(value) {
|
||||||
|
return "<td class=\"\"><input type=\"text\" class=\"display\" readonly=\"readonly\" value=\"" + value + "\" /></td>";
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHtml(element, htmlContent) {
|
||||||
|
if (element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.innerHTML = htmlContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default ContentService;
|
37
src/src/popup/popup-service.js
Normal file
37
src/src/popup/popup-service.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import '../../../literyz-js/extensions.dist.js';
|
||||||
|
|
||||||
|
|
||||||
|
class PopupService {
|
||||||
|
|
||||||
|
async SendMessage(eventName, callback) {
|
||||||
|
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
|
||||||
|
chrome.tabs.sendMessage(tabs[0].id, { event: eventName }, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetHyperlinks() {
|
||||||
|
const a = this;
|
||||||
|
const baseUrl = await a.GetLocation();
|
||||||
|
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
a.SendMessage("GetNodes", async function(payload) {
|
||||||
|
resolve(payload.copy());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetLocation() {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
a.SendMessage("GetLocation", function(payload) {
|
||||||
|
resolve(payload);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default PopupService;
|
60
src/webpack.config.js
Normal file
60
src/webpack.config.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const { version } = require('./package.json');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
|
||||||
|
|
||||||
|
class PrependVersionPlugin {
|
||||||
|
apply(compiler) {
|
||||||
|
compiler.hooks.emit.tapAsync('PrependVersionPlugin', (compilation, callback) => {
|
||||||
|
Object.keys(compilation.assets).forEach((filename) => {
|
||||||
|
if (filename.endsWith('.js')) {
|
||||||
|
const asset = compilation.assets[filename];
|
||||||
|
|
||||||
|
const headerText = `/*!\n * Peji Inspektor/Popup v${version}\n * Copyright 2024-2024 Ray Lam (https://www.hiimray.co.uk)\n *\n */\n`;
|
||||||
|
|
||||||
|
const newContent = headerText + asset.source();
|
||||||
|
|
||||||
|
compilation.assets[filename] = {
|
||||||
|
source: () => newContent,
|
||||||
|
size: () => newContent.length,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: {
|
||||||
|
popup: './src/popup.js'
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: `[name].dist.js`,
|
||||||
|
path: path.resolve(__dirname, '../'),
|
||||||
|
library: 'PejiInspektor',
|
||||||
|
libraryTarget: 'umd',
|
||||||
|
globalObject: 'this'
|
||||||
|
},
|
||||||
|
mode: 'production', // development|production
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env.VERSION': JSON.stringify(version)
|
||||||
|
}),
|
||||||
|
new PrependVersionPlugin()
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.scss$/,
|
||||||
|
use: [
|
||||||
|
'style-loader',
|
||||||
|
'css-loader',
|
||||||
|
'sass-loader'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user