Полезная информация

Будьте в курсе последних изменений в мире Mozilla, следя за нашим микроблогом в Twitter.

№30110-05-2022 13:07:04

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 99.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Спасибо. И второй и третий варианты на Win 7 работают.

Отсутствует

 

№30212-05-2022 00:48:51

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 99.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Вы можете этот скрипт изменить, что бы он открывал библиотеку в текущей вкладке, если вызван из библиотеки открытой во вкладке?
userChrome.js/openLibraryContextMenu.uc.js · alice0775 · GitHub
   
Что бы скрипт заработал во вкладке, надо удалить в нем строку
if (location.href == "chrome://browser/content/places/places.xhtml") return;
или поставить ! после скобки.
Автору бестолку писать.
   
Вообще, хорошо бы еще и пункт скрывать при пустой строке поиска.
А в идеале, написать новый скрипт, что бы он работал везде и переходил в папку в том документе из которого вызван: библиотека, библиотека во вкладке,
сайдбар, Sidebar Tabs.

Отсутствует

 

№30312-05-2022 07:23:42

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
UA: Firefox 78.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt
Так есть же. Разве нет?


Или сугубо под 91?
Вроде нашёлся какой-то древний код (для custom_script.js), может подойдёт?
Если нет, то подкинь ещё подробностей.
Это я к тому, что сейчас времени нет, но если появится, то могут пригодиться.

скрытый текст

Выделить код

Код:

try {({
	run(func) {
		var topics = ["quit-application-granted", "chrome-document-loaded"];
		var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
		for(var t of topics) obs.addObserver(this, t, false);
		this.observe = (subj, topic) => this[topic[0]](subj);
		this.q = () => topics.forEach(t => obs.removeObserver(this, t));

		this.run = async doc => {
			var code = `(${func})(document.getElementById("placesContext_editSeparator"));`;
			var ps = await doc.ownerGlobal.ChromeUtils
				.compileScript("data:charset=utf-8," + encodeURIComponent(code));
			(this.run = ps.executeInGlobal.bind(ps))(doc);
		}
		var re = /\/(?:places|bookmarksSidebar)\.xhtml$/;
		this.c = doc => re.test(doc.documentURI) && this.run(doc);
	}
}).run(sep => {
	var label = "\u041F\u0430\u043F\u043A\u0430 \u0437\u0430\u043A\u043B\u0430\u0434\u043A\u0438";
	var popup = sep.parentNode, listener = {
		handleEvent() {
			if (this.shouldHide) return;

			var menuitem = document.createXULElement("menuitem");
			menuitem.setAttribute("label", label);
			menuitem.setAttribute("oncommand", "creator.goParentFolder();");
			menuitem.creator = this;
			sep.before(menuitem);

			this.handleEvent = e => {
				if (e.target != popup) return;
				var sh = this.shouldHide;
				if (Boolean(menuitem.clientHeight) ^ sh) return;
				if ((menuitem.hidden = sh)) return;
				menuitem.disabled = false;
			}
		},
		get shouldHide() {
			var node = popup._view.selectedNodes.length == 1
				&& popup._view.selectedNode;
			return !(node && PlacesUtils.nodeIsBookmark(node)
				&& node.parent.type == node.RESULT_TYPE_QUERY);
		},
		get goParentFolder() {
			var tree = popup._view;
			if (tree.id.startsWith("b")) {
				delete this.library;
				var func = () => this.sidebar(tree);
			} else {
				delete this.sidebar;
				var list = document.getElementById("placesList");
				var func = () => this.library(popup._view, list);
			}
			delete this.goParentFolder;
			return this.goParentFolder = func;
		},
		sidebar(tree) {
			var {bookmarkGuid} = tree.selectedNode;
			if (tree.result.root.uri.startsWith("place:terms="))
				tree.place = tree.place;
			tree.selectItems([bookmarkGuid]);
			this.scroll(tree);
		},
		async library(tree, list) {
			var {bookmarkGuid} = tree.selectedNode;
			var {parentGuid} = await PlacesUtils.bookmarks.fetch(bookmarkGuid);

			if (PlacesUtils.getConcreteItemGuid(list.selectedNode) == parentGuid)
				list.selectItems([PlacesUtils.virtualAllBookmarksGuid]);
			else {
				var rows = list.view._rows, lastRow = rows[rows.length - 1];
				if (lastRow.bookmarkGuid == PlacesUtils.virtualAllBookmarksGuid)
					lastRow.containerOpen = true;
			}
			list.selectItems([parentGuid]);
			this.scroll(list);

			tree.selectItems([bookmarkGuid]);
			await new Promise(requestAnimationFrame);
			this.scroll(tree);
		},
		scroll(tree) {
			var pos = .4, visibleRows = tree.getPageLength();
			var ind = tree.view.selection.currentIndex;
			var first = tree.getFirstVisibleRow();
			var newFirst = ind - pos*visibleRows + 1;
			tree.scrollByLines(Math.round(newFirst - first));
		}
	};
	popup.addEventListener("popupshowing", listener);
	addEventListener("unload", () =>
		popup.removeEventListener("popupshowing", listener)
	, {once: true});
});} catch(ex) {Cu.reportError(ex);}

Отсутствует

 

№30412-05-2022 23:54:25

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 99.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Получается только для 91 нужен, им еще долго пользоваться. В 100 функция работает идеально, открывает папку там где нажат пункт.
Тот код что вы выложили только в окне работает. В окне у меня работает и тот код что по ссылке, да и вообще везде, вот только, вместо перехода на месте, из вкладки переходит в окно, а из Sidebar Tabs в нативный сайдбар.
В общем, как минимум, нужен код для Sidebar Tabs, как максимум аналог функции из [firefox]100.

Отсутствует

 

№30513-05-2022 02:42:36

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
UA: Firefox 78.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

код что вы выложили только в окне работает

Быть этого не может.

скришотцы с 91

Выделить код

Код:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaMAAAGtCAIAAAA0/YzTAAAACGFjVEwAAAAEAAAAAHzNZtAAAAAGdFJOUwAAAAAAEHMRF/UAAAAaZmNUTAAAAAAAAAGjAAABrQAAAAAAAAAAAJYAZAAA+4lIWQAAECFJREFUeNrsnUFO20AYRjkEbLhENqxLJSo5C0Bq9yzYdVGhCPUGXfQCkegNkOgBItErwAGiXKBALxCx6ZhR8jn97IlcCxRnnvSE3PHMeDKJX+e3nfw78/kzAMAWc3d3h+kAANMBAGA6AIC35OTk4/vDD4+Pf5oqhF2hwunpJ0wHAD023d7uvmRXp7lQIVTDdADQO+Syw3dHkl2d5kIF7UqYbjq5CrVfKKbz54fp7WD3YDJ9Wq02O7JC39WW8ah4Oa64GN+mDpH9Gw+A7Go1lzZd9FoxXWxfT2ba+2qmS/eA6QAgIbuE5mQ6X9ANisuHSgmmA4BNlp1pLm06SSTGjK6VuOKLQeUPL4zRbqx/PbkpC9WVItOj0dWy29HoPLZKiMzaNh3i6aI4iNXGYSma/UcBIBPZJTSXMJ2UEX0h74SNReFkfLmnwnIjrgeDdGK1cmFo1/ist7aX4dTWDxGOXnow+7cfIA90bc5uUKRN5xfsotcWfgklQwW2KowLK625FruWy7EoR93oMEWuNZ239UOUI4nqzP4TALDF+C2IgGTX1nRx4SZzpUxXTBs8FZeHQUOqVpYctzJdsq0OsRwz0StAPpoL2wGT3fo7EjdVg8RoNBG9ehCqEklKNzrKkpZrOm9be4iqoFnZAWSiufRzduk7EgpFV7yjKNLvSKiJbjXo5oCu/Q2K87OWazpv64f49zHA7D8NAPlorlZ2fEcCAPpKcJlrzmXH914BoN+mc8257PjeKwDwq00AAJgOAADTAQBgOgAATAcAgOkAADAdAACmAwBMBwCA6QAAMB0AQD9Mp2wMPfr5o3QCCpVsFJptfmwK4FVIZ0H8VslxozxhPTOdfiB+40yXnu3sP5cAbx29KiNib/BfXf+lkg1Fs43pAN7SdAr9anMYepquUGixWNzrDWNb1fGuVFL5GfdWpoviqHZlaRLv47YiR60BY4VZU7rFhuHplTYNuNNsLwZW2tBHpWQakubPcmx6devnmRS6kI3pFPTpxHaVSE8znWDJbDirJbOzcLomutKuUPN40N50vqG0GA1mVJYMS1hhWSx8eMocZK9ddJtt9ZlOAhlF6W/K+nnGdJDdmk55toppcx7C4ao7ykI729XQV1v1Xal5OGNbhp9qGHpL5DBz06lCRRaqYIUaXgvTdZlt9dk8qmKq/0i0NpTX0vOM6SBD05kmPA/h/rA4Ds6yK02phuYL70ox45llj02ihp6tsbvpFCFqeBYAdoheE5PmpvNRLZOixb8eF6+dZ0wHGZluMv5eTT+4ty6HYfXqkq+kvKGv++oXYvJFW9PpKlvg/6NXDdLTLWp43n9iwN1nO5FnMm4PlT7NTJecZ0wHOZlOcZOuZKdzGMZdg+LL5/DXVlLW8D6aaPUQ1cqxE53J/2E6rVncZX7DwZ9KCaiwLqNj3fD0jEhqwN1n+7lhVJJa9WpdrKCBNc8zpgO+I9EVu5Bn/9wwXJS9GJWC7uw/3ACYbktNF6NXnsgD4Huv22g6Bbw8EAeA6QAA0wEAYDoAgL6abufr7/4yz/4tBABMBwBA9AoAmA4AANMBwF/2zqeljSiKo/lWrvpNql0IfgQ33WdjN2GYlRQSqLhJFoqhm64iFALFrDTpxkIrlGLaVQNxld7mMrnTuePTJDDJdM6PQ5hc359JDYf7GlTAdAAAmA4AANMBAGA6AABMBwDwhOnO+7cvow8vXncAALYckZUoaxXTdQffP97+mhFCyNZHZPWu/21F0625d61WmxFCSCHBdIQQTLe86fr9frPZjKJIHuUa0xFC/ivTTafT09PTi4uLu7s7eSqPci0VTEcIKbHpfDcnassUpSL1XNM1Dn3qw/FkRgghW2s6ad/u7+/TFe3spJ5vuqzXxg1MRwjZctNFUeSLWsd0hBB6uqzpJuNhPTnQ9kbjzFeHl+1Dmztpx3UbacPk4rDR6enSySxNQ1fsdRr6XIf5uZn1dVM/MZmrCbwEtz4hpIz/T9ftdjPFTqcj9SVNJxdqB/WFFu2rrTjWomqofTl0i4ylriu4yJT48X1trhs/Dqh5flftSeAl+PUJIWU0nTR0URSJ7Bafvcq1NnRLme6vGrTtSjqvdLM2fzryI9OLxFn92VLWYcnQUS/drOXPlaJuYRZLT7SK9GhPvgRbnxBSKtOZ5prNpjwOBgPp40R58nhzc+N2XMt0V6Or1qNCsVNkHMeBs6EsKK5J5lrX5ueqwurSrOXenk20mwy/BF2fcyshZTSdaS6w0+qnV2up0s1X+PQ6UZ0FTJcozE6Xbq4NTq+cP9FuMvASbH3aOkJKZrrpdPqk5lb/REIrielMOv/W/ScSKkFVkh1d59GiDpg/bbW0NcvOPTmxFWxTN/GrrmsRr+W9BH9vfMxMSClMZ7Kr7s+9WkNnT/m4gRB+wh/TEUIwHSGEbIvpCCGkPKbjdw4TQvidw3l8+fH7/eefAAClQJTF3wYDAP42GAAApgMAwHQAAJgOAADTAQBgOgAATAcAgOkAANNV/V8BADAdAACmAwComukODj4txUPlvwcAUErTzZ4dTAcAmA4AgNMrAICxtumOj9/u7b0qoKer5eX6evhQ+W8VABTR0+3u7onsCjBdxmuYDgCKM52X3fqnV0wHANtmOpPdRnq6/f392jxy4QbbtTzWkiwW2dnZSZ+FAwI9OnqTnh7e14puCz9RsTHubs/OzvPXr/zbFGADphM2e3p1tsovijhEWwsNadEP89iU4L4yQLZw40M3rMPSFRWcKi9//cq/RwE2cHoVCj+9mrlcX6axoqDXvgvztvKtnzVx1mHl7ysaWmjUbeFv2Cp6S+m7Te+rm9r6lX+DAhRnOq+5Yns6k0Kge/LDFPWLTHGmszOmd8qi7vY108mAwBZ+ornseab7w9759aQNhXHY77SL3Y8ldBAdGO/1wrnPMf+QOUSuSfwz9LPNabahuAm0PbR78WRN0zc9uhmhjOfkST0th9IEefKeUvpj3gowg6tMrOZmZbpEJdJ/cPYqhtLO+jfTOV7XDtAv4T5gWTpmr9JJ75+yDuB/u3LYbbrklL8sHTWdVUZ69mrH2zHu2Wvm+wf7LPfrvky1Bw94SbXM0dpn6f37C/9vCsCvweYGq7bUKneRAcB0mA4A+N0rAAB34gQAwHQAgOkAADAdAACmAwDAdAAAmA4AANMBAMzQdEsvOn+Fv/DvAQDMpeniP0367gGYDgAwHQAApgMAmH7e69PP0+mMGJtiQ0IYABQo71XkpfquAdp0OqqGfGsAKFbe69NNl7mruE2ZwXQAUKC816ebLpMjY0u8vDhXR5qEHi8CJdoVANM9NiHsuU2XpGTZ2FN3nKvbdBmtSJ9oVwBM9yjNPbfpEsElynPEudq+Iwo2E/dFtCsApntYc1MwnS2I3CGqgmP2qscT7QqA6R6V9/rcV5noKknntNqNbtNpY6YfJdoVANPN+MphfZ7LHefqNp3+HoBoVwBMx28kCDwEwHSYDtMBYDru2gQA3IkTAADTAQBgOgAATAcAgOkAANMBAGA6AABMBwCwIKbrdDrtdrvVah1OWst2Un1h0mRMp8NlwwAwn6Zrtw/jOB6NwjAcy+poFEjHmMj3zXAY+L5sj4LAyBiRnb/wbwAAzKXppHATi33Y3vY8b2d35/Lqe7VaXV5e3ms0vl5+293be+N5r0slGSMj/YV/AwBgjk3XaDRuf97t73+86f+q1WpBGK2srPRv76rVyo9e/8vFVRTHBwfckQ0A5ifvVZtO6jiZtEopJ7PX1dXVtbW191tbMnsV0133+hcXl8aM80yX3MeN8EMAKGjeq3zbIKaTCq5er9dqb42JpKaTLWI9ebRSqQwGo17vJopih+mSu41jOgAoSt6rrunK5XIUx55XDsxY7CYlXrPZHI78ZvOTbCyVXjnO09nQL0wHAMXNe221DsRifhAGoZGl2G3SCc1g6A/uV66vb+RPrM7T6TQZHcKQxLYmARGZFJtkzptJIJSnOBJjpx//qneVOVoUD1DovFfxl1hMPrrvNjfPz8+73c/STk9Ph36wsbFxdnbW7XZlVZlOpa8qs2RSaZKYQR3ElZPzkJMYO/X4V70rfbSYDqBwea/adLZFUWSMCcPQ3Lfx/TKKJn/zTGc//HmK0V5LSyTPdHa8IzF2yvGvelf6aDEdQOHyXrXppHyztdvR0ZGsrq+vS2V3fHxs+ycnJ9p0yRRScJvO1kF2cEKe6dwJ08L0418zu9JHywlKgOLmveqazt1+s3fHKAgDQQBFvf96g4jXCTbBLngbhwxuM0QDQpLiLQ+RLYLVJ5rFaa39nDVTx7z2juT7PnhwrXR9p14qHTX+tV6qf1qlg1OfHM7S5Y1bv6GLRxj5U939s3K/3tNdVlYmI6JQx7bGZqxaxpRR+z4x9pDxr/VSueOhM5y1dPU83bbVT5nUUtTNfF17UGsoIrBr6eJ5a8Tuuqy2rHhTV2RuGG5/li6/vRr/Cuxdunl+jeNji2l6brxmjaCjGIB/4gRQOkDpAJQOQOkAlA5A6QCUDkDpAJQOUDoApQNQOgClA1A6AKUDUDoApQOUDkDpAJQOQOkAlA5A6QCUDkDpAKUDUDoApQNQOgClA1A6AKUDUDpA6QCUDkDpAJQOQOkAlA5A6QCUDlA6AKUDeLNTxzQAAAAAgvq3NohsJPDQ6QCcDsDpAJwOwOkAnA5wOgCnA3A6AKcDcDoApwNwOgCnA5wOwOkAnA7A6QCcDsDpAJwOwOkAp7tXAJwOwOkAnA7A6QCcDsDpAJwOuHM6wOkAnA7A6QCcDsDpAJwOwOkAnA5wOgCnA3A6AKcDcDoApwNwOgCnA5wOwOmA2KkDEgAAAAAg/187omzQ6apOV3W6qtNVna7qdNXpqk5Xdbqq01Wdrup0VaerOl11uqrTVZ2u6nRVp6s6XdXpqk5Xna7qdFWnqzpd1emqTld1uqrTVaerOl3V6apOV3W6qtNVna7qdNXpqk5Xdbqq01Wdrup0VaerOl11uqrTVZ2usFPHNAAAAACC+rc2iGwk8BCcDsDpAJwOwOkAnA5wOgCnA3A6AKcDcDoApwNwOgCnA5wOwOkAnA7A6QCcDsDpAJwOwOkApwNwOgCnA3A6AKcDcDoApwNwOsDpAJwOwOkAnA7A6QCcDsDpAJwOcLp7BcDpAJwOwOkAnA7A6QCcDsDpgDunA5wOwOkAnI7YqQMSAAAAACD/XzuibFCdrup0VaerOl3V6arTVZ2u6nRVp6s6XdXpqk5XdbrqdFWnqzpd1emqTld1uqrTVZ2uOl3V6apOV3W6qtNVna7qdFWnq05Xdbqq01Wdrup0VaerOl3V6arTVZ2u6nRVp6s6XdXpqk5XdbrqdFWnqzpd1em0UwckAAAAAIL+v25HILhBANMBmA7AdACmA0wHYDoA0wGYDsB0AKYDMB2A6QDTAZgOwHQApgMwHYDpAEwHYDrAdACmAzAdgOkATAdgOgDTAZgOMB2A6QBMB2A6ANMBmA7AdACmA0wHYDqA8XQBJhuJ+CYlb8IAAAAaZmNUTAAAAAEAAAGiAAAAXwAAAAAAAAA4AJYAZAAAYqHD9wAACTlmZEFUAAAAAnja7J1dSyNXAIYHCv0RBX9FrnpZ+gt6vb1c9k8UZIrgx4UWETEgfmBchS1ebRKvSgLd2iTdkmwXhCLsLq0wbK0iNX6kW5u+5GxPx0xmEuwEnczz8DKcrznKEB7OmcmH02q965lC3WsPGcdx2gAAcbBZ/TXMZmgOAO47l5eX5XI5m826HVRQVY1D1Fy1Wl1fX19YWNBRZTQHAMOjXq9PT0+7AdSorvg1d3V1tb29nc/nDw8PVdVRZbWgOQAYkuPcSDQgZs1p7SavdTWqZYA13UHGGSscHKM5ABh8r2rXcdo7mkJXVQM0LE7NaeF2dHTU1ag1ndoj1IbmAOAWlEolt8PGxoaquh9nqiqourW1ZaoaFqfmdD9Ox57taA4A4mVpacn9F7NlLHcwO0s12icSd7aayzjvyTyaM5rLFXNjnZaHXxXQHABE41p8prOO8xPzvblCodDVuLOzo/YBVnPO2McPj1Uqzkl9B2gOAAbWnN2rChWGqDkt5bQ/lensk1aV7VIuWnPBMpoDgAE3rXavKrpMp2GxaU6O09MNHfUEVys4+U7H/f19daE5ABjeIwiZR9VKpWKqKqiq5xIxP4KwjmsHQHMAMKQ3lExNTdmHra6Pzc1NU9CAeN5QoncFhzkumrlHGfMIAs0BwH1/e7BMx2daAeBOTGfXdH7UqC4+ug8AI7J71Q04+0RCBVXVyDeUAABfxNRXcwAAo625vVcnbQCAe49kdRvNvX7b3P35mBBCEhEpK0pzhBAyAkFzhBA0RwghaI4QQtAcIYSgOUIIQXOEEILmCCFkoDie95YQQkY4aI4QguYIIQTNEUJIujRXKpUf9yKfLzQaP3mpv+iEkMRrLpfLtdvtv29yfX3daDSKxd1Kpeql/roTQpKtOf0+jvGan1arVa1Wm83m06f5589/9FJ/6QkhCdbc6urqdQB9cfuzDrVa7cmTr73UX3pCSII1t7y8LK/9dRNp7uTkRL+CeHp6urKyMuj/5zh7e9+rcOcJ/ieqvm9M/cuIkNRpLpvNymvvbqJN68XFxfn5uX4LUT/ME7Pmhn86RiMEzf2XxcVFee3PENSlAWiOEJJgzc3Pz0tnrQ5XPi47qFEDep744MHnTgcVrFxyucem0XW/9O8WhekNU5KOdjYNy2QytldT9Z3Tf3rYf2L/aPScasGShIyU5mZnZ6WzZgjaumrAgMsoFaQn/40wa5xgo/VIsNGvOWsuoy0VBpxTMwTP0oC+c4Zprrj7zSeffqao4KX+tUhIkjQ3MzMjnf0Rgro0IHiWdYToKRqzKFPVesQ2Rmuu71a075zR84fNKS1Gb58luHYHFbzUvxYJSZLmJicnz87OTkNQlwYEz/K7RoII6kONI6a5Dz78yGhOBS/1r0VCkqS5iYkJ6ew4BHVpQM+lXHB/am91qRq2wfRL0MwTtmmNEFZwzv+pua5NK5ojZKQ057qu3iL3Wwjq0oDgWUZV5haY8N/z6nraoK6uva21mxlv201Zx2jNhc1pT7+d5uy/hOYIGTXNjY+Pa8n2ewjq0oBUXWW7QozQnMKzCEISo7m1tbUvItGAVF1lrQe1lozWnI61Wl2mw3eEJEBzb9788uLFy1rth55Rlwak4eKaPbhB1QjNBX1nZFevv/RS/xolhK/VTGSiNadPBKvw7LsqpiMEzSUv/m1pT83Jcfo8nAr6/G+p9C1vqSPkn/bOpzWKJIzDH0UI7mnBQ5IZb54UD+J1LwYT8yGCrCGBCE6v38A9r7urRs0qq3dRo0ZNdJwlMJAwITMbXTT/jEnHbPSHBS/S3fYMKMGuepqH4e233qrpKToP1ZmkG80VbwXXbC0J+cvsZptznP4xTk2rq6v6VpovYQHQXPFWc3Kcrd0yHad1nBzn/igHzQF8JTyOeq+5e2/qyNGfnOl+PnMu33GtVkuai4OfNACeul8wLvz627Hjfe4b1XzHLSwsoDkANFdIun4od+K4ib/+/vHAoTj46QJAc0Vd0OU7bn5+fuj0WREHP10AaK54rK9vaEH34OGTHMfV63XVPJqaiYOfLgA0V+AFXY7jroxPcMUKgOYKv6C7c2cy03Gzs7NcsQKgOR8WdBJZpuNqtRpXrABozpMFXabjqtXqvq7eOPgpAkBzhaendFh/GZdJ1/7uId833WC1Uolu3bodB38mAJrzkxs3burR3Y1GY3f3Q5ibHvO2uLiox5NrKuLgzwdAcx4SRZF+yD8EvzWbLT0FKQ7+fAA05yGjo6NbW7GWcoGjSRgeHo6DPx8AzXmIfjm1y/Zp01TEwZ8PgOb81NzOzi7s7KA5QHP+au799v8g0BygOT/p/GdbD82p1f5RsOe0PxLtfv3hoTlAc95qbnNzuxPkkWq1ls7vfXeLvy1oDtCct5rbeLfdCZLLs+e1dH7vu1v8TUFzgOb81dz62600A6cGZRNtClxG8fjVCZesROddcnrmhcu4VqtU3mJXY6OprFw+aK0aqu2Yn3fPPBJ7o5wxLWOVCdAcoDlvNbe6tpmDpPB0uuqCUqmsQLufJ6+MX08kLRDppOo1jrUODAy6pGIFHY7pRrBeVtB2zHOVX6wyAZoDNOet5pZX3qW5dPmaraEeP3mujAWiv39QBdpV0mUsmahMdzcyK9uO2W787DGlxfSbJkBzgOa81dzrNxsJHk09kwtc3Ntb1q4CZRRY8s9L16zMcfLkKSUTlRZbYGRWth2z3fjZY+qA02+aAM0BmvNWc6/+e5vg9z+uygsKHjyckRT0qljB2NnIkgpcUsWJpPq6pF6tuwU2uCUTcXpMa82JLcgfUx/BkgnQHKA5bzX38uVamp6eknSgVzE5Oa2Mdvv6BvSq7eLFcVemJru2dWVCrS6jessrdhm1akxXaa0Wf2lM657ZKxGkW+2QxsYqlkyA5gDNeau5f5fWwuHe/WlpLqsJzQGa81dzzdZKOJw40d/dU8psQnOA5vxkZGSk1VpuNlf8pru7ZBfCmQVLS8uaijj48wHQnIfoXpJzc43F5krgaBK4rSagOZ9vkl6vzzUWXoUpOH1wfXxNAjdJBzTnLXraSxRFuo3wUJCbPngU8cgbQHMAAGgOAADNAQCaAwBAcwAAaA4AAM0BAKA5AAA0BwCA5gAA0BwAoDkAADQHAPAd8xEOzVf4yuPOhQAAABpmY1RMAAAAAwAAAaIAAAEnAAAAAAAAADYAlgBkAAHPstxvAAAXC2ZkQVQAAAAEeNrs3F1LFFEYwPH5CH2QCGK+RlfedSeEEQTRC0Zob6yZsWT0JjkVRZJEhgQFQYQXJUSERHgToWCOUBiBM2h0OT54YDjhmWe3tWLnnP/wc9hmzxxlXP6d2QWjKNrltLD45dXMmyfTzwGgy0msJFlVNavMXLryffVHJg8AoMtJrBaWvnaSOdn/U0VRRMH/egD8FWQOAJkjcwDIHJkDQObIHAAyR+YAkDkAIHMAQOYAkDkyB4DMkTkAZI7MASBzZA4AmQMAMgcAZA4AmfvDzAV/4QDUKHP89WAA/PXg32XZz5XVNQCoBUlWdeaC/38AgB/IHAAyBwBkDgDIHACQOQAgcwBA5gCgPeufG3FSsGfPnr2v+0i+AMBXUrqt1VzwFwKAr1jNAWA115GDyVzz9uPt+pOZnmQ5Dv66A6j9au7S+CPn5x1zHz4+mH65f/xTHPx1B1Dv1dzw2EOJmtP6xsa9qRc9txbj4K8+gBqv5oZuTEjRqrx99/7Y9Wdx8JceQI1Xc+ev3lcyt5ZlA1cm2pxKtt6nXXCxHD+J/NMcDP1lBIS4mjszeldypjh9+c4OM/ffT6doAKs5y0Az0TMnA8gcgBqv5k5eHNMzJwOcJ84uF2aTB2Vchl4XZpuct+8WZTPPViZJtnI2GZbm5lkzVcs57dOdP4n9TfU55QiVBPxazR1vXNMzJwP0Gex8pLn9RlhZHPugO3P2AztzZblMtuKk3TnT3D7LHqDPSeYA71ZzR86O6pmTAa4Ty+WSOzRmUWYyFCf2QT1zrW9FW8+pz++e02SRe17Ax9Xc4cGmnjkZsP0suzVp7shHmpM5AN2xmjt0akTPnAxwLeXc96eT8+Zg1Q2mHUEzj3LTqgTLMecOMsdNK+D1aq6v/4KeORngPDHNzVtgwn7Py/5koCyRfW9b1s2ML4+bx7LXM+ec0z69s8zJN+UjCMDT1dyBEw09czIgpKtsGhr6Sw3wajW3b3Cq9+g5hQwI6kLLejDNQ3+1AV6t5vbe/LWn+W338JKTPCUDQri4kratjaUcsMneHdy2DUNhHNcIPXkL3biBV8iJC2mD9pQNuEU9ATdQs4B9yCHopYIe8vA5eabQwIrj6P+BKBiJZmk1+pWybJrVgylz+UXI9sLqwZtj7lnSdT+eCfnWmX7nmc1tjzlCYO76szm+3+zL/OnMnU6naSp3ulL+PD1NLw4eCflKceY+4czi66g/u7y8/L1UjLmpjRkHc2QLzPGt+9uSzv7JbTYHcwTmYO6+S2M2B3ME5mAO5mCOwBzMwRzMEZiDuZsXmCMwB3MwB3ME5mDuzsvNmStD7l6Th3IkBOYo34m5Ifdd1w2lTvVahqne5+FICMxRrltuxdxYy05ce1VvV+p4JATmKHc3m5v+rqPELld9Kqdb8vCz7zT9YQZxl/Jobeb6YZ797XOednW2N6BT9Txc6hZWp8AczMHc6sz5dWseiu31+vjq0W+/sLXGhpQ0bjI3vu0W5iQwB3Mwd+WLVmUu2BJ7lOaJW28PUBNdN6tYHMEmcx7rmcAczMHclZgL7zm0PTLovEHInFe0h+XZ3Nwbt3phDuZgbpU7rSFblzyqb2CyukwDYY7AHOUu3jcXMBffgpAYbVy0EpijBMzpj3fzKQjmXwTmKF9/NtddznEhMEdgjvJR5pjNkQ8F5mAO5vjoPoE5CswRAnMUmCME5igwRwjMUWCOEJiDOZgjMAdzMAdzBOZgDuZgjsAczMEcITBHgTlCYI5y78zVMmz5m73GWlLKo1VYx3jFwBzS3YI5M06+42bMabc16XQpqqGwENR6gTnKLRZiMtf03B5r2bHoG4E5yrdgLkTN4Eul1om/89Uua2+TvqliK2jOWx7L406vdr2Zxbe0OvToQ3RVTok8Suu6PKepHXYSN9P1Pq3eGElwHKaM/uy8hyH3vtqo9uZtoq50hH2FOZiDuaswl9QRnd/FptTzvfqlheenbhsmrQfR87+vy8zV3tiKRuKdLDbbp2QbGyOJjoP/37D89Pcpj74lPKSyYH0eCszBHMytN5uLVUryyp3utcnLUKpR4pm2NJnzvLNMe4h26dTJn0UwEukkaCbDm38sVm+NRI+DRxBUpzqLbOnzoHRqVzqV82kgzMEczK342lyoUkrJzz3ZK/2cn+fzXG9hNmfiiBqyS82Nh9RmTjuJm/ml914AaowkOA7+TKMh+QODgWlXevB5bQ7mYG6FO63qWufihKYYSdpYz88VmHOFly9a45EowXGzKQtX3O8d1zFbXdvXMgSX8+cDaxxSmIM5mFvxfXMNU/SEd79y3scv/LsdH71ojS/clm9B2Ja4k7hZ8/6JdhIdh4cHOxoRi/ONi/0+pVIP3o885fOunEUuWmEO5m74KYhIHN5O24y+eKc/8q4dmIO5O2Wuu5zjZgNzYWAO5pjNkf8LzMEczPHRfQJzW8cF5giBOQrMEQJzFJgj/9i7g5uGgSiKolRBF9m5A3fhKtLFNOMu6MAVQAfpABShWF/R15cBJTb2uXoLC9lkZhYXj0PyQHNCcwDNHT00B5qjOZqjOdAczdEczYHmaI7mAJoTmgNoTh4QzV6gOZqjOc1eoDmaoznNXqA5mqM5zV7zafMJab9XfmG6IPXY/P2gOdHsdWWNZq+u6+Zt+3nok36v7MK4IMXY4rfGeyBAc6LZ68rzm71aO5+GdjNRi/MqL4wLko8tKesCzYlmr2c2e4Wbsn66/rAfp7clmisWJB571klzotlrzWaveNrYhqG1Ia8xzC+MC1KNzb/p0Jxo9lqp2St3ZaK5eGGxIMXYbFppTnRB4K/QHM3R3D40pzPst9AczdHcj3E3B5oTH90HaE5oDheaozmaoznQHM3RHM2B5miO5mgONPdyeLnQHEBzQnMAzQnNATQnNAfQ3NFDc6A5mqM5zV6gOZqjOc1eoDmao7nLRbMXaE40e2n2uuQlD/X04+9JR9KGU/iizY9qccLx+s1kNCeavfbV7FW/aD39qe+6ZCTldOrjjTST0Zxo9tpPs1cto3T6sSCijeP3cTKd+LZPuTjxnI00k9GcaPbaYbNXrbk4/Xkn24c9YDWSOMFyoVZuJvNsTjR77bXZq37RfPpJ18/9SKaxxd3uQs2t20xGc6LZa6/NXrXm8unfWSMZye09h9eu7xffza3ZTGbTKrog/gumvwloTmhuq9TTVzy2HJo7fGjucZj+JqA58dF90BzN0RzNgeZojuZoDjRHczQH0JzQHEBzQnMAzcnWNPcObAOao7lHae4T2AY0R3M2rV/s3dFN3EAUheGtYitxB26BJ1dBBXl1FXTgLpIKXEHSASUkoxHD0TDSCiVItvP9uqCFjMcWEj934vUcWLTSHM3RHGiO5miO5kBzNEdzAM0pmgNoTtEcQHOK5gCaUzQHmqM5mvu3muv3hqwxyXaLBM2pq2quhpvQHGhOXU9zGTa62fsbNKeuqbl9W0s8XeR+3iqRQFrTRStlQGbcxeBH+c3t2L3m+MWJ2pie/nrq+jpT9fJEXVRgZPcNDqzH5ph+qm8ZF1tTVv0doDl1Ms2NXhQiFr58f6qvC7+el/neDglXLuv2SHP7PE0PY5jHjHP4c/49lBTjH6WvzsVc46nib8Dre2o9aE6dSXN99Hp2PRm0fF/X5z/j3nS21pHRyhXeWsKkDMtzrdv26Yzq/noyRfseIr73Af5dg5kHDjrZ8VQ5z6yVozl1Os29bC9T+9UNHVSqAaPBmffyzXnbv4fmUknjBq2da17Whwnzcd4gridOmv3abZqm1nblArPNPDqwNWh1zHiqbV2WdaufX0Fz6lSaK8QqbKy5/D+7ZS0fnRS6Hmqsuei8/lJzzV9FW123GAd+7FLHB2bHN56qjJ+meX4zY9Nl98JqlubUETWXPUv+ht8K9bZDb6voffIWRC5ax5oL6Xxu0dpdT7u3cK/qCTfVf7pPT0/lc9+lfjjwRztjnDcHt0nKNdSfFc3RnPIUxGmIVi6/HODmA80pmnvnNuL1iHxCc2XR6uYDzSmauyR16erhEJpTNAfQnKI5gOYUzYHmaI7maA40R3M0R3OgOZqjOYDmFM0BNKdoDqA5RXMAzSmaA83RHM19mea2del2ZytfAjSnrht5M3lsEzSnLqW5timuHThAc+qymmtbD5V0h9xD+GEaVoZmye4Czakj34KoGTS5z1qfdNUYLXJld4Hm1KE117Y4z+CFTLoap2EVIkJBdhdoTh1Yc4MGKpKuxmlYsbKT3QWaUwfXXP+2kuhrhmlYvaQul93ldjPNqYu9by6ysir7IOmqT8PaI+/qatld3jlIc+rqT0GMI2DOi+yuL4Pm1HU1J7sLNKc803oyZHfRnKI5gOYUzQE0p2gOoDlFc6A5mqM5mgPN0RzN0Rxojub+b839BI4BzdHcb/buLadtIAoDcFaRlWQH2QWr6C5YTKtW6m0VbanIAlAfK1VgQmgSUJTajHoYoUmsKnFz+36dBxPMwIP1acbGc7pibimyH8Ec5ixaxaIVc5jDnGAOc5jDnGAOc5gTwZzCnAjmFOZEMKcwJ4I5hTnBHOYwt1XmXnZ+sD+4YE4dIXPRjCb1/eOcYE4dKXPp2C7hgjl1tMxFX/qCd4WG0/1ek7zDaT96A6a+iNmXeXPC+ldEg8Hncwj7N5jDHOa6uzcXJLUy1yt2iQ4rw75oel8ax0RSMIe5/z6bC7YKzyXitOz86GoaU7mYr6VvxTONxF8vpbVHtfuDmMMc5jpiLq0lc9QST83cLT4pnb/q2UXCrp7cxQnZ/K48m4sfqQRzmMNcd7O5NuZ6iaHAK/8wT5iVBol1LuYEc6deO7s3V1xChm7ZwdnZ8MX/2TV+ZYvWeOCQdItnDv3BcDgYWLQK5k699vktCM8KBHPqwJjrlVKtCuYEc8psTgRzyqv7Ipg7+cKcYA5zmMOcYA5zmMOcYA5zmBPBnMKcCOYU5kQwpzAngjmFOcEc5jCHOcEc5jC3lf3mmk0xRTCnjoU5G70J5tTJMFe3cDCPE8ypo2Xu/PxV2v8yEttkxt6ZsfNlebvN1M1rZfev9jHTH6AHGOYwh7kumAt38g/TJ+Wd0+M4PxgOBv2W7l+lMeOgIew5eoBhDnOY2xJzMfPK7Mhb2ET7rvXMPZ3zpqX7V3nMJnqAZcEc5jDXzb25Gpekxj8xF0oO6wVmS/evdWNGxy89wKoKc5jDXAfMxc21tNLMF5jhzkrmYtq1pvtX25ihoR5gmMMc5jpkLsGRKbNy5VgUrb37V3nMvIl1pQdYhTnMYW7/34LwlEAwpw64s1d7MCeYU2ZzIpg79fLqvmAOc5jDnGAOc5jDnGAOcwfB3E11++1q8nk0e/d903r9ZfJ+9Pj2YqrUbuvT5bS+qq9vMIe5J+a+Xk0ufsyryXw2e9iwxuPJYrGcTudK7bSa67m+qutrG3OYa5j7OJrd3j/c3U/Hk98b1s9f14+LZX2g1G6rvp7rq/rD5RRzf9g7u942iigM7w8AgZCalFJu4AaUxpXo5gZQaWK4QAihEok0VuAPcMNvoAWj/AMueoH4aolVzEeAqqlUimQaklLiSE3akDZJ203itut1bI8/0moZ75FH09mpHbRx0njfV6+qs2fPzoxd+9HM2PECczXM8cUmK1dzeRbcK7ft6j2XBzC87S6WKqcuAXPAnIQ5J8+Ce/m2Xbnn8gCGt9nAHKzB3BoL7uWMXVl3eQDD221gLvRWMFcsV7NrLLitjF1ed3kAw9vuAjBnAHMy5kpVe40F962MXVp3ffmZfYZfnSPTFj8Lwy1ygQFzwJyEuUKpejfHgvvmqs2qri/PMdf5XdrSZmC4Rc4DcwYwJ2OOVe/kWHDfWLWLVVfNe1A7mba0GRhukfNFYA6YkzCX55hzWHDfWLGLFdeXr0NNlzkWixie9sWG66dkURnVU0CV6oXCJ+ND9WsjfztMU6m2RknriNlpkLRjEyNvPDCRoZHUY3jrvQbMGcDcNmNOnxGBLjnDSXQsMdOwcTJhq0fkm7Ym6puNdqbPHJpv1JQ4xSt7OjYDc7v3Rk6fTd0JPbaAOTgo5m47LLiXVuxCxVXz3jv/RNrSZi4mhg0SZaRTIqbggNl5JJ6kFnQXMmGahXHu6Cr1rXnJyMWGY6MMn7I1GJg4xcdwLJEUTQUxx9xrff2/nU3xGN6ogTlYwdwaq2ayLLgXl+182fXlZ7r4u33K8mfmppK7jMhkLWMNmD1ejVxMMSWNA2ZP1+AwtaC7kCk+OhgZ+DSpVPpbI0+ODO8yh+Yajo3aPDoy02BgdOrzkS96eUZ6LEG8+5nILWulRrqxFD+EN+gcMGcAcxLmcsXqapYF98KyvVZ21bz3bv92yvJnJjy4XM2yq5wpVCMVi1gERC5+SnchU0zFSqW2NVG8gbFFJhoNjE5xqY8liDnmXNflpDvY1//rWIpn4I3YKQBzwNyDmFuxWXBft+xcyfXla+/2b/6xdBlrwNv432W+0Wv28IxcLGKlntPniuZCRv54MGJ48sqY0oWutfcOU5tNxjbeZSiKTGgGVsPcwCdJ5YEHMWFOkO6XsRRPws0MzIXercZcO9qbyvkPW2/CHEgHzMGBMOcUqss2C+5rlu2UXIrbzR7X/vIftt6EOYV0o2Mpfgpu4GwemAPmHsScdZcF9/wtO8tcHsCbZxVz9+/fX1q6ebC3/+czKSv0T87DDcyF3srPamZy1ZVsCZh7xDFHjFtfXy+Xy//OXwfpGpi/njM5/KwmMCf9SPrEQmXVqWQL1YBetQuFimvnK/Ammn9vTmEc/cddvjx7KNp/5twFO/RPkd/89cxf1ZPX8CPpwFz9ljeT14qjuOXNo+qndkf8jLNtO5PJXLo0tf/l/s++/PNU6J8lxT+nSxPzuOUNMIcbGO4QPb03omWcZVlLS0vj4xOH+g47EG5gCANzOxpzgnFXrswR4zjahIE5YA4G5nY85gTjHnviua++HrEsqzf67omT3zsQMAdvF+YWoM1T5559gnHJH0Zf7HqV1qo8WICaCZgD5lqFORfaPO15dj9n3ONPPn9h/CI/fPud95PJ0bm5OR78+NNpF2ooYA6Yw6J1B4hvvfF53NjZ3+mQBy90vTI7O3vu3Pnu/YccCItWGJhrP7351iBn3PT09Evm6w4EzMHAXPtpdvYqn9ANffDh+T9SDgTMwcAc5ABzwBwwB8xBwBwwB8wBcxAwB8wBc8AcBMwZoYcLMAdBwBzcxphbjJkdhqcOM7ZYy6S7jY5EmodboXQiLrpuqsV0ooPGBm1IwBwwF3rMedQw4om0ODzO4y3DHCGVBgC1QsAcMBd6zNXmcX7EbDXmMDtrnYA5YC7cmKOpXLcfcoSe44njtJSNxROUjce6DU/dsbgoi8c/MuplUrOUiRPC5KQh9UhTOXG50oVMYVrbegtbCYvScpvKqBeR0Q8SAubgUGHO1O2IEX08ptDGmYJCARoeEI+kMmkRmojHDFHpBVQps0Y+5U/yYmqfCBiXFtTEOF9TMu/0g8TyGJiDMZtT0CNiwgSJMpoygU4l2WEIEXQ0fem7qNMz+uDHI/7ByxkdFrFABuZg7M2RFByoWKGrzOaYa4QkfV/+LmhKyKds9K8DzAFzwBww9/8wR7Onhp+0iri+NaasB9Wyhy9a9fticiO6LmhlHY2aURrixhethDxgDpgD5sKOObFtr//enA8rXk00+vDZnECn5iOI5otWtQuRFJf4OjX0H0FQDTAHzAFzwFwLRdDBlj8EzMHtijnaHePTQ8ydIGAObivMyd9lw7c3IGAOxp/uQ8AcMAfMAXMQMAfMAXPAHATMAXPAHDAHAXOhh8ujhTkICof+a6cOCQAAABAA/X/tC4PCCDSnOdCc5iabgzOd5gJQjc0uEln6aAAAABpmY1RMAAAABQAAAaIAAAFMAAAAAAAAAFMAyABkAACXGG92AAAYyGZkQVQAAAAGeNrsnUFO3DAUhnOr3IGegeliJBZM1/QQ9AaIBdMtLOAI0O66RUVsYY3YRl20v2rpyfILTjNpsCb+ok+jN44dR8rok984iZuu+wUAsGDQHACgOQAANAcAUIvmjo5+jKKr/gIAwP5p7vc/b2gOANAcAABJKwDAHo3mmr7t/v5nV/11AoCFaM5LDc0BwLyaOzs7zxROTFrRHACU19zh4Wq1+piUiPcfza3Xa8XaFPjKFuvTsl07SNu2cQqcsefp6Ze4eb5fK/RdJA19Vu7P9vr6pv/41f9GAebVnJnOYlE2aXWq6i+UNeQsc5DtTQKPNcn3qwomJt+Fb2jV4hKzm772H7/6HyjAjJrzphPmuPdMWk1byVDIz1SIEPvxlwW+bXIOamX2eatfOcgc6rvwJ2wl4ZTis437VYUuPn71v06A2TXnc9VSUxBCQWbc1CsO85SaeM1ZaumFYuVv9atYFTJd+IaJyAY1R7oKUNdMq3lE8WDSKj15Ye2muUy/cUOLB09Yn5mkVUF8fAZ0AGU0VyRptf/49ZkZzZkvLGkN9VU+mLQmEw7WKtNvG22DJ9y4LT5ba+WP31X/GwXgYa/9IPFp0/BuGAA0h+YAgGdaAQB4rSYA1A6aAwA0BwCA5gAA0BwAAJoDAEBzAABoDgAAzQEAmivL8fFms/nUVX9tAGBRmnt4eHx5eQ3xwcEHEWIValdX/XUCgP3W3NPTs7ymEdzd3feTk8+KhQJ9VaFiVeiqv1QAUFJzfukvvVF9bKIa7ObRLld/+G3DLAkGAPNpzi8JNszt7bcgtcvLK43dxMXFNpRo11jNJdVYEREAzZU3nVLU4Li4MJhOu9AcAEzSXCnT+XRVEw7+P7uAzb0Oas6/ytwWQo3fn55ZJlV79RkvIaiA95UDoLl+zYkpmsv/Q9e4LdGcrRnoPZisOOMXzYnbKmDVVAA0N9pxPmlVlvpfklYLRNCWr5BZP9COaRUYygGguR0d56cgttuvYQpCwZQpiHiXNGcDt7zmfMMAawkCoLn0hpJRjlOuGu6P60W7JmrOhJVPWv0xFbR/N2YtANDc1Ecgwr9vGrjFtwfrqwrt9uAdNBdPO8QrsepzcJlUq88C+ABobpkPezH5AIDmZnx0XygoiCWtTD4AoLnFIsFxLzEAmgMAQHMAAGgOAADNAQCgOQD4w94drDYOA0AA7f//cU5bQdlBqwGRJZdaeuFRHMd1XdoOst1oEHOAmAMQcwBiDkDM6WkFvHVfTyugpxXg5J7WzJeZ+eAyhdyR04qMb9MkxnBXT2smSjo+4MI8xnBdT+vc0pC+wSOlR9FUxnBXT2tGNykeHB9T5bVMg57umzyNXj/SJI2uc1liBozd8ZpDWiZe7y17b0O2zxedj8E0n3BvT+scZ0m37vEaT/Nqn/3V+l2HzqbjNXvI9r1lvzp/oRqTdresf3WEa3paO+aWk9l5GLUMkZYo6fXpyulg2pQfdmxtahJ7fDcyLlncx+DyHFza07osd8zt71r2+nxiYuX9mBsfl5PQfRts9p+Yy/npcgxGc3BpT2v+/pNQfdKale/HXNJq7PzNk9bebbbvLZeYm4Mve+hjcG0ObuxpzZ3WZMfmFsRP4+p84T96/Vj4edqjud5zAiufnu03bbB9i2PeTx+DO61w8pu9FAy6MAf39rTmXRCn0v8PJmICEHOAmAMQcwBiDkDMAYg5ADEHIOYAfkXMfX39+S+v639ggJgD+N0x9/ch5oATY+7fh5gDnt/T2hm3Tzo9ra/rf2XhYT2tS8ZleVkZelrNNwcP6Gn9JOb0tJpyDh7W07o/Y+2Y09OqCwIe0dO6vza3Ls/0tGr2ggf0tH5yp1VPq8tz8LCe1o65Xp7paTWagwf0tH4ymtPT6tocHP5mLz2t7rTC4TGnp9WFOTg85vS0vq7/lQUzlACYVhMQcwBiDkDMAYg5ADEH3+yd707iQBRHn9wHQSxoghifRUDW3VcwflAgtJQ/fnF/6yQ3k7lL003jmoFjTprpdBja1JzcmQ69AGgOAADNAQCa+x4uLj7+BZYHAwCaAwBAcwCA5r5Bcx9lKWw3qUdzAJBlnlavOZE4Ds0BQN55WhukZrsMWgEg4zytfoiawNwcAOSdp9VPxnnHxaRnH/5cCi5fGRd4OSUAmvt/+b26a07ySsq+Ms2CevZ3HQDNfYHjOg5au2vOsqCe/S0HQHNf5bjujyC6a47hKgCa+8I8rd0XlHQftEpzBHQAaC6b5cHtNZdkQSWjMwCa48deAIDm0BwAoDk0BwBoDgAAzQEAoDkAADQHAGgOAADNAQCgOQAANAcAgOYAANAcAEDOmluva3E4+3sDAKepubLcjkZzocLh7G8PAGSfp7Wq9oGy3AWvqdzrPfT707retelBr8mM3wmsl8qFFwWrfGLwTlCALPO0Xl7ORFFMtL29/blYbLfb/dXV42DwqLJMZzGdCmWZii9ksTl5wRm6Ol3m4ez/awFyytNaFDNJ7fp6XhTTXm8yHj8tFtVgMFdZNToq9729VQrxRqOnfv/Bh3IilM8ha5cukHQWAJnlad3v35fLerncPD+v5TsJTpobDmfSnNynGhXu7mS6ejyeS3MN0Y1COSlP21CIQ7zwF7QY7xq+XjYJu6YVa6AvTXqO9aqjSYpY39L35jPJ+nMIXfGGd4DM8rSuVvX9/S/ZLajt5mYu5WlXg9bVaiP6/Ylius1mt9sd6vrgc0HEOjO7mVDMHdq1o37011Dvs0kkX6FKO2Q9WHvf0h/V1mWSbUh5wRoggKzytCpkC4GbBGeaC3FcaBDm6TRh10ZzyWA2DqOSEClRia9X4Vjefv91+mz4oNfWsZYuvnOZZN05MD0HkGWeVqlNsdvLSyU0GffXaE6m+xy0JnNzaWhzTHPNTy19vX3QtNJec9qqfUvN6ZD17zPJJudANAeQXZ5WH83NVBgOZbStfPdZng4GbefmzFB+0GqV7TVntlLnLQetvltr71smmovFZz34c2BuDiDL5cGS2mj0oyg0AfdnZcl4LKNV2qqsGtXrSevr68YvKImjtlg9DY8gZBCb1E9k4etVCLs+mvM9+wywcXvfUiRDaZH048+BJ60AWWrO/BWvEPY1noYnj6ybAwCnuZyxX0GcPLpMQjkA3lACAIDmAADNAQCgOQAANAcAgOYAANAcAACag9/s3c9rHGUAxvH/R8Wb4NWDKFLxYvFHK62lFEJa01KLqVDoRVFEqgfrQWZbkibbdNtURBvEi7QED3V3s/lhG1Jb2zSNSTSbnV/vOx7m9UlWBsniQhBcZ/cbPizvzry3gYc3M7PvA4CYA0DMAQAxBwDE3L/h+yb7ub4kPX9hAHRVzGmrpZGRmudVpFAoj47Orq6GSc9fGwDd0NOaZZy2z5Rz56YUcxoMDc34Pj2t9LQC+e9pDUObZVyxqPbCUBttDg/XdDAITOt8elrZbw7IWU9rFCWe1yy7qSngmgcVcNIcNNd0+mweoaeVLeeAnPW0GpOo/2Hr39VaFNltDyV0k65YrD14sKHF3YULM8pBelrpggDy1NPaPuaCwDbv02mC7tlpoK/0tNLsBeSop7X9P602DK2yb+txRHVxcWNsbFoxR08rt+eA3PS0tn8EoVZWlRaeP1/VcX3GcSK+b+hpZTUH5Kantf0LJTqiyCsUKhp7XiUIbHMyPa3cmwO65PVgLeWiyG417Zf1FCJ7zEpPK09aga76sZfSrdEw+qSnlRtzAD2t9LQCYIcSAMQcABBzAEDMAQAxBwDEHAAQcwBAzAEAMQeAmPtvWfuHufm5KXsaJD1/eQB0Y8ytzJsvXzRXX0pW7yQ9f3kAdFvMaQVnJz9Kb51KZ06aH86woAPQdTG3ctuOv+BsScyVXXaNBR2Arok5/a0uRNffT+cGmzGXzr5jbnyggzqTTWtTktC6CyZ7FgHofMyZ+Qlz48Po2kBYejW+9Fw6fcLFo85/VzTQVx3UqXDimKaZhe/ax1yGmAPwf4m56KtDaeUtt/aZC4f/Uj/u1o/K5iA7+OunaWUg+PowMQcgbzG39FM4vi+tHnF+wa31SSudSqsD4dX95tHt9lnW2sCQ7Zme9PyVBoi5zjBRHC1ON0qvp+XDbv2sW3pzGx1My32Ny3ujpVlrzI5iLquMYWUHEHMdfRlYSXe/4hd3u+WP3cN+98vLLrN01C2f8S++oijUNE3eQcxlp7LawJ6/2AAx18mkC69/kk7ucY9Ou4VdLvPwvfT73cHk2ZaM21nMaVlHzAHEXCeZ2PoTJ93UIXe3z9161t3Z6xZe2xzc609vHmx8e0oTNG1HMZfdktNXKpwBYq7TTNIo7nHzb7t7g+7+aTfT7+aObQ7uHtegUTqgCf8Uc3/vZt0Wc1n7Kks5gJjrMOvX694zmxn343479MTG5YP1Sxo87qoH3M8n6t7zJgqTnr9UAHIcc3qtZOOLp+zIY/WxfcHcN3HgS2NqfP3iG3b0yYb3dLzCr74A5Pre3G+L69cG/akrcRiYKDKxFQ0ifyOolnTK/L6c9PylAsC2mgBAzAEg5gCAmAMAYg4AiDkAIOYAgJj7k707eG0iCMM4/J8LoVAIBAwSMLRQLIG0x3qoVOpRD8mpUIRarId6EaMhNWmTUaO+NPIx2S+7pid3M7+Ph5LuTDcbprzMJu0MAJQ85h4/efogIfkBA1C9mHv25tOaiDkAxBwAlDXm9KAAMQdgE2Lud04Vx5yWmdO6cvFWrbYLxIbRy2TvHiC5mFOoKdE2PuCMXh179wBpxZxmN5LOhg96gZrTheR/a4GEYs5mN7b5gy2YHk/xFrWIxfhb44/bAusWK9Yh3hfRL8KuVjuuPr7nyrP55d3dNUSz1+R/a4GEYk4REMeZpZsFimWHvlWrz0efm+tsFWZP4faBtTNYf9fTtcZP5Oekmadm+x4g6ZjL3MzG06jMFCkTJf647djvg8k/ne0D62Mrr+fK+Z0yzrLYXwNvzwFJx5zkxVzxp5b+uP2gxcr6Maev6r9mzKkpc349tvvTzDUwmwPS+rs5f49pCeVvWnXwoTFnaaWTr3nT6k9r/X3PTMzFwWdn8NfAe3NAcv8FYbO2OHoKPoJQgqjiN/6NP64Hi2/9bM6f2QJL5d9Q8z0lvioffCp/DXzSCiQXc3mzG/5uDsAmxJz/L4iNp5fJVA5gISYAYFlNAMQcABBzAEDMAQAxBwDEHAAQcwBAzAEg5v6zXq9/uKpOT19dXX0IyQ8SgMrHXLfb1YJLv5ZrPp+fnZ2dnLw8P38bkh8nANWOuU6ns8i1uEIIvV5vMpkcH7+4uHgXkh8qABWOuf39/bmr6XT6+r76/f7R0fOQ/FABqHDM7e3tKdd+LpdibjgcDgaD0WikHPQ/ZetN2nriLDkJoKQxt7u7q1z7sVwhhLu7u9vb29lstrOzU3QGW6E3+eEEUNKYa7fbyrXvOaUmdfhnzLHeJIDyxlyr1VKchfuaRTW9Lx1Uh4J0i9dGt31O2RoGQIlirtlsKs4mOaVbV3UoiLn4gfzNu+SHFkCJYq7RaCjOvuWUmtRhnZjjBhZASWOuXq+Px+NRTqlJHYg5ABWOue3tbcXZ15xSkzoQcwAqHHNbW1vD4fBzTqlJHYg5ABWOuVqtpinbl5xSkzqE5IcKQIVj7uDg8FFhqUNIfqgAVDjmbm7G19cfLy/fr6QmdQjJDxUAltUEAGIOADEHAMQcABBzAEDMAQAxBwDEHAD8Ye9uWpuIojCO+4FEkCzyJVx1564giiAUX6hI6xtpqxKs+FZsVBSLRSyI4EJw4UIEESki3YggSLtxaUsLklV9yJHD4J25TQgE597/8PMymdy5LU54OJOBHvq0AugSc/RpBUDM0acVADFHn1YAxNxQfVqzv1QAsu7TSntDALXv00rMAci3T2u432w29dJa8duONW/tZn+9AWKurn1afd8yTn1aqeYAJNWn1fdFO9y0Aqhfn1ZiDkCOfVp1f6pv37SjkZtWAAn2aVW6+eOFfyo72ywE9S6PIABijj6tAIg5+rQCIObo0wqAmAMAYg4AiDkAIOYAoBdz299ajc4uIyMjY6rjPv0DgFQp6XrVXPb/EQBSRTUHgGpuJI51Vtv3n4cmO2/HOuuN7K8TgNpXc9cWn5X2aV39/OXJizeHF782sr9OAOpdzc0tPK3q07q9s/No5fXYve+N7K8WgBpXczN3liJ9Wj98/HTq9qtG9pcKQI2rucs3H0f6tP7a3Jy6sdTnUtrGX9r+6MV/E720g7l/7IAcq7kL8w/jfVrPX38wZMyN/HQSDaCaK5hqd+J9WjWBmANQ42ru7JWFeJ9WTSg98f36rm3a8XCZeff34PJa8W5Rm71bGUnafDVN29jyd7XUnmsWT6/6TfyHxtfUEVISSKuaO926Fe/Tqgl9llHaLJ78izBPnOCg50h4sBhznlwWW9rpc02tEJ5lE+JrEnNActXcxMX5eJ9WTSg70cul0qCxokwvPUf84J4x50pnDrRmuH7VmhaL3PMCKVZzJ6bb8T6tmhCcVcwaBUQYHzpIzAH4P6q54+euxvu0akJZKVd+f7q8ZgerbjCLIWjrRG5aI4EVrDlUzHHTCiRdzR2dnI33adWE8CyLKm0apfCdlz8ZCB8X2DRPN5vvx21fYzzmqtb00weNOc9WHkEAiVZzR8604n1aNSGbS+IZmvtHE0iqmjs0vTJ+8lKEJmR1YVQPbmzl/ukEkqrmDt79faD9c//cj1J6SxNyuBiKtt5GKQfw14MBgL8eDABUcwAyqebob8bIyJj0SDtqAHTdBwBiDgCIOQBIIub0RGMg3ewvAIA/7Z3fThtHFId5K+5LJRwsqEHcBpBI0+doEqymhnCN+FfDE6QvEfUm6k2E+gClRGn5kzTYay9Lf2Xao9UedoQUebWWv9Gnzex4ZjKA+XRmd/EZP83Zc/yqxzugOQBAcwAAaA4A4Ms1t7u7v7KyWsG1uampqfX19UJjp7Op9nfvTpKJ/2kBwAijucePV8x0cc25eqyD19z09LQZzRrRHACMXHNmulFrTtGcwjdref36Z7WgOQCoQnNmupFqTjrT0VpCcGeaC/VQ8kMK9Xv7B3saOi1MFXwaVOsnVKMtyQbqVT8wYH38SuTu++ef+LcjQC00J0atOf3CBxGoLqfc6y91CNqKa86ckq8XKGyT/TzqoIG+v3XzA4VfuX1R988/8e9FgEo1F3fcqDVndjPfWbsFRBb+5Fvy+rBik9t2ON+Sd58qfh6tpDDKB5J+YNhr51duo3JfV27+iX8jAlSqubjjKtCcKiHACbLzsjDi0ZyIaK7QHjr7eE31/HbSr8oP9IKOa47tKkAtHiiR40b9QImPj8xK1m6NEc15XfqeXnPmL7+pzPvR6vZq2UAdI5vWwiadgA5gIh4P9te2fLuOftPqNRe/8F+44WD/kSrhVMXp0opblRs45Up+JTbKz59M/NsRgL+CGAsslLNTPgYGAM2hOQDgg5gAAPhYTQAANAcAaA4AAM0BAKA5AAA0BwCA5gAA0BwAQMWa29nZ2d7e3traevVv2QqVXP2/U/XZ2eHZYAAYQ81tb7/SX3H1+8Ph8Ean/f5AlTTNkiTt9QZJovZsMEjVR6ZLJv67DwDjpzmFbFLY98+eNRqN5y+en73/s9lszs/Pb7Tbf5x9eLGx8ajR+HpmRn3UM5n47z4AjKvm2u32x0+fX7784fLq71arNRhmCwsLVx8/N5tzf51f/X76Pru93dzkE9YAYNzytJrmFMFpr6ogTpvWpaWl5eXl754+1aZVmrs4vzo9PUvTmzLN2eeykbcQAOqYp1W3F6Q5xW6Li4ut1jdpmimaU4uUp1fn5uaur/vn55dZdhvRnH1oOJoDgHrlabVobnZ2VtvSRmN2kN5IbQruOp1Or590Oj+qcWbmq7Jrc5ayC80BQD3ztEpzm1JYMhgOhqmOUpsqyTC97iXXdycXF5f659Zdm/PpYHwiBUu3akkeCmlobKtbSB6oIZFMr9WnbfVTFVaL3wHqm6dV8pLC9Hv77ZMnx8fH3e5PKoeHh71ksLa2dnR01O12deo057KmOq0U0spYhkCfRqskV0NJptfK07b6qfxq0RxATfO0muZCybIsTVM9Kaejys3dMctudCzTXPjNL/OLl1reIGWaC/0jmV4rTtvqp/KrRXMANc3TappT4Baitr29PZ2urq4qptvf3w/1g4MDrznbOYq45iwCUk+jTHPxtNCi+rSthan8arkoCVDXPK2muYcV3ZSIJIspS89qEgl1yxlYpjlr8VM5Kk3b6qey1aI5gPo+HmyaU8hmoZzuWYTLcwf/l9Duo7mpkhJ8ISP4dKtqVPFaDJjR4pleq0/b6qcKLdxiBqi35uy5uYcVe6DEa8I3hmPZbVnyGQJAdZrT3VWZbvOudO6KKr7Icbu7e1+iOdu0krYVACrV3MnJb2/e/PIQ3r79NTJP3IA8dQEAD+cfIcArVy6sH9EAAAAcdEVYdFNvZnR3YXJlAEFQTkcgQXNzZW1ibGVyIDIuOTH+/Sr4AAAAAElFTkSuQmCC

Отсутствует

 

№30613-05-2022 09:53:59

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Да, работает. Спасибо. Или с кодировкой что-то не то было или очки пора купить. :) Вопрос закрыт.

Отсутствует

 

№30713-05-2022 16:15:24

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Посмотрите кнопку Save.
Что хотелось бы пофиксить:
1. Через меню кнопки сохраняет pdf и html не в папку загрузок назначенную в браузере, а в папку загрузок в системном профиле пользователя.
2. Через меню кнопки не сохраняет выбранный текст в файл txt.
3. Через контекстное меню сохраняет выбранный текст в файл txt на рабочий стол.
Хотелось бы пути сохранения перенаправить в назначенную папку, а п.2 починить.
   
У меня ссылки на мод не сохранилось. Последнюю правку делал вроде по этим постам.

js

Выделить код

Код:

// var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
// var {console} = Cu.import("resource://gre/modules/Console.jsm", {});

try {CustomizableUI.createWidget({
	id: "ucf-cbbtn-Save",
	tooltiptext: "Сохранить страницу\n/ часть / выбранное",
	localized: false,
	get initCode() {
		delete this.initCode;
		return this.initCode = Cu.readUTF8URI(Services.io.newURI(
			"chrome://user_chrome_files/content/custom_scripts/custom_js/Save_Script.jsm"
		));
	},
	cbu: {
		types: {
			128: "Bool", boolean: "Bool",
			64: "Int", number: "Int",
			32: "String", string: "String"
		},
		getPrefs(pref) {
			try {
				return Services.prefs[`get${
					this.types[Services.prefs.getPrefType(pref)]
				}Pref`](pref);
			}
			catch {return null;}
		},
		setPrefs(pref, val) {
			Services.prefs[`set${this.types[typeof val]}Pref`](pref, val);
		}
	},
	gClipboard: {
		get ch() {
			delete this.ch;
			return this.ch = Cc["@mozilla.org/widget/clipboardhelper;1"]
				.getService(Ci.nsIClipboardHelper);
		},
		write(str) {
			this.ch.copyStringToClipboard(str, Services.clipboard.kGlobalClipboard);
		}
	},
	custombuttonsUtils: {
		writeFile(path, data) {
			try {
				if (path.includes(":\\")) path = path.replace(/\//g, "\\");
				var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
				file.initWithPath(path);
				file.exists() && file.remove(false);

				var strm = Cc["@mozilla.org/network/file-output-stream;1"]
					.createInstance(Ci.nsIFileOutputStream);
				strm.init(file, 0x04 | 0x08, 420, 0);
				strm.write(data, data.length);
				strm.flush();
				strm.close();
			} catch(ex) {
				Cu.reportError("Custom Buttons: " + [path, "---", ex, ex.stack].join("\n"));
			}
		}
	},
	addDestructor(destructor, context) {
		this._destructors.push({destructor, context});
	},
	addEventListener(...args) {
		var trg = args[3];
		if (!trg) trg = args[3] = this.ownerGlobal;
		trg.addEventListener(...args);
		this._handlers.push(args);
	},

	onCreated(btn) {
		var win = btn.ownerGlobal;
		btn._handlers = new win.Array();
		btn._destructors = new win.Array();
		win.addEventListener("unload", this, {once: true});
		new win.Function(
			"self,_id,cbu,xhtmlns,addDestructor,addEventListener,gClipboard,custombuttonsUtils",
			this.initCode
		).call(
			btn, btn, this.id, this.cbu,
			"http://www.w3.org/1999/xhtml",
			this.addDestructor.bind(btn),
			this.addEventListener.bind(btn),
			this.gClipboard, this.custombuttonsUtils
		);
	},
	handleEvent(e) {
		var btn = e.target.getElementById(this.id);
		for(var args of btn._handlers)
			args.pop().removeEventListener(...args);
		delete btn._handlers;
		for(var {destructor, context} of btn._destructors)
			try {destructor.call(context, "destructor");}
			catch(ex) {Cu.reportError(ex);}
		delete btn._destructors;
	}
});} catch(ex) {Cu.reportError(ex);}

jsm

Выделить код

Код:

self.label = "Save";
self._handleClick =()=> menuPopup.openPopup(this, "after_start");
self.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABGklEQVQ4EaWSvQ4BQRSFd/3EUouGksIDiNBLvMAqtVoaiShUHkItIRGd1iN4A0ql2l8wvruxw67FJuR87p05d85OFsP482PKeaVUjWpDDKpwgyAd2GyZprmiPkXAWFbUIvSld2EdgQ5UYApzKLl+xG2+VAuvDjZcoAldQspUI0yAzMXlS+D6e6qEtKlvAVc2o/CqI4sJTMF5Z4Qc6OU2hrw0eq01XZLrjah+ldhYgEeeAJIVbg9CyxMgp3j6kFqAIK15SP/V8ARwOI95ZqhBfRP+QCmVx9+4pv9XiGNc4JPEkxnt+wO0EbbRAVwtwyELfsl6zDpzOoBVFlLwSzIjs86c88cgscbKhgSkYQtByrG5gxPMeJlL6n+6A9I+WoE5cj6LAAAAAElFTkSuQmCC";


var folderpath="E:\Download";         // папка для сохранения иконок для ярлыков и ярлыков сайтов

// Создать меню для кнопки .............
var array = [
   { label: "Сохранить favicon сайта", func: "saveFavicon()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACPVBMVEX09ff////C3L+Uq8+Vq8+Uqs+Zr9CZrtCZr9Gfu+ear8+mt9JRf8ORxl3t8vfF06+Twojs8/d9otl8o9s+aquZrs/X9KLp8Pft8fZhisf//+DBzN2hveihv+pii8hti9pgicl6oNlojs1zncNsi836/P2duebx8/eYyWqBp+Gn0IKBvlKHsm9qmaVuk8zt7/FEbauEv1Tp7/JdhL9oi9Pl8e2LwlmdsdD7/P76+/3H7ofo8+peh8eHwFaSteZ0pkp2gl7q8/Ohy5OApt2by2eZuOqbuOWaezWuvtd7nN2HvWxul9Ty9feQxV5ljcqBp+JEcLCVtOOo0nR7odx5n9suX6Z1mtBzmtSXyGPv9PewzfOzx+O6zu/s8fd9o95Xfrthi8lYhMN5oNnw9ffw9Pjw9Pf8/f6ewO/m8O9zmdE6aapsjdyUwouPxWPDzd6XteOSs9B5nNVpnpqHt7h/s6F6n9d7ntSTttGHwVh4qp+Ev1HH7ox6qk5wj+Hm8e3t9fOm0IKAtqOBpNrx+P9ljcyhs9FpkM2hv+/u8/fF0eOLu4N+vFKgzX3p9OSFqN13qExekIl4n9j7/P3x9PhxmNDm8e9Vg8Zfkozr8veq0YTX9qL//92AtamOwnHFz96Fot1diMh+pd13ntmatu+YyW/3+/+Tqs5UgcShzJNbhsdTf8GHs7bo8PaXtuqMr+Ty8/SZt+SUqs7r7Ox3ndb9/f7t8feZyXGYyWWCpNbz9PRuiteNtNDn7/V4ntjx8fGo3JqNAAAAv3RSTlP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AEVuhDkAAAD+SURBVBhXY5jHzcUMAqxAICq9bx8D96adDFAgaGQOFOBaH7h7zoqZDTlFyptncAAFWBjyi52CXCI0unRLxcECPhsatbbzmlXMnS60hg0kkOxW0uNrq93tNaFpD1ggUm21QK532ZQdSm1hmXKdDCwdnOWVOi1RjNGMQCCrwMDMJ8NZ4LAynVGPkXFp8zpJBubYmn579wXtqhZb0iwn9a1iWLaViYmJ3891obOwYtLEvcYMGyWAAkwJdv6accEhi8LjGVr11SenpC5f61g3NcO0vjCAIc+DjZ2dnWexddWSbYa9nlkM+8BgWsxsK7FZ1VLzRaACNokmtdnyu1QMQgF7Rlh4zWWTAwAAAABJRU5ErkJggg=="},
   { label: "Копировать favicon в base64", func: "copyFaviconData()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAI2bv/9RVpf/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAACIkvD/Jia6/ywpq/8AAAAAAAAAAAAAAAAAAAD/AAAA/wbwAf90qpv/Ymic/1RWqP9OUKr/W2Ch/2dumf9YYKT/Ly/B/xQP3/8MB9P/JCGb/wAAAAAAAAAAAAAAAAAAAP8G8AH/U5ea/ycr8f8VIP3/HiP4/ywo8v8sIvb/LCL2/ywi9v8KBOj/BQDe/wQAtv8tK4P/AAAAAAAAAAAAAAD/BvAB/3Sqm/9iaJz/Tim3/0UuuP9GPrT/R0ex/zk8uf8gIMz/FRDe/xEMzv8jIJz/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8AAAD/SqOR/yImvP8sLKj/AAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/BvAB/3Sqm/9KW5r/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAABvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAG8AH/AAAAAAAAAP8G8AH/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/BvAB/wbwAf8AAAAAAAAA/wAAAP8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAG8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOesQQBjrEGAAaxBwACsQcABrEHDg6xBwAesQcAPrEHAD6xBw8+sQcPprEHD8axBwAGsQQABrEGAAaxB//+sQQ=="},  
   { separator: ''},
   { label: "Сохранить ярлык страницы как…", func: "saveShortcuts()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP8E/yT/BP8k/5XLDv/zqgD/86oA//I1///yNf//86oA//OqAP/zqgD/86oA//OqAP+Vyw7/lcsO/wT/JP8E/yT/BP8k/5XLDv+Vyw7/86oA//OqAP/yNf//8jX///OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//02AP/9NgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/9NgD//TYA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA/wA31v8AN9b/86oA//9If///SH//86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP8AN9b/ADfW//OqAP//SH///0h///OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/5XLDv+Vyw7/86oA//OqAP/zqgD/86oA/0CA//9AgP//86oA/07+9f9O/vX/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP9AgP//QID///OqAP9O/vX/Tv71//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/AACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQ=="},
   { separator: ''},  
   { label: "Копировать изображение / текст в base64", func: "copyFaviconbase()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AIAQ/wCAEf8AgA//AIAR/wCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AgBX/AIAVAAAAAAAAAAD/AIAo/wCA//8AgP//AID//wCA//8AgP//AIAoAAAAAAAAAAAAAAAAAAAAAP8AgBL/AID//wCA//8AgA3/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgBAAAAAAAAAAAAAAAAD/AIAR/wCA//8AgP//AIAK/wCACv8AgP//AID//wCAIf8AgAX/AIAh/wCA//8AgP//AIAQAAAAAAAAAAAAAAAA/wCACv8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAUAAAAA/wCABf8AgP//AID//wCACgAAAAD/AIAQ/wCADP8AgCH/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCABf8AgCH/AID//wCA//8AgAv/AIAh/wCA//8AgP//AID//wCA//8AgP//AIAH/wCAB/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AIAg/wCA//8AgP//AID//wCA//8AgP//AID//wCAB/8AgAf/AID//wCA//8AgP//AID//wCA//8AgP//AIAh/wCAC/8AgP//AID//wCAHP8AgBz/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCACf8AgA7/AIAMAAAAAP8AgAj/AID//wCA//8AgAP/AIAD/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCABQAAAAAAAAAA/wCADf8AgAr/AIAL/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCAB/8AgAr/AID//wCA//8AgCH/AIAH/wCAJf8AgP//AID//wCAI/8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAf/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgCT/AID//wCA//8AgAr/AIAK/wCA//8AgP//AIAKAAAAAP8AgCj/AID//wCA//8AgP//AID//wCA//8AgCP/AIAM/wCA//8AgP//AIAN/wCADf8AgP//AID//wCADQAAAAAAAAAA/wCAEP8AgBH/AIAP/wCAEf8AgBAAAAAAAAAAAP8AgBT/AIAVAAAAAAAAAAD/AIAV/wCAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQcH5rEGA8KxBAHCsQQBwrEEIQKxBAACsQQAArEEAAKxBAQCsQQwArEEAAKxBAACsQYAArEHBmaxB//+sQQ=="},
   { separator: ''},
   { label: "Сохранить страницу как PDF", func: "savePageToPDF()", image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYUw4pJt3V/+Rb1D8lnFP/55zTf+VcVH/lXJS/5VyUv+VclL/lXJS/5VyUv+VclL/k3BR/J56Wv9cRzSkAAAAAJNvUKTto2L/4ppe/uehZf/Pmmr/noZv/9Scav/Wl17/1plh/9eZYf/XmWH/15lh/9eZYf/WmGD/2Jlg/suRXP9mRiuk8rWA/397dP1akKn/rqqi/3LF3f8Mntj/4dLJ///+9f/48u3/9e7n//bt5v/47+f/+O/n//jv5//rvZP/1ZJX/a9/VP9+lrD8AIvz/xOt+f8Douv/ALb6/wC28/9tmar/z8jJ//Lq5/////7//v////n9///6/P3//////+Ta0P/PjVP/pnpT/IWds/+aiXj/5efl/8Px//951/3/LMz//wCx8/8GltL/NIu3/4ycqf/l29L////+//n6+//8/v//3tXM/8+OVP+oe1P/6K57/86QWP/r6Ob////////++v/r9/z/oOb9/zDL//8Arf//AI/r/ydysv+hpqr//PTr///////d1Mz/0I5U/6h7U//osH//wo5g/+fm5P/7/f//9vf5//z7+////vv/9/r8/5Dc/P8Oqv7/AJf//wF02v9ffZ7/8Ojh/+Ha1P/NjFL/qHtT/+ewf//Ej1//7O3r///////+/v7//v7+//f5+v/6+vv////8/8Tq/f8hp/7/AJH//wB18/8/bqj/1MGu/9mXXv+leVH/569+/8iSYv+/tKn/wLew/8O5sf/P0M////////7+/v/3+fv////7/9Hv/v8hoP3/AIn//wB4/v84ZqL/w4NH/619VP/nsYD/x45c/9W5of/bv6j/0Jxt/6J/YP+spqD/2N3i//7////6+/3///76/8vr/v8Slv7/AIb+/wBz//83VH7/nW1B/+ewfv/Fjl7/7Ozr///////9+/r/9d7K/9Ghdv+jd1D/pJ6Y/+jt8f/9///////7/6fb/v8Ahv7/AYD//wRp6f95YlT/57B//8SOXv/n5uT//v7///r7/P/8/v////////XRsv/DhEv/loBu/9DX3P/9/v/////7/2O6/f8Afv//FnTU/5JtTf/nsH//xY9e/+jn5f/+/f//+fj5//n4+P/5+Pn/+/////Xbxf/Wj1D/nX1h/+Ll6P////7/3+/3/w+V//8tcbP/qHJB/+WuffzCjV7/5efn///////+/v7//////////////v7///////XRsP/TnW3/8fT3//////////z/ddD//0Nxl/+zdkH88LmH/9CRWP2+qJT/0M7N/8/Jxv/Pysf/z8rH/8/Kxv/Py8n/zsO6/7+pmP/PzMv/zsnG/9bNyP+nsK7/h4R3/b2BT/+Sb1Ck7qxw/9GSW/69hlb/wYhX/8CIV//AiFf/wIhX/8CIVv/BiVj/xI1d/8CIVv/BiFf/vYZW/9STW/7ppmv/bE80pAAAAACUd16k+sui/+7AmPzwwpr/8MKa//DCmv/wwpr/8MKa//DCmf/vwZj/8MKa//DCmv/uwJj8+cui/5N3XaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="},
   { label: "Сохранить страницу / выбор как HTML", func: "savePageToHTML()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACzElEQVQ4jV2STW8bZRDHf/Psrr11nZhgVKcKaSmUiArRKBRVIMgH4BKJ7xAp5MSFiA+Rc28ckBAoipC4koJQLyAaVFChIlQllDRWmjRev8Qvu14/+wwHx6ZlpNFcZn7zn79GVJW1tbXc6urqijHGqKoAPF3TgcVaq8owXJbphx99fOOnWzcHoqqsr68/t7y83BARVBXnHHraXo3a3HoUU8gFAHRTS2Bg/7C2Zx7vXPIBwjA0p3BU9Zns9i3vvVrhr6MWzlpee+EsRqAbHc3+/Pee7wPkcrkx4P+g0IMvb/5Iv5/iXEaWZQS+By578MaVy9YH8H3fE5FnANZajqMmgcAnH7yN73mICMYMd21sbLy7srKiPkA+n3/qBLhzv8p+EuOfTUjShPbODvOVWa5fnRsvKBaLAcAIMFbw+bc/EBVn8At7SPcQ60LSiVm++P0fGu0e7y++yalvHoABCILAiAj7hzU+vfcVT6zPVGmR3x4/xJoLSH6BVu4cN777nnQwQETI5XL/AYwxRkS4ff8BEk6Q2pBfq3dxUuHMmWt0kgFGStTDY/7YrTLybQwYPU2cpgzsCd1OgmSzWHeOR7VjWicxaT9lxn+HfjoYmWnGHgAiIsydf5HKnUXiThehQDG4Tr3e5KR7hN8XilnGKxfOoyrDgZECwIgIb125xIxxTGVdgjRG4pR2+zbG/sIkD7l2cYJyaYLMOZxzjBV4nueLCI1GnaWFab65t4OXt4gUuFqYJ8gGuPYBCxdLHNciys9PkaapjAHGGM8YQ7lcZv71OaYmC/xZPaJHTN4cUgpDXrr8MtOVaUqTRXzfY3t7u7O0tDR82a2trfkkSTSOY+31etrpdLTZbGoURRpFkdbrTY3qTW00mhrHse7u7t4tl8uhqg4VxHHcPDg4+ExVHeBU1YmIU1WnisucZtamLszn01ar9WRzc/PrWq2WAPwLJ7l2ULfXOAMAAAAASUVORK5CYII="},
   { label: "Сохранить выбранный текст как TXT", func: "saveSelectionToTxt()", image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAQE6AAAAZAAAAGgAAAJmAAACZgAAAGYAAABmAAAAZgAAAGYAAABmAAAAZgAAAGYAAABlAAAAaQABAmYAAQEjAAAAADlVkOdVcKHxVXKi8kdklPJLZpfyU3Cg8lJvn/JRbZ7yUW+g8lFun/JRbp/yUG6e8lVyofFVdKjzLkV45wAAAFABAQEAaIzF/3y34v9wsuL/cJe0/0lpgv9bjLP/dLLh/2+v3v9sq9v/cK3d/3Gv3v9sqtv/b7Df/4G77P9VcqT2AAAAVAMDAQBnir/+ZqfU/pDB4/7a3uD+j46N/kxYXv6To6/+1er4/tXp+P7J3/D+1ej4/svg8v6Gut/9aqzd/lhxnvAAAABSAwIBAGaIvv9pptX/ocfj//f4/P/P0tX/g4CA/1xZWf+Woqr/2uz8/9Hl+f/W5fT/2Of3/5fC4v5tq93/Vm+e8QAAAFIDAgEAaYm+/3mw2/+iyeX/9Pn8/+z0+//IzNL/d3h5/0tMTv+Mkpn/xdvs/9Hp/f/O4PL/msXk/nmz4/9XcJ/xAAAAUgMDAQBti7//k7/h/6fL5v/v9fn/4u73/9Dk9P+8wMT/YGpx/zJJWv94iJf/ztzo/9Pp/P+ZwuD+gLfk/1dwnvEAAABSAwMBAHOPwf+myub/sNHp//j7/P/6/P3/8fr///r39P+sxdP/IXWq/xJJcv+NjZD/0+Lu/6TN7f6Ft+L/WXGf8QAAAFIDAwEAd5LD/7PR6/+ZxOP/0ePx/97r9f/Y5/L/3e32/8Tc7f9gseT/CHK3/zBYdv+HiY7/lL/f/pLE7/9bcJ3xAAAAUgMDAQB4k8P/xNvx/5/F5f+kyOX/qMrn/6TH5f+kyOX/sM/q/5e51P9Mm83/GHm3/xxIav9fdYf+pMvs/1x1pfIAAABTAwMBAHmSxf/O4/T/y9/y/8Hb9P/C3PX/wNv0/7vW7/+93ff/utDm/42fsf9Gjbn/EXS2/ytSbv6Fj5r/WnGc8gAAAFICAwEBepPE/tHk9f/S5PX/vMjV/7fCzP+3w8//uMPP/7XBzP+6ytf/qa+4/3h/hv9Ghaz/JoO+/jNXdP82PVnyAAAAVgACAgCBmcb/2+r3/dHh8fyPkpX/kI6N/5yam/+dnJ3/paWk/6enpf+sr6//mpSR/3Bubf9SjbD8H4C+/QsrSvcCAAB/AAAAA3yVx//j8///3u/7/52gpf6pqKf+uLm5/rq7u/7Ly8v+ycnI/paWlf6LjY/+np2f/Xh+g/5gnL7/MX+y/xcgJ80BAgNNN1OUs6W84fDA1O73mJyj/ainpv+2trb/t7e4/8fHyP/Fxsb/kZGQ/4eGhP+vucT/j6G+/W53k/NlkbnwNoOv/AgiNb8CCBsQDRo/YwsaO3B0d33arKyp9q2trfWvr6/2u7u79ru7vPawr7H1sbCt9nJ2gOQIGD6bFCFEYB0qPE1Bf6SpEz9cggAAAAMCAQEBAQAAADIyMmlDQ0ONQUFBhUFBQYVCQkGFQkJBhUhISIRNTU2OKysrZAEAAAUBAQAAAgEAAAkEAAEDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="},
   { separator: ''},
   { label: "(Меню ПКМ) Сохранить текст в файл", value: "Save.SelectionToFile" },
   { label: "(Меню ПКМ) Открыть текст в редакторе", value: "Save.TextToEditor"},
];

var menuPopup = self.appendChild(document.createXULElement("menupopup"));
array.forEach((m,i)=> {
   if ("separator" in m) { menuPopup.appendChild(document.createXULElement("menuseparator")); return };
   var mItem = menuPopup.appendChild(document.createXULElement("menuitem"));
   mItem.setAttribute("label", m.label);
   mItem.setAttribute("class", "menuitem-iconic");
   if ("image" in m) mItem.setAttribute("image", m.image || array[i-1].image); 
   if ("value" in m) { 
       mItem.setAttribute('type', 'checkbox');
       mItem.setAttribute('checked', cbu.getPrefs(m.value) );
       mItem.onclick =()=> cbu.setPrefs(m.value, !cbu.getPrefs(m.value));
       }
   if ("func" in m) mItem.addEventListener("command", ()=> eval(m.func.toString()));
});
menuPopup.setAttribute("onclick", "event.stopPropagation()");


function aDate() {
 var t=new Date();
 var y=1900+t.getYear();
 var min=t.getMinutes(); if (min<10){min="0"+min};
 var h=t.getHours();
 var m=t.getMonth();switch(m){case 0: m="января";break;case 1: m="февраля";break;case 2: m="марта";break;case 3: m="апреля";break;case 4: m="мая";break;case 5: m="июня";break;case 6: m="июля";break;case 7: m="августа";break;case 8: m="сентября";break;case 9: m="октября";break;case 10: m="ноября";break;default: m="декабря";}
 var d=t.getDate();
 var curdate=d+" "+m+" "+y+" "+"г";
 var myfilename=curdate;
 return myfilename;
}
 

function WebScreenShotonImage(image) {
      var canvas = document.createElementNS(xhtmlns, 'canvas');
      canvas.width = image.naturalWidth;
      canvas.height = image.naturalHeight;
      var ctx = canvas.getContext('2d');
      ctx.drawImage(image, 0, 0);
      var base64 = canvas.toDataURL();
      gClipboard.write(base64);
   
      // стиль для изображение в сплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(base64, self.label, "Изображение копировано как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
};


var saveToFile = function (fileContent, fileName) {
    var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
    uc.charset = 'utf-8';
    fileContent = uc.ConvertFromUnicode(fileContent);

    var nsIFilePicker = Components.interfaces.nsIFilePicker;
    var fp = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
    fp.init(window, '', fp.modeSave);
    fp.defaultString = fileName;
    fp.appendFilters(fp.filterHTML);
    fp.appendFilters(fp.filterAll);
    fp.open(function (rv) {
  if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
    var stream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
    stream.init(fp.file, 0x02|0x20|0x08, 0666, 0);
    stream.write(fileContent, fileContent.length);
    stream.close();
  }
});
};


function savePageToHTML() {
var vert=`javascript:(function(){var getSelWin=function(w){if(w.getSelection().toString())return w;for(var i=0,f,r;f=w.frames[i];i++){try{if(r=getSelWin(f))return r}catch(e){}}};var selWin=getSelWin(window),win=selWin||window,doc=win.document,loc=win.location;var qualifyURL=function(url,base){if(!url||/^([a-z]+:|%23)/.test(url))return url;var a=doc.createElement('a');if(base){a.href=base;a.href=a.protocol+(url.charAt(0)=='/'%3F(url.charAt(1)=='/'%3F'':'//'+a.host):'//'+a.host+a.pathname.slice(0,(url.charAt(0)!='%3F'&&a.pathname.lastIndexOf('/')+1)||a.pathname.length))+url}else{a.href=url};return a.href};var encodeImg=function(src,obj){var canvas,img,ret=src;if(/^https%3F:%5C/%5C//.test(src)){canvas=doc.createElement('canvas');if(!obj||obj.nodeName.toLowerCase()!='img'){img=doc.createElement('img');img.src=src}else{img=obj};if(img.complete)try{canvas.width=img.width;canvas.height=img.height;canvas.getContext('2d').drawImage(img,0,0);ret=canvas.toDataURL((/%5C.jpe%3Fg/i.test(src)%3F'image/jpeg':'image/png'))}catch(e){};if(img!=obj)img.src='about:blank'};return ret};var toSrc=function(obj){var strToSrc=function(str){var chr,ret='',i=0,meta={'%5Cb':'%5C%5Cb','%5Ct':'%5C%5Ct','%5Cn':'%5C%5Cn','%5Cf':'%5C%5Cf','%5Cr':'%5C%5Cr','%5Cx22':'%5C%5C%5Cx22','%5C%5C':'%5C%5C%5C%5C'};while(chr=str.charAt(i++)){ret+=meta[chr]||chr};return'%5Cx22'+ret+'%5Cx22'},arrToSrc=function(arr){var ret=[];for(var i=0;i<arr.length;i++){ret[i]=toSrc(arr[i])||'null'};return'['+ret.join(',')+']'},objToSrc=function(obj){var val,ret=[];for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj,prop)&&(val=toSrc(obj[prop])))ret.push(strToSrc(prop)+': '+val)};return'{'+ret.join(',')+'}'};switch(Object.prototype.toString.call(obj).slice(8,-1)){case'Array':return arrToSrc(obj);case'Boolean':case'Function':case'RegExp':return obj.toString();case'Date':return'new Date('+obj.getTime()+')';case'Math':return'Math';case'Number':return isFinite(obj)%3FString(obj):'null';case'Object':return objToSrc(obj);case'String':return strToSrc(obj);default:return obj%3F(obj.nodeType==1&&obj.id%3F'document.getElementById('+strToSrc(obj.id)+')':'{}'):'null'}};var ele,pEle,clone,reUrl=/(url%5C(%5Cx22%3F)(.+%3F)(%5Cx22%3F%5C))/g;if(selWin){var rng=win.getSelection().getRangeAt(0);pEle=rng.commonAncestorContainer;ele=rng.cloneContents()}else{pEle=doc.documentElement;ele=(doc.body||doc.getElementsByTagName('body')[0]).cloneNode(true)};while(pEle){if(pEle.nodeType==1){clone=pEle.cloneNode(false);clone.appendChild(ele);ele=clone};pEle=pEle.parentNode};var sel=doc.createElement('div');sel.appendChild(ele);for(var el,all=sel.getElementsByTagName('*'),i=all.length;i--;){el=all[i];if(el.style&&el.style.backgroundImage)el.style.backgroundImage=el.style.backgroundImage.replace(reUrl,function(a,b,c,d){return b+encodeImg(qualifyURL(c))+d});switch(el.nodeName.toLowerCase()){case'link':case'style':case'script':el.parentNode.removeChild(el);break;case'a':case'area':if(el.hasAttribute('href')&&el.getAttribute('href').charAt(0)!='%23')el.href=el.href;break;case'img':case'input':if(el.hasAttribute('src'))el.src=encodeImg(el.src,el);break;case'audio':case'video':case'embed':case'frame':case'iframe':if(el.hasAttribute('src'))el.src=el.src;break;case'object':if(el.hasAttribute('data'))el.data=el.data;break;case'form':if(el.hasAttribute('action'))el.action=el.action;break}};var head=ele.insertBefore(doc.createElement('head'),ele.firstChild);var meta=doc.createElement('meta');meta.httpEquiv='content-type';meta.content='text/html; charset=utf-8';head.appendChild(meta);var title=doc.getElementsByTagName('title')[0];if(title)head.appendChild(title.cloneNode(true));head.copyScript=function(){if('$'in win)return;var f=doc.createElement('iframe');f.src='about:blank';f.setAttribute('style','position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');doc.documentElement.appendChild(f);var str,script=doc.createElement('script');script.type='text/javascript';for(var name in win){if(name in f.contentWindow||!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name))continue;try{str=toSrc(win[name]);if(!/%5C{%5Cs*%5C[native code%5C]%5Cs*%5C}/.test(str)){script.appendChild(doc.createTextNode('var '+name+' = '+str.replace(/<%5C/(script>)/ig,'<%5C%5C/$1')+';%5Cn'))}}catch(e){}};f.parentNode.removeChild(f);if(script.childNodes.length)this.nextSibling.appendChild(script)};head.copyScript();head.copyStyle=function(s){if(!s)return;var style=doc.createElement('style');style.type='text/css';if(s.media&&s.media.mediaText)style.media=s.media.mediaText;try{for(var i=0,rule;rule=s.cssRules[i];i++){if(rule.type!=3){if((!rule.selectorText||rule.selectorText.indexOf(':')!=-1)||(!sel.querySelector||sel.querySelector(rule.selectorText))){style.appendChild(doc.createTextNode(rule.cssText.replace(reUrl,function(a,b,c,d){var url=qualifyURL(c,s.href);if(rule.type==1&&rule.style&&rule.style.backgroundImage)url=encodeImg(url);return b+url+d})+'%5Cn'))}}else{this.copyStyle(rule.styleSheet)}}}catch(e){if(s.ownerNode)style=s.ownerNode.cloneNode(false)};this.appendChild(style)};var sheets=doc.styleSheets;for(var j=0;j<sheets.length;j++)head.copyStyle(sheets[j]);head.appendChild(doc.createTextNode('%5Cn'));var doctype='',dt=doc.doctype;if(dt&&dt.name){doctype+='<!DOCTYPE '+dt.name;if(dt.publicId)doctype+=' PUBLIC %5Cx22'+dt.publicId+'%5Cx22';if(dt.systemId)doctype+=' %5Cx22'+dt.systemId+'%5Cx22';doctype+='>%5Cn'};var href = 'data:text/html;charset=utf-8,' + encodeURIComponent(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->');var a = document.documentElement.appendChild(document.createElement("a"));a.setAttribute("href", href);var name = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());name=name.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');name += (function () {var d = new Date(), z=function(n){return '_' + (n < 10 ? '0' : '') + n};return z(d.getHours()) + z(d.getMinutes()) + z(d.getSeconds());})();a.setAttribute("download", name + ".html");a.click();a.remove();})();`;
gBrowser. loadURI(vert, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});
};


function saveShortcuts() {
var file = Components.classes["@mozilla.org/file/local;1"].
           createInstance(Components.interfaces.nsIFile);
file.initWithPath(folderpath);

if( !file.exists() || !file.isDirectory() ) {   file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0x1B6);}

var savetodir=folderpath+"\\"; 
var urllink=gBrowser.currentURI.spec;
var out=getTabLabel();
var filename=savetodir+out+'.url';
var data="[InternetShortcut]\r\nURL="+urllink+"\r\n";

saveToFile(data, filename);
 // стиль для изображения во всплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
   // подсказка
   var notific = 'Сохранил в: ' + folderpath;
   var image = gBrowser.selectedBrowser.mIconURL;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(image, filename, notific);
};

// Кодировать изображение или текстовой файл в base64 .............
function copyFaviconbase(){
var fp = window.makeFilePicker();
fp.init(window, "Открыть файл", fp.modeOpen);
fp.appendFilter("Text and images", "*.txt; *.text; *.css; *.js; *.ini; *.rdf; *.xml; *.html; *.htm; *.shtml; *.xhtml; *.jpe; *.jpg; *.jpeg;\
                                    *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw");
  fp.open(re=> { 
  if ( re != fp.returnOK ) return;
   var file = fp.file;
   var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
   inputStream.init(file, 0x01, 0600, 0);
   var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
   stream.setInputStream(inputStream);
   var encoded = btoa(stream.readBytes(stream.available()));
   var contentType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService).getTypeFromFile(file);
   var dataURI = "data:" + contentType + ";charset=utf-8;base64," + encoded;
   gClipboard.write(dataURI);
   //Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Текст скопирован как  base64");
    // стиль для изображение в сплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Изображение скопировано как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Изображение скопировано как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
});
};

// Сохранить страницу как PDF файл через сервис 'pdfmyurl.com' .............
function savePageToPDF() {
      var loc = gBrowser.currentURI.spec;
   var vert = "http://pdfmyurl.com?url=" + loc;
  
   gBrowser. loadURI(vert, {
   triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()
   });
}; 

if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 15
	? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
	: (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
		internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin);

// Сохранить иконку текущего сайта с диалогом сохранения .............
function saveFavicon() {
       var uri = gBrowser.currentURI;
       function getSiteName() {
                  try { var domain = uri.host.split('.') } catch(e) { return "" };
                   domain = (domain.length == 2) ? domain[0] : domain[1]
                   return domain.charAt(0).toUpperCase() + domain.slice(1).split('.')[0] + " ";  
            };
    var url = gBrowser.selectedTab.image;
    url && saveImageURL(
        url, getSiteName(), null, false, false, null, null,
        /^data:(image\/[^;,]+)/i.test(url) ? RegExp.$1.toLowerCase() : Cc["@mozilla.org/mime;1"]
            .getService(Ci.nsIMIMEService).getTypeFromURI(Services.io.newURI(url)),
        null, PrivateBrowsingUtils.isContentWindowPrivate(content || window), document.nodePrincipal
    );
};


// Копировать иконку текущего сайта в base64 .............
function copyFaviconData() {
   var img = new Image();
   img.src = gBrowser.selectedTab.image;
   WebScreenShotonImage(img);
};


// Сохранить выделенный текст или весь текст на странице как txt файл .............
function saveSelectionToTxt() {

let browserMM = gBrowser.selectedBrowser.messageManager;
        browserMM.addMessageListener('getSelection', function listener(message) {
        var sel = message.data;
       !sel && document.getElementById("cmd_selectAll").doCommand(); 
     
   // создать название файла из заголовка страницы и текущего времени и сохранить текст ....
   var fileTitle = getTabLabel() + '  ' + aDate().replace(/:/g, ".");
   saveURL("data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + ("\r\n\r\n" + sel)), 
                                fileTitle + ".txt", null, false, false, null, window.document);
   !sel && goDoCommand("cmd_selectNone"); 
 browserMM.removeMessageListener('getSelection', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelection", content.document.getSelection().toString())', false);
};


// Добавляем в контекстного меню страницы новые пункты .............
((contextMenu, el)=> {

   // в контекстного меню выделенного текста ....
   var saveItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
   saveItem.id = "content-saveItem";
   saveItem.setAttribute("label", "Сохранить выбранный текст в файл");
   saveItem.setAttribute("class", "menuitem-iconic");
   saveItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); 
   saveItem.onclick =()=> saveSelectionToFile();

   var editorItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
   editorItem.id = "content-editorItem";
   editorItem.setAttribute("label", "Открыть выбранный текст в редакторе");
   editorItem.setAttribute("class", "menuitem-iconic");
   editorItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAA////AIiafwC85K4AS1ZGANLsyABKU0UAy+m+AL/lsQC14aQAn9WMAJ/QjQCsrKwAqNyXAOPz3ADe8dcA2e/QANPtyQDM68EAxei4AL7lrwC14aUArt6dAJfOhACdz4sAgICAALThpQDg8doA3vHVANjuzgDR7MYAyum+AMLmtQC7460AsuCjAK3dmgCUy4AArdedANDsxQDL6sAAz+PIAMviwwDH4L4Awd62ALvbrwC02KcArdafAKbTlgCEu3EAtNWoANPqywDa8NIA1u7NANHtxwDK6cAAw+e3ALzkrwC14aYAr9+dAKXbkQCJwnMA1+3QAKncmADd8dQAyuLBAMbgvAC6264AttmoAK/XoACn1JYAotKPAJbNgwB9tWgA4+zfANju0ADT7coAz+vFAMPntgC95K8Art6eAKndlQCa1IYAi8R3AP3+/QDD37kAvt2yALjarACz2KYArdaeAKHRjwCXzoUAj8V6AI6/ewDu8e4Awea2AMrqwQDG6LoAweazALnjqwCz4KQAr9+cAKbbkwCd2IkAlc1/AKbTlQC73K8At9qqALDXowCp1ZsApdOVAKDRjQCYzoUAksx7AIi+cwCu0aEAp9yUAMXougDC5rYAveSuALfipwCw4J8AqdyXAKLajwCd2IcAlNR9AI3FdwDU6ssAqdWZAKPSkgCe0YsAmc6GAJDLfQB/tmoA3enZAJfWhACc2IkApNuRAKTbkACj2pAAodqOAKHZjgCl25IAotmOAIzHdgAPAAAA2JIKAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOzARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcrkUA9CUMAAAAAAAAAAAAAAAAAAAAAAAAAA8AAQAAAAEAAAAAAAAAVCIMAAAAAAABAAAAuwP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAACZDSMAAQAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAABAEAABHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGRkZGRkZGRkZAAAAAAAZAQEBAQEBAQEBARkAAIeHiImKi4yNjY5+AQEZAD4mJlZXRH+AgYKDhIVdGQBzJnR1dnd4eXp7fH1+ARkAGiYnaWprbG1ub3Bxcl0ZACdeJl9gYWJjZGVmZ2gBGQAAAyZUVVZXWEVZWltcXRkAAA1KS0wfTU45T1BRUlMZAAA+P0BBK0JDREVGR0hJGQAAAzIzNDU2Nzg5Ojs8PRkAACYnKCkqKywtLi8YMDEZAAAAGhscHR4fICEiIyQlGQAAAA0ODxAREhMUFRYXGBkAAAADBAUGBwYIBgkGChkAAAAAAAACAAIAAgACAAIAAPgBAADwAAAAwAAAAIAAAACAAAAAgAAAAIAAAADAAAAAwAAAAMAAAADAAAAAwAAAAOAAAADgAAAA4AEAAPqrAAA="); 
   editorItem.onclick =()=> textToEditor();


    // устанавливаем где и при каких настройках показывать новые пункты ....
   addEventListener('popupshowing', e=> {
      if (e.target != e.currentTarget) return;
      var sel = gContextMenu.isTextSelected;
      saveItem.hidden = !sel || !cbu.getPrefs("Save.SelectionToFile");
      editorItem.hidden = !sel || !cbu.getPrefs("Save.TextToEditor"); 
      }, false, contextMenu);

   // удалять новые пункти при изминениях ....
   addDestructor(()=> {
      saveItem.remove(); editorItem.remove();
   });   
})(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open"));


// Сохранить выделенный текст в файл на рабочем столе .............
function saveSelectionToFile() {

 let browserMM = gBrowser.selectedBrowser.messageManager;
 browserMM.addMessageListener('getSelect', function listener(message) {
   // создать текст для записи
   var url = gBrowser.currentURI.spec;
   if (/\.рф/.test(url.host)) url = convertFromUnicode("UTF-8", url);
   
   var time = convertFromUnicode("UTF-8", aDate().replace(/:/g, "."));
   var text = convertFromUnicode("UTF-8", message.data); 
   var title = convertFromUnicode("UTF-8", getTabLabel());
   
   var text = "..............................................................\n"
            + title + " - " + time + "\n" + url + "\n\n" + text + "\n\n\n";
   var text = text.replace(/\u000A/g, "\u000D\u000A").replace(/\u000D\u000D\u000A/g, "\u000D\u000A");

   // путь к файлу и название файла
   var file = Services.dirsvc.get("Desk", Ci.nsIFile); 
   file.append("Save - " + (aDate().replace(/:/g, ".")) + ".txt");
          
   // создать файл с текстом или добавлять текст в файл
   var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
   file.exists() ? foStream.init(file, 0x02 | 0x10, 0664, 0) : foStream.init(file, 0x02|0x08|0x20, 0666, 0);
   foStream.write(text, text.length);
   foStream.close();
    // всплывающая подсказка дает возможность открыть файл если кликнуть на подсказке
       var notificat = 'Сохранил выделенный текст в файл на рабочий стол'; 
   var image = gBrowser.selectedTab.image || self.image;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
    .showAlertNotification(image, notificat, "Кликни чтобы открыть файл", true, "", (s, t)=> { 
      if (t == 'alertclickcallback') file.launch();
   }, "");
 browserMM.removeMessageListener('getSelect', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false);

};

// Создать текстовой файл с выделенным текстом в папке профиля и открыть в редакторе .............
function textToEditor() {


 let browserMM = gBrowser.selectedBrowser.messageManager;
 browserMM.addMessageListener('getSelect', function listener(message) {
   // создать текст для записи
    var text = convertFromUnicode("UTF-8", message.data); 
    var file = Services.dirsvc.get('ProfD', Ci.nsIFile);
   file.append("TextToEditor.txt");
   custombuttonsUtils.writeFile(file.path, text);
   file.launch(); 
          

 browserMM.removeMessageListener('getSelect', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false);
};


// Конвертировать текст в юникод .............
function convertFromUnicode(charset, str) {
     var converter = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
     converter.charset = charset;
     str = converter.ConvertFromUnicode(str);
     return str + converter.Finish();
 
};

// Получить название вкладки без не сохраняемых символов и лишних пробелов ..............
function getTabLabel() { 
   var label = gBrowser.selectedTab.label;      
   var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
   return label.substring(0, 50);
};
 ((main, parts) => this.onmousedown = e => {
    if (e.button) return;
    this.onmousedown = null;

    var df = MozXULElement.parseXULToFragment(`
        <menugroup orient="vertical">
            <menuseparator/>
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить всю страницу как PNG"
                value="all"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить видимую часть как PNG"
                value="page"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAIBkAAAEAIAAMDQAAFgAAACgAAAAgAAAAMgAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29fT/2tra/8jIyP/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8jIyP/a2tr/9vX0/+zs7P/ak0b/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/9qTRv/s7Oz/7Ozs/+J9Dv/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+/6SdmP/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/+vn4//z7+v/6+fj/4n0O/+zs7P/s7Oz/4n0O//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/aFtT//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//j39v/ifQ7/7Ozs/+zs7P/ifQ7/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P9oW1P/7+zq/+/s6v/v7Or/8O3r//Dt6//w7ev/8O3r//Dt6//w7ev/8O3r/+/s6v/w7ev/9fTy/+J9Dv/s7Oz/7Ozs/+J9Dv/49/b/+Pf2//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4/2hbU//q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/y8O//4n0O/+zs7P/s7Oz/4n0O//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/aFtT/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe//Dt6//ifQ7/7Ozs/+zs7P/ifQ7/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P9oW1P/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/7uro/+J9Dv/s7Oz/7Ozs/+J9Dv/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx/2hbU//x7+3/8vDv//Hv7f/x7+3/8e/t//Lw7//x7+3/8e/t//Lw7//x7+3/8vDv//Hv7f/29fT/4n0O/+zs7P/s7Oz/4n0O//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//aFtT/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/8vGwf/ifQ7/7Ozs/+zs7P/ifQ7/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f9nWlL/aFtT/2hbU/9nWlL/Z1pS/2hbU/9oW1P/Z1pS/2daUv9oW1P/aFtT/2hbU/9nWlL/pJyX/+J9Dv/s7Oz/7Ozs/+J9Dv/w7ev/8O3r//Dt6//w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Hv7f/w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Dt6//w7ev/4n0O/+zs7P/s7Oz/4n0O/+/s6v/v7Or/7uro/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/u6uj/7+zq/+/s6v/ifQ7/7Ozs/+zs7P/ifQ7/7uro/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7Ojm/+J9Dv/s7Oz/7Ozs/+J9Dv/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/4n0O/+zs7P/s7Oz/4n0O/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/ifQ7/7Ozs/+zs7P/ifQ7/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+J9Dv/s7Oz/7Ozs/+J9Dv/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/4n0O/+zs7P/s7Oz/4n0O/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/ifQ7/7Ozs/+zs7P/ifQ7/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+J9Dv/s7Oz/7Ozs/+J9Dv/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/k39z/4n0O/+zs7P/s7Oz/4n0O/+Lc2f/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/ifQ7/7Ozs/+zs7P/ifQ7/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+J9Dv/s7Oz/9fTy/+J9Dv/8+/r/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/4n0O//X08v/8+/r/6KFU/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ooVT//Pv6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить выбранный элемент как PNG"
                value="click"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAADDn2Hfz5pE/8eVQP7IlkH/yJZB/8iWQf/IlUH/yJVA/8iVQP/IlED/yJQ//8iUP//IlD//yJM+/8iTPv/Hkj3/nI1w//bDbP//8OH//+zW///s1///69b//+rV///p1P//59L//+XQ///izf//38n//9vG///ZxP//1b///dG////Prf/KlkX/88N4/v37///99Pj//fT6//vy9v/68fT/+u/y//rt8P/66u3/+ufq//rl6P/64eT/+93h//3a3//71d7//9LK/86XR//0xHb//vv////18///9fT///f5///4////9f7///P8///v+f//7Pb//+nz///m8f//4eb//9vZ//3Y2v//1Mb/zphH//TGd//+/////Pj1///7///Q58r/m9aV/6TZnv+i15r/otWY/6LTlv+j0pb/mc6M/9DXuf//3+P//Nnc///Wyf/OmUf/9MZ3//7////8+/j//////53WnP+Y5pn/rvGv/6PvpP+e7p//me6b/5nvm/95533/mM+L///j7f/629z//9jL/86ZR//0xnf//v////z9+v//////qtup/8Xzxf/a/tn/z/vO/8n7yf/D+sL/xPvD/6Hzo/+j05b//+Tu//re3///2cz/zplI//XGeP/+/////P36//////+n26f/uvC6/9T71P/K+Mr/xvjG/8D3wP+/+L//nfCf/6LTlf//5u//+t/g///cz//OmUj/9MZ3//7////8/fr//////6rcqv/G9MX/3//f/9n92f/V/NX/0PzQ/9H+0P+s9a7/pdSY///o8f/64OL//9zP/86aSP/0xnf//v////z9+f//////ndid/5TjlP+v7q//qeyp/6jsqf+k7KX/p+6n/4Tlh/+Z0Y7//+r0//rh4v//3tH/zppI//TGd//+/////v77///////Y8Nj/p9+n/6/jr/+t4a3/rd2p/67bpv+u2ab/p9Wc/9jgx///6Oz//OPl///e0f/Omkj/9MV1//7//////fr///78///+/f///////////////////P////j////0+///8fn//+vu///m4v/94+P//97P/86ZSP/zx3v//v/////+/f///////f////v////7////+/////v+///7+///+/f///vz/P/98Pr//+33//3p9///5OL/zppL//a1Sv/0xoL/9cR7//XEfP/1xHz/9cR8//XEfP/1xH3/9cR8//XCev/1wXr/9b94//W9d//1u3X/87l0//y6bP/Llj7/+pMA/vWBAP/1gwD/9YMA//WDAP/1gwD/9YMA//WDAP/1gwD/9YQA//WEAP/1hAD/9YQA//WEAP/zhAH//okA/8qLIv3xpzP/4ptV/+OdU//jnVP/451T/+OdU//jnVP/451T/+OdU//jnVL/451S/+OdUv/jnVL/451S/+GdVf/qnUf/2aRJ/9q0c9/8yn7/98V5/vjGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6/vrIe/+jj2y4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить выбранную область как PNG"
                value="clipping"/>
        </menugroup>
    `);
    var menugroup = df.firstChild;
    menugroup.setAttribute("context", "");
    menugroup.setAttribute("oncommand", "handleCommand(event);");
    menugroup.handleCommand = e => {
        var name = _id + ":DataURLReady";
        main = main.replace("%MESSAGE_NAME%", name);

        var urls = {}, configurable = true, enumerable = true;
        Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, {
            configurable, enumerable, get() {
                var value = `data:;charset=utf-8,({${
                    encodeURIComponent(main + part)
                }%0A}).init("${key}")`;
                Object.defineProperty(urls, key, {configurable, enumerable, value});
                return value;
        }}));
        var getTabLabel = () => {
            var label = gBrowser.selectedTab.label;      
            var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
            return label.substring(0, 50);
        }
        var listener = msg => {
            var fp = makeFilePicker();
            fp.init(window, "Сохранить как…", fp.modeSave);
            fp.appendFilter("", "*.png");
            fp.defaultString = getTabLabel() + ".png";
            fp.open(res => {
                if (res == fp.returnCancel || !fp.file) return;
                var wbp = makeWebBrowserPersist(), args = [
                    Services.io.newURI(msg.data), document.nodePrincipal,
                    null, null, null, null, fp.file, null
                ];
                //wbp.saveURI.length == 9 && splice(args);
                var {length} = wbp.saveURI;
                length >= 9 && splice(args);
                length == 10 && args.splice(3, 0, null);
                wbp.saveURI(...args);
            });
        }
        var splice = arr => {
            var fox74 = parseInt(Services.appinfo.platformVersion) >= 74;
            var args = [fox74 ? 7 : 2, 0, fox74 ? Ci.nsIContentPolicy.TYPE_IMAGE : null];
            (splice = arr => arr.splice(...args))(arr);
        }		
        messageManager.addMessageListener(name, listener);
        addDestructor(() => messageManager.removeMessageListener(name, listener));

        (menugroup.handleCommand = e => gBrowser.selectedBrowser.messageManager
            .loadFrameScript(urls[e.target.value], false)
        )(e);
    }
    menuPopup.querySelector('menuitem[label*="ярлык"]').after(df);
})(`
    init(cmd) {
        cmd.startsWith("c")
            ? this[cmd].init(this[cmd].parent = this)
            : this[cmd]();
    },
    capture(win, x, y, width, height) {
        var canvas = win.document.createElementNS("${xhtmlns}", "canvas");
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        var tryDraw = ind => {
            try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")}
            catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);}
        }
        tryDraw(17);
        sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png"));
    },
    `, {

    all: `all() {
        var win = content;
        this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY);
    }`,
    page: `page() {
        var win = content, doc = win.document, body = doc.body, html = doc.documentElement;
        var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft;
        var scrY = (body.scrollTop || html.scrollTop) - html.clientTop;
        this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight);
    }`,
    clipping: `clipping: {
        handleEvent(e) {
            if (e.button) return false;
            e.preventDefault();
            e.stopPropagation();
            switch(e.type) {
                case "mousedown":
                    this.downX = e.pageX;
                    this.downY = e.pageY;
                    this.bs.left = this.downX + "px";
                    this.bs.top = this.downY + "px";
                    this.body.appendChild(this.box);
                    this.flag = true;
                    break;
                case "mousemove":
                    if (!this.flag) return;
                    this.moveX = e.pageX;
                    this.moveY = e.pageY;
                    if (this.downX > this.moveX) this.bs.left = this.moveX + "px";
                    if (this.downY > this.moveY) this.bs.top  = this.moveY + "px";
                    this.bs.width = Math.abs(this.moveX - this.downX) + "px";
                    this.bs.height = Math.abs(this.moveY - this.downY) + "px";
                    break;
                case "mouseup":
                    this.uninit();
                    break;
            }
        },
        init() {
            var win = {};
            Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
                .getFocusedElementForWindow(content, true, win);
            this.win = win.value;

            this.doc = this.win.document;
            this.body = this.doc.body;
            if (!HTMLBodyElement.isInstance(this.body)) {
                Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
                    .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!");
                return false;
            }
            this.flag = null;
            this.box = this.doc.createElement("div");
            this.bs = this.box.style;
            this.bs.border = "#0f0 dashed 2px";
            this.bs.position = "absolute";
            this.bs.zIndex = "2147483647";
            this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor;
            this.body.style.cursor = "crosshair";
            ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true));
        },
        uninit() {
            var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)];
            this.body.style.cursor = this.defaultCursor;
            this.body.removeChild(this.box);
            this.parent.capture.apply(this, pos);
            ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true));
        }
    }`,
    click: `click: {
        getPosition() {
            var html = this.doc.documentElement;
            var body = this.doc.body;
            var rect = this.target.getBoundingClientRect();
            return [
                this.win,
                Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft,
                Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop,
                parseInt(rect.width),
                parseInt(rect.height)
            ];
        },
        highlight() {
            this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false;
            this.target.style.cssText += "outline: red 2px solid; outline-offset: 2px; -moz-outline-radius: 2px;";
        },
        lowlight() {
            if (this.orgStyle) this.target.style.cssText = this.orgStyle;
            else this.target.removeAttribute("style");
        },
        handleEvent(e) {
            switch(e.type){
                case "click":
                    if (e.button) return;
                    e.preventDefault();
                    e.stopPropagation();
                    this.lowlight();
                    this.parent.capture.apply(this, this.getPosition());
                    this.uninit();
                    break;
                case "mouseover":
                    if (this.target) this.lowlight();
                    this.target = e.target;
                    this.highlight();
                    break;
            }
        },
        init() {
            this.win = content;
            this.doc = content.document;
            ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true));
        },
        uninit() {
            this.target = false;
            ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true));
        }
    }`
});

JS подключен в CustomStylesScripts.jsm в секции для custom_js. [firefox] 91, 100.

Отредактировано _zt (13-05-2022 16:16:11)

Отсутствует

 

№30813-05-2022 23:18:16

sandro79
Участник
 
Группа: Members
Зарегистрирован: 15-11-2017
Сообщений: 1750
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
А можно ли сделать скрипт для открытия закладок в контейнере?
Как то есть начиная с сотой версии, сделать для старших версий, в частности для 91 хотелось бы добавить такую возможность.
Знаю, есть для этого дополнение, но я от него отказался по неск. причинам.
Через скрипт было бы неплохо, и чтоб пункт меню был расположен так же, как и в 100+, сразу после "Открыть в новой вкладке"

скрытый текст
Пунт переименован
Image_001.png
скрытый текст
Чувствую я, не придётся мне переходить на 102 ESR. Для меня больше минусов чем плюсов, единственное - плавающие полосы прокрутки впечатлили.
Начиная с 99, указатель переходит в режим захвата для изменения размера окна, ещё не успев дойти до внутреннего края окна, что очень неудобно при использовании кнопок панели меню и автоскрываемой боковой панели, постоянно приходится прицеливаться.
И, как я понял, из-за неотключаемого WebRender, с 92+ у меня пропадают кнопки управления окном в Win7 при использовании инструментов веб-разработчика, если используется нестандартная тема в браузере.
Да ещё и в Ютуб, когда плейлист играет, если открыть сайдбар, когда затемняется страница, то кнопки тоже пропадают
скрытый текст
Image_002.png

Отредактировано sandro79 (13-05-2022 23:18:37)

Отсутствует

 

№30914-05-2022 08:00:04

sonyas75
Участник
 
Группа: Members
Откуда: Ставрополь
Зарегистрирован: 22-03-2011
Сообщений: 557
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

sandro79 пишет

Чувствую я, не придётся мне переходить на 102 ESR.

аналогично. вот прям в точку. я никак ночнушку 102, которая будет ЕСР, не могу привести в чувство. вроде и внешний вид сделал аналогичным, и кнопки важные работают, а куча мелочей не поддаются. какой-то дискомфорт необъяснимый. совсем не зашло.

Отсутствует

 

№31014-05-2022 08:03:39

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
UA: Firefox 78.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

jsm

Почему jsm? Нет, расширение здесь, наверно,
может быть любым, в том числе и jsm, но это довольно странно.

1. Через меню кнопки сохраняет pdf и html не в папку загрузок назначенную в браузере, а в папку загрузок в системном профиле пользователя.

pdf там через какой-то сторонний сайт, так что это без меня.


А html — я не вижу такого.
Назначил в браузере папку, и сохраняет в эту папку.


Кстати, хорошо бы в savePageToHTML() в строку var vert=`javascript:(function(){…
добавить String.raw, а то там слэши экранирующие. То есть так:
var vert = String.raw`javascript:(function(){…

2. Через меню кнопки не сохраняет выбранный текст в файл txt.

Да, у saveURL() аргументов, определённо, больше.

скрытый текст

Выделить код

Код:

/*
   saveURL("data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + ("\r\n\r\n" + sel)), 
                                fileTitle + ".txt", null, false, false, null, window.document);
*/
	saveURL(
		"data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + sel),
		fileTitle + ".txt",
		null, false, false, null, null, null,
		gBrowser.selectedBrowser.browsingContext.originAttributes.privateBrowsingId > 0,
		document.nodePrincipal
	);

3. Через контекстное меню сохраняет выбранный текст в файл txt на рабочий стол.

Ну да, так там и задумано, и даже прокомментировано.
Можно заменить var file = Services.dirsvc.get("Desk", Ci.nsIFile); на
try {var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {file = Services.dirsvc.get("Desk", Ci.nsIFile);}


sandro79 пишет

Как то есть начиная с сотой версии, сделать для старших версий, в частности для 91

То есть с этого бага перерисовать?
Хорошо, попробую. Код для custom_script.js

скрытый текст

Выделить код

Код:

Services.prefs.getBoolPref("browser.privatebrowsing.autostart", false) || (async css => {
	var obs = doc => {
		var win = doc.ownerGlobal;
		if (win.browsingContext.usePrivateBrowsing) return;
		var menuitem = doc.getElementById("placesContext_open:newtab");
		if (!menuitem) return;

		var df = win.MozXULElement.parseXULToFragment(
			`<menu
				id="placesContext_open:newcontainertab"
				label="Открыть в контейнере"
				accesskey="й"
				nodetype="link" node-type="link"
				selectiontype="single" selection-type="single"
			>
				<menupopup
					oncommand="openInContainerTab(event);"
					onpopupshowing="return createUserContextMenu(event, {isContextMenu: true});"/>
			</menu>`
		);
		df.firstChild.firstChild.openInContainerTab = open;
		menuitem.after(df);
		win.location != "chrome://browser/content/browser.xhtml" &&
			win.windowUtils.loadSheetUsingURIString(css, win.windowUtils.AUTHOR_SHEET);
	}
	var open = e => {
		var win = e.view, pui = win.PlacesUIUtils;
		var tn = pui.lastContextMenuTriggerNode;

		if (tn.closest("#managed-bookmarks"))
			var url = tn.link, arg = {};
		else {
			var node = pui.getViewForNode(tn).selectedNode;
			if (!pui.checkURLSecurity(node, win)) return;

			var url = node.uri;
			win.PlacesUtils.nodeIsBookmark(node)
				? pui.markPageAsFollowedBookmark(url)
				: pui.markPageAsTyped(url);

			var js = url.startsWith("javascript:");
			var arg = {
				allowPopups: js,
				allowInheritPrincipal: js,
				inBackground: pui.loadBookmarksInBackground
			};
		}
		arg.userContextId = +e.target.dataset.usercontextid;
		win.openTrustedLinkIn(url, "tab", arg);
	}
	var topic = "chrome-document-loaded";
	Services.obs.addObserver(obs, topic);
	Services.obs.addObserver(function quit(s, t) {
		Services.obs.removeObserver(obs, topic);
		Services.obs.removeObserver(quit, t);
	}, "quit-application-granted");
})("chrome://browser/content/usercontext/usercontext.css");

Отсутствует

 

№31114-05-2022 08:41:20

sandro79
Участник
 
Группа: Members
Зарегистрирован: 15-11-2017
Сообщений: 1750
UA: Firefox 91.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

То есть с этого бага перерисовать?

Да-да, с него. Новый баг добавлен и отлично работает! Огромное Спасибо! :beer:

Отсутствует

 

№31214-05-2022 13:52:59

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

Почему jsm?

Возможно я сам это добавил, что бы сразу видеть зависимость.
   

Dumby пишет

pdf там через какой-то сторонний сайт, так что это без меня.

Сохраняет то не сайт, а скрипт или браузер, но если бы был браузер, то он сохранял бы стандартно.
   

Dumby пишет

А html — я не вижу такого.

Да, я забыл настроить папку на одном из профилей.
   

Dumby пишет

Да, у saveURL() аргументов, определённо, больше.

C этим все в порядке. Спасибо.
   

Dumby пишет

try {var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {file = Services.dirsvc.get("Desk", Ci.nsIFile);}

1. Так сохраняет в профиль. [firefox] 91, 100
2. И не сохраняет текст из textarea, можно это изменить?

Отредактировано _zt (14-05-2022 13:56:12)

Отсутствует

 

№31315-05-2022 17:21:44

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1728
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Просьба, сделать запускатор для кнопок ATB.


Win7

Отсутствует

 

№31416-05-2022 09:19:07

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
UA: Firefox 78.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

Сохраняет то не сайт, а скрипт

Скрипт ничего не сохраняет.
Просто открывает урл в текущей вкладке. И всё, больше ничего.


Мне вот стало любопытно, а сохранялка в pdf,
которая у лисы на борту, сохраняет хуже чем веб-сервис?
Если нет, то можно было бы обсудить перевод на лисий код.
Сравнить можно сопоставлением с результатами сохранения,
например, этим WebExtensions (поднастроить его ещё).
Ну, если есть желание, разумеется.

1. Так сохраняет в профиль.

Путь к папке сохранения должен браться из настройки browser.download.dir
То есть в «папку загрузок назначенную в браузере» (если не получилось взять, тогда на рабочий стол).
Если там путь, ведущий в профиль, то всё правильно.

2. И не сохраняет текст из textarea

Даже и не предусмотрено. Как и работа в (i)frame'ах.

можно это изменить?

Вроде не должно быть сложностей, это же контекстное меню,
туда выделенный текст уже проброшен самим браузером.
Функция saveSelectionToFile() на замену

скрытый текст

Выделить код

Код:

function saveSelectionToFile() {
	var line = ".".repeat(62) + "\n";
	var hint = "Кликни чтобы открыть файл";
	var prfx = "Сохранил выделенный текст в файл ";

	var img = self.getAttribute("image");
	var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
	var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);

	(saveSelectionToFile = async () => {
		var time = aDate(), url = gBrowser.currentURI.displaySpec;
		var text = `${line}${getTabLabel()} - ${time}\n${url}\n\n${
			gContextMenu.contentData.selectionInfo.fullText
		}\n\n\n`;
		try {
			var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
			var msg = prfx + "в папку " + file.leafName;
			await IOUtils.makeDirectory(file.path);
		} catch(ex) {
			file && Cu.reportError(ex);
			file = desk.clone();
			var msg = prfx + "на рабочий стол";
		}
		file.append(`Save - ${time}.txt`);
		await IOUtils.writeUTF8(file.path, text, {mode: file.exists() ? "append" : "create"});

		var name = "sstf-" + Cu.now();
		as.showAlertNotification(
			gBrowser.selectedTab.image || img, msg, hint, true, "",
			(s, t) => t == "alertclickcallback" && file.launch(), name
		);
		setTimeout(as.closeAlert, 8e3, name);
	})();
}

kokoss пишет

Просьба, сделать запускатор для кнопок ATB.

В смысле чтобы кнопки в окне появлялись раньше?
Можно так попробовать (код для custom_script.js).

скрытый текст

Выделить код

Код:

(async url => {
	var manager = ChromeUtils.import(url).ExtensionParent.apiManager;
	var onReady = (e, addon) => {
		if (addon.id == "add_toolbar_buttons@vitaliy.ru")
			onAddon(addon), manager.off("ready", onReady);
	}
	var onAddon = async addon => {
		var mgr = addon.experimentAPIManager;
		var loaded = mgr.getModule("addToolbarButtons").asyncLoaded;
		loaded ? await loaded : mgr.getAPI("addToolbarButtons", addon);

		mgr.global.baseUri = (mgr.global.contExt = addon).baseURL;
		var atb = mgr.global.add_toolbar_buttons;
		style(atb, addon);
		atb.init();
	}
	var style = (atb, addon) => {
		var noop = () => {};
		var sss = atb.styleSS;
		var subst = "v-add-toolbar-buttons-style";
		var args = [Services.io.newURI(`resource://${subst}/`), sss.USER_SHEET];
		var rph = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
		var shutdown = (e, isAppShutdown) => {
			if (isAppShutdown) return;
			sss.unregisterSheet(...args),
			rph.setSubstitution(subst, null);
			manager.on("ready", onReady);
		}
		(style = async (atb, addon) => {
			atb.loadButtonStyle = atb.removeButtonStyle = noop;
			var css = `@-moz-document url(chrome://browser/content/browser.xhtml) {\n${
				await (await fetch(addon.baseURI.resolve("button.css"))).text()
			}\n}`;
			rph.setSubstitution(subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(css)));
			sss.loadAndRegisterSheet(...args);
			addon.once("shutdown", shutdown);
		})(atb, addon);
	}
	manager.on("ready", onReady);
})("resource://gre/modules/ExtensionParent.jsm");

Отсутствует

 

№31516-05-2022 12:53:48

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

Путь к папке сохранения должен браться из настройки browser.download.dir

Ага, только вы написали менять var file = Services.dirsvc.get("Desk", Ci.nsIFile);, ну я его и заменил, а это совсем не там, менять нужно было var file = Services.dirsvc.get('ProfD', Ci.nsIFile); :)
   

Dumby пишет

Функция saveSelectionToFile() на замену

В конце ";" не нужен?
   

Dumby пишет

Мне вот стало любопытно, а сохранялка в pdf,
которая у лисы на борту, сохраняет хуже чем веб-сервис?

Лучше, так как там хоть немного можно настроить вывод. У меня и без расширений пункт Печать позволяет сохранить PDF. Конечно надо заменить этот атавизм (сервис) на встроенную функцию. Вот только как, с выводом окна настроек или с чтением уже имеющихся настроек и моментальным сохранением? Я за второй вариант, если он возможен (настройки печати браузер сохраняет).

Отсутствует

 

№31616-05-2022 15:09:23

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1728
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

Можно так попробовать (код для custom_script.js).
скрытый текст

Благодарю, в актуальной версии UCF работает, а можно сделать что бы работало и в этой версии UCF ?

Отредактировано kokoss (17-05-2022 00:09:04)


Win7

Отсутствует

 

№31716-05-2022 16:00:22

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
UA: Firefox 78.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

менять нужно было var file = Services.dirsvc.get('ProfD', Ci.nsIFile);

Скриншот с форума.

В конце ";" не нужен?

Вообще, после функций не принято, и, за редким исключением, не нужно.
Но если есть сомнение, то можно поставить, хуже не будет.

чтением уже имеющихся настроек и моментальным сохранением

Я так предполагал: ты настроишь тот WebExtensions так, как нужно,
затем выложишь настройки, а я попробую вписать их в код.

вариант публикации

Идём в отладочную консоль аддона, например, открываем вкладку с адресом
about:devtools-toolbox?id=%7B9ab38051-cd73-4e46-b7bd-dc147f6f6b29%7D&type=extension&tool=webconsole


Там запускаем код. Должна открыться вкладка с настройками.
Копируем настройки в пост под спойлер.

Выделить код

Код:

(async () => {
	var data = JSON.stringify(
		await browser.storage.local.get(), null, "\t"
	);
	var url = URL.createObjectURL(
		new Blob([data], {type: "text/plain;charset=utf-8"})
	);
	browser.tabs.create({url})
		.finally(() => URL.revokeObjectURL(url));
})();


Останется определиться с тем, откуда брать
путь к папке для сохранения, и как формировать имя файла.


kokoss пишет

а можно сделать что бы работало и в этой версии UCF ?

Даже не знаю, может так попробуй

скрытый текст

Выделить код

Код:

…
	//manager.on("ready", onReady);
	var policy = Cu.getGlobalForObject(Cu)
		.WebExtensionPolicy.getByID("add_toolbar_buttons@vitaliy.ru");
	policy ? onAddon(policy.extension) : manager.on("ready", onReady);

Отсутствует

 

№31816-05-2022 17:04:26

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1728
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

может так попробуй
скрытый текст

К сожалению у меня не работает. А если для файла config.js ?

заработало

Выделить код

Код:

(async url => {
	var manager = ChromeUtils.import(url).ExtensionParent.apiManager;
	var onReady = (e, addon) => {
		if (addon.id == "add_toolbar_buttons@vitaliy.ru")
			onAddon(addon), manager.off("ready", onReady);
	}
	var onAddon = async addon => {
		var mgr = addon.experimentAPIManager;
		var loaded = mgr.getModule("addToolbarButtons").asyncLoaded;
		loaded ? await loaded : mgr.getAPI("addToolbarButtons", addon);

		mgr.global.baseUri = (mgr.global.contExt = addon).baseURL;
		var atb = mgr.global.add_toolbar_buttons;
		style(atb, addon);
		atb.init();
	}
	var style = (atb, addon) => {
		var noop = () => {};
		var sss = atb.styleSS;
		var subst = "v-add-toolbar-buttons-style";
		var args = [Services.io.newURI(`resource://${subst}/`), sss.USER_SHEET];
		var rph = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
		var shutdown = (e, isAppShutdown) => {
			if (isAppShutdown) return;
			sss.unregisterSheet(...args),
			rph.setSubstitution(subst, null);
			manager.on("ready", onReady);
		}
		(style = async (atb, addon) => {
			atb.loadButtonStyle = atb.removeButtonStyle = noop;
			var css = `@-moz-document url(chrome://browser/content/browser.xhtml) {\n${
				await (await fetch(addon.baseURI.resolve("button.css"))).text()
			}\n}`;
			rph.setSubstitution(subst, Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(css)));
			sss.loadAndRegisterSheet(...args);
			addon.once("shutdown", shutdown);
		})(atb, addon);
	}
    manager.on("ready", onReady);
	var policy = Cu.getGlobalForObject(Cu)
		.WebExtensionPolicy.getByID("add_toolbar_buttons@vitaliy.ru");
	policy ? onAddon(policy.extension) : manager.on("ready", onReady);
})("resource://gre/modules/ExtensionParent.jsm");


thank-you.gif

Отредактировано kokoss (16-05-2022 23:17:30)


Win7

Отсутствует

 

№31916-05-2022 18:26:01

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

Скриншот с форума.

Ну да, и оно сохраняло в профиль, пока не изменил var file = Services.dirsvc.get('ProfD', Ci.nsIFile);, да еще и папку левую там создавало, с названием как папка загрузок браузера.
Теперь все работает и ладно.
   
Ну пусть так будет, вывел все опции. Если оно в скрипте будет человекочитаемым то всегда изменить можно.

скрытый текст

Выделить код

Код:

{
	"footerCenter": "",
	"footerLeft": "&PT",
	"footerRight": "&D",
	"headerCenter": "",
	"headerLeft": "&T",
	"headerRight": "&U",
	"marginBottom": 0.2,
	"marginLeft": 0.2,
	"marginRight": 0.2,
	"marginTop": 0.2,
	"orientation": 0,
	"paperHeight": 11,
	"paperSizeUnit": 1,
	"paperWidth": 8.5,
	"scaling": 1,
	"showBackgroundColors": true,
	"showBackgroundImages": false,
	"shrinkToFit": true,
}

Сохранять стандартно, в папку загрузок браузера.
   
И подскажите как добавить в кнопку пункт "Печать" браузера (шоб имя свое задать можно было), сразу после нынешнего (и будущего) "Сохранить страницу в PDF". Преднастройки это хорошо, но хотелось бы иметь возможность настройки из UI.

Отсутствует

 

№32017-05-2022 09:48:44

Dumby
Участник
 
Группа: Members
Зарегистрирован: 12-08-2012
Сообщений: 2129
UA: Firefox 78.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

    "paperHeight": 11,
    "paperSizeUnit": 1,
    "paperWidth": 8.5,

Странно, paperSizeUnit единица.
1 — это nsIPrintSettings.kPaperSizeMillimeters (миллиметры).


Наверно имелся в виду ноль.
0 — это nsIPrintSettings.kPaperSizeInches (дюймы).
А то получается размер с ноготь мизинца.


Вобщем, пока такой набросок замены функции savePageToPDF()
И, на всякий случай, idl'ки: release и esr91,
вдруг захочется с оставшимися настройками повозиться.

скрытый текст

Выделить код

Код:

function savePageToPDF() {
	var ps = Ci.nsIPrintSettings, cfg = {

		paperWidth: 8.5,
		paperHeight: 11,
		paperSizeUnit: ps.kPaperSizeInches, // kPaperSizeMillimeters

		marginLeft: 2,
		marginRight: .2,
		marginTop: .2,
		marginBottom: .2,

		edgeLeft: .1,
		edgeRight: .1,
		edgeTop: 0,
		edgeBottom: 0,

		headerStrLeft: "&T",
		headerStrCenter: "",
		headerStrRight: "&U",

		footerStrLeft: "&PT",
		footerStrCenter: "",
		footerStrRight: "&D",

		printBGColors: true,
		printBGImages: false,

		scaling: 1,
		shrinkToFit: true, // overrides scaling
		orientation: ps.kPortraitOrientation, // kLandscapeOrientation

		printerName: "",
		printSilent: true,
		printToFile: true,
		showPrintProgress: false,
		isInitializedFromPrefs: false,
		isInitializedFromPrinter: false,
		outputFormat: ps.kOutputFormatPDF,
		outputDestination: ps.kOutputDestinationFile,
	};
	ps = Cc["@mozilla.org/gfx/printsettings-service;1"]
		.getService(Ci.nsIPrintSettingsService).newPrintSettings;
	for(var key in cfg) if (key in ps) ps[key] = cfg[key];
	(savePageToPDF = async () => {
		try {
			var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
			await IOUtils.makeDirectory(file.path);
		} catch {
			file = Services.dirsvc.get("Desk", Ci.nsIFile);
		}
		file.append(`Snap ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")}.pdf`);
		ps.toFileName = file.path;
		await gBrowser.selectedBrowser.browsingContext.print(ps);
		//file.launch();
	})();
}

как добавить в кнопку пункт "Печать" браузера (шоб имя свое задать можно было)

Пункт который из гамбургера?
Ну, меню кнопки в начале кода расписано,
можно вклинить что-то типа

скрытый текст

Выделить код

Код:

{ label: "Союзпечать", func: document.getElementById(document.getElementById("appMenu-viewCache").content.querySelector("[key=printKb]").getAttribute("command")).getAttribute("oncommand"), image: "chrome://global/skin/icons/print.svg"},

Отсутствует

 

№32117-05-2022 20:21:00

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby пишет

paperSizeUnit

Забыл вернуть, я же пытался все настройки вывести.
В общем, шикарно получилось. Спасибо. И главное без стороннего сервиса и с возможностью настройки.
   
А для открытия списков URL и сохранения списка адресов, выбранных или всех текущих вкладок, есть скрипт? Из буфера обмена / файла, в буфер обмена / файл / закладки.

Отсутствует

 

№32217-05-2022 20:38:05

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt пишет

В общем, шикарно получилось.

И что получилось, можно итоговый вариант?

Отсутствует

 

№32318-05-2022 14:21:41

_zt
Участник
 
Группа: Members
Зарегистрирован: 10-11-2014
Сообщений: 1419
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

voqabuhe

скрытый текст

Выделить код

Код:

self.label = "Save";
self._handleClick =()=> menuPopup.openPopup(this, "after_start");
self.image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAABGklEQVQ4EaWSvQ4BQRSFd/3EUouGksIDiNBLvMAqtVoaiShUHkItIRGd1iN4A0ql2l8wvruxw67FJuR87p05d85OFsP482PKeaVUjWpDDKpwgyAd2GyZprmiPkXAWFbUIvSld2EdgQ5UYApzKLl+xG2+VAuvDjZcoAldQspUI0yAzMXlS+D6e6qEtKlvAVc2o/CqI4sJTMF5Z4Qc6OU2hrw0eq01XZLrjah+ldhYgEeeAJIVbg9CyxMgp3j6kFqAIK15SP/V8ARwOI95ZqhBfRP+QCmVx9+4pv9XiGNc4JPEkxnt+wO0EbbRAVwtwyELfsl6zDpzOoBVFlLwSzIjs86c88cgscbKhgSkYQtByrG5gxPMeJlL6n+6A9I+WoE5cj6LAAAAAElFTkSuQmCC";


var folderpath="E:\Download";         // папка для сохранения иконок для ярлыков и ярлыков сайтов

// Создать меню для кнопки .............
var array = [
   { label: "Сохранить favicon сайта", func: "saveFavicon()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAACPVBMVEX09ff////C3L+Uq8+Vq8+Uqs+Zr9CZrtCZr9Gfu+ear8+mt9JRf8ORxl3t8vfF06+Twojs8/d9otl8o9s+aquZrs/X9KLp8Pft8fZhisf//+DBzN2hveihv+pii8hti9pgicl6oNlojs1zncNsi836/P2duebx8/eYyWqBp+Gn0IKBvlKHsm9qmaVuk8zt7/FEbauEv1Tp7/JdhL9oi9Pl8e2LwlmdsdD7/P76+/3H7ofo8+peh8eHwFaSteZ0pkp2gl7q8/Ohy5OApt2by2eZuOqbuOWaezWuvtd7nN2HvWxul9Ty9feQxV5ljcqBp+JEcLCVtOOo0nR7odx5n9suX6Z1mtBzmtSXyGPv9PewzfOzx+O6zu/s8fd9o95Xfrthi8lYhMN5oNnw9ffw9Pjw9Pf8/f6ewO/m8O9zmdE6aapsjdyUwouPxWPDzd6XteOSs9B5nNVpnpqHt7h/s6F6n9d7ntSTttGHwVh4qp+Ev1HH7ox6qk5wj+Hm8e3t9fOm0IKAtqOBpNrx+P9ljcyhs9FpkM2hv+/u8/fF0eOLu4N+vFKgzX3p9OSFqN13qExekIl4n9j7/P3x9PhxmNDm8e9Vg8Zfkozr8veq0YTX9qL//92AtamOwnHFz96Fot1diMh+pd13ntmatu+YyW/3+/+Tqs5UgcShzJNbhsdTf8GHs7bo8PaXtuqMr+Ty8/SZt+SUqs7r7Ox3ndb9/f7t8feZyXGYyWWCpNbz9PRuiteNtNDn7/V4ntjx8fGo3JqNAAAAv3RSTlP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AEVuhDkAAAD+SURBVBhXY5jHzcUMAqxAICq9bx8D96adDFAgaGQOFOBaH7h7zoqZDTlFyptncAAFWBjyi52CXCI0unRLxcECPhsatbbzmlXMnS60hg0kkOxW0uNrq93tNaFpD1ggUm21QK532ZQdSm1hmXKdDCwdnOWVOi1RjNGMQCCrwMDMJ8NZ4LAynVGPkXFp8zpJBubYmn579wXtqhZb0iwn9a1iWLaViYmJ3891obOwYtLEvcYMGyWAAkwJdv6accEhi8LjGVr11SenpC5f61g3NcO0vjCAIc+DjZ2dnWexddWSbYa9nlkM+8BgWsxsK7FZ1VLzRaACNokmtdnyu1QMQgF7Rlh4zWWTAwAAAABJRU5ErkJggg=="},
   { label: "Копировать favicon в base64", func: "copyFaviconData()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAI2bv/9RVpf/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAACIkvD/Jia6/ywpq/8AAAAAAAAAAAAAAAAAAAD/AAAA/wbwAf90qpv/Ymic/1RWqP9OUKr/W2Ch/2dumf9YYKT/Ly/B/xQP3/8MB9P/JCGb/wAAAAAAAAAAAAAAAAAAAP8G8AH/U5ea/ycr8f8VIP3/HiP4/ywo8v8sIvb/LCL2/ywi9v8KBOj/BQDe/wQAtv8tK4P/AAAAAAAAAAAAAAD/BvAB/3Sqm/9iaJz/Tim3/0UuuP9GPrT/R0ex/zk8uf8gIMz/FRDe/xEMzv8jIJz/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8AAAD/SqOR/yImvP8sLKj/AAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/BvAB/3Sqm/9KW5r/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAABvAB/wbwAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/BvAB/wbwAf8G8AH/AAAAAAAAAAAAAAAAAAAAAAAAAAAG8AH/AAAAAAAAAP8G8AH/AAAAAAAAAAAAAAAAAAAA/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAP8G8AH/BvAB/wbwAf8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/BvAB/wbwAf8AAAAAAAAA/wAAAP8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/AAAAAAAAAAAG8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wbwAf8G8AH/BvAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOesQQBjrEGAAaxBwACsQcABrEHDg6xBwAesQcAPrEHAD6xBw8+sQcPprEHD8axBwAGsQQABrEGAAaxB//+sQQ=="},  
   { separator: ''},
   { label: "Сохранить ярлык страницы как…", func: "saveShortcuts()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/BP8k/wT/JP8E/yT/BP8k/5XLDv/zqgD/86oA//I1///yNf//86oA//OqAP/zqgD/86oA//OqAP+Vyw7/lcsO/wT/JP8E/yT/BP8k/5XLDv+Vyw7/86oA//OqAP/yNf//8jX///OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA//02AP/9NgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP/9NgD//TYA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/wT/JP+Vyw7/86oA//OqAP/zqgD/86oA/wA31v8AN9b/86oA//9If///SH//86oA//OqAP/zqgD/86oA/5XLDv8E/yT/lcsO//OqAP/zqgD/86oA//OqAP8AN9b/ADfW//OqAP//SH///0h///OqAP/zqgD/86oA//OqAP+Vyw7/BP8k/5XLDv/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/lcsO/5XLDv+Vyw7/86oA//OqAP/zqgD/86oA/0CA//9AgP//86oA/07+9f9O/vX/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP9AgP//QID///OqAP9O/vX/Tv71//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/86oA//OqAP/zqgD/AACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQ=="},
   { separator: ''},  
   { label: "Копировать изображение / текст в base64", func: "copyFaviconbase()", image: "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AIAQ/wCAEf8AgA//AIAR/wCAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AgBX/AIAVAAAAAAAAAAD/AIAo/wCA//8AgP//AID//wCA//8AgP//AIAoAAAAAAAAAAAAAAAAAAAAAP8AgBL/AID//wCA//8AgA3/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgBAAAAAAAAAAAAAAAAD/AIAR/wCA//8AgP//AIAK/wCACv8AgP//AID//wCAIf8AgAX/AIAh/wCA//8AgP//AIAQAAAAAAAAAAAAAAAA/wCACv8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAUAAAAA/wCABf8AgP//AID//wCACgAAAAD/AIAQ/wCADP8AgCH/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCABf8AgCH/AID//wCA//8AgAv/AIAh/wCA//8AgP//AID//wCA//8AgP//AIAH/wCAB/8AgP//AID//wCA//8AgP//AID//wCA//8AgP//AIAg/wCA//8AgP//AID//wCA//8AgP//AID//wCAB/8AgAf/AID//wCA//8AgP//AID//wCA//8AgP//AIAh/wCAC/8AgP//AID//wCAHP8AgBz/AID//wCA//8AgAf/AIAH/wCA//8AgP//AIAh/wCACf8AgA7/AIAMAAAAAP8AgAj/AID//wCA//8AgAP/AIAD/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCABQAAAAAAAAAA/wCADf8AgAr/AIAL/wCA//8AgP//AIAH/wCAB/8AgP//AID//wCAB/8AgAr/AID//wCA//8AgCH/AIAH/wCAJf8AgP//AID//wCAI/8AgP//AID//wCAB/8AgAf/AID//wCA//8AgAf/AIAL/wCA//8AgP//AID//wCA//8AgP//AID//wCA//8AgCT/AID//wCA//8AgAr/AIAK/wCA//8AgP//AIAKAAAAAP8AgCj/AID//wCA//8AgP//AID//wCA//8AgCP/AIAM/wCA//8AgP//AIAN/wCADf8AgP//AID//wCADQAAAAAAAAAA/wCAEP8AgBH/AIAP/wCAEf8AgBAAAAAAAAAAAP8AgBT/AIAVAAAAAAAAAAD/AIAV/wCAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//+sQcH5rEGA8KxBAHCsQQBwrEEIQKxBAACsQQAArEEAAKxBAQCsQQwArEEAAKxBAACsQYAArEHBmaxB//+sQQ=="},
   { separator: ''},
   { label: "Сохранить страницу как PDF", func: "savePageToPDF()", image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYUw4pJt3V/+Rb1D8lnFP/55zTf+VcVH/lXJS/5VyUv+VclL/lXJS/5VyUv+VclL/k3BR/J56Wv9cRzSkAAAAAJNvUKTto2L/4ppe/uehZf/Pmmr/noZv/9Scav/Wl17/1plh/9eZYf/XmWH/15lh/9eZYf/WmGD/2Jlg/suRXP9mRiuk8rWA/397dP1akKn/rqqi/3LF3f8Mntj/4dLJ///+9f/48u3/9e7n//bt5v/47+f/+O/n//jv5//rvZP/1ZJX/a9/VP9+lrD8AIvz/xOt+f8Douv/ALb6/wC28/9tmar/z8jJ//Lq5/////7//v////n9///6/P3//////+Ta0P/PjVP/pnpT/IWds/+aiXj/5efl/8Px//951/3/LMz//wCx8/8GltL/NIu3/4ycqf/l29L////+//n6+//8/v//3tXM/8+OVP+oe1P/6K57/86QWP/r6Ob////////++v/r9/z/oOb9/zDL//8Arf//AI/r/ydysv+hpqr//PTr///////d1Mz/0I5U/6h7U//osH//wo5g/+fm5P/7/f//9vf5//z7+////vv/9/r8/5Dc/P8Oqv7/AJf//wF02v9ffZ7/8Ojh/+Ha1P/NjFL/qHtT/+ewf//Ej1//7O3r///////+/v7//v7+//f5+v/6+vv////8/8Tq/f8hp/7/AJH//wB18/8/bqj/1MGu/9mXXv+leVH/569+/8iSYv+/tKn/wLew/8O5sf/P0M////////7+/v/3+fv////7/9Hv/v8hoP3/AIn//wB4/v84ZqL/w4NH/619VP/nsYD/x45c/9W5of/bv6j/0Jxt/6J/YP+spqD/2N3i//7////6+/3///76/8vr/v8Slv7/AIb+/wBz//83VH7/nW1B/+ewfv/Fjl7/7Ozr///////9+/r/9d7K/9Ghdv+jd1D/pJ6Y/+jt8f/9///////7/6fb/v8Ahv7/AYD//wRp6f95YlT/57B//8SOXv/n5uT//v7///r7/P/8/v////////XRsv/DhEv/loBu/9DX3P/9/v/////7/2O6/f8Afv//FnTU/5JtTf/nsH//xY9e/+jn5f/+/f//+fj5//n4+P/5+Pn/+/////Xbxf/Wj1D/nX1h/+Ll6P////7/3+/3/w+V//8tcbP/qHJB/+WuffzCjV7/5efn///////+/v7//////////////v7///////XRsP/TnW3/8fT3//////////z/ddD//0Nxl/+zdkH88LmH/9CRWP2+qJT/0M7N/8/Jxv/Pysf/z8rH/8/Kxv/Py8n/zsO6/7+pmP/PzMv/zsnG/9bNyP+nsK7/h4R3/b2BT/+Sb1Ck7qxw/9GSW/69hlb/wYhX/8CIV//AiFf/wIhX/8CIVv/BiVj/xI1d/8CIVv/BiFf/vYZW/9STW/7ppmv/bE80pAAAAACUd16k+sui/+7AmPzwwpr/8MKa//DCmv/wwpr/8MKa//DCmf/vwZj/8MKa//DCmv/uwJj8+cui/5N3XaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="},
   { label: "Печать / печать в PDF", func: document.getElementById(document.getElementById("appMenu-viewCache").content.querySelector("[key=printKb]").getAttribute("command")).getAttribute("oncommand"), image: "chrome://global/skin/icons/print.svg"},
   { label: "Сохранить страницу / выбор как HTML", func: "savePageToHTML()", image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACzElEQVQ4jV2STW8bZRDHf/Psrr11nZhgVKcKaSmUiArRKBRVIMgH4BKJ7xAp5MSFiA+Rc28ckBAoipC4koJQLyAaVFChIlQllDRWmjRev8Qvu14/+wwHx6ZlpNFcZn7zn79GVJW1tbXc6urqijHGqKoAPF3TgcVaq8owXJbphx99fOOnWzcHoqqsr68/t7y83BARVBXnHHraXo3a3HoUU8gFAHRTS2Bg/7C2Zx7vXPIBwjA0p3BU9Zns9i3vvVrhr6MWzlpee+EsRqAbHc3+/Pee7wPkcrkx4P+g0IMvb/5Iv5/iXEaWZQS+By578MaVy9YH8H3fE5FnANZajqMmgcAnH7yN73mICMYMd21sbLy7srKiPkA+n3/qBLhzv8p+EuOfTUjShPbODvOVWa5fnRsvKBaLAcAIMFbw+bc/EBVn8At7SPcQ60LSiVm++P0fGu0e7y++yalvHoABCILAiAj7hzU+vfcVT6zPVGmR3x4/xJoLSH6BVu4cN777nnQwQETI5XL/AYwxRkS4ff8BEk6Q2pBfq3dxUuHMmWt0kgFGStTDY/7YrTLybQwYPU2cpgzsCd1OgmSzWHeOR7VjWicxaT9lxn+HfjoYmWnGHgAiIsydf5HKnUXiThehQDG4Tr3e5KR7hN8XilnGKxfOoyrDgZECwIgIb125xIxxTGVdgjRG4pR2+zbG/sIkD7l2cYJyaYLMOZxzjBV4nueLCI1GnaWFab65t4OXt4gUuFqYJ8gGuPYBCxdLHNciys9PkaapjAHGGM8YQ7lcZv71OaYmC/xZPaJHTN4cUgpDXrr8MtOVaUqTRXzfY3t7u7O0tDR82a2trfkkSTSOY+31etrpdLTZbGoURRpFkdbrTY3qTW00mhrHse7u7t4tl8uhqg4VxHHcPDg4+ExVHeBU1YmIU1WnisucZtamLszn01ar9WRzc/PrWq2WAPwLJ7l2ULfXOAMAAAAASUVORK5CYII="},
   { label: "Сохранить URL вкладки / выбор как TXT", func: "saveSelectionToTxt()", image: "data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAQE6AAAAZAAAAGgAAAJmAAACZgAAAGYAAABmAAAAZgAAAGYAAABmAAAAZgAAAGYAAABlAAAAaQABAmYAAQEjAAAAADlVkOdVcKHxVXKi8kdklPJLZpfyU3Cg8lJvn/JRbZ7yUW+g8lFun/JRbp/yUG6e8lVyofFVdKjzLkV45wAAAFABAQEAaIzF/3y34v9wsuL/cJe0/0lpgv9bjLP/dLLh/2+v3v9sq9v/cK3d/3Gv3v9sqtv/b7Df/4G77P9VcqT2AAAAVAMDAQBnir/+ZqfU/pDB4/7a3uD+j46N/kxYXv6To6/+1er4/tXp+P7J3/D+1ej4/svg8v6Gut/9aqzd/lhxnvAAAABSAwIBAGaIvv9pptX/ocfj//f4/P/P0tX/g4CA/1xZWf+Woqr/2uz8/9Hl+f/W5fT/2Of3/5fC4v5tq93/Vm+e8QAAAFIDAgEAaYm+/3mw2/+iyeX/9Pn8/+z0+//IzNL/d3h5/0tMTv+Mkpn/xdvs/9Hp/f/O4PL/msXk/nmz4/9XcJ/xAAAAUgMDAQBti7//k7/h/6fL5v/v9fn/4u73/9Dk9P+8wMT/YGpx/zJJWv94iJf/ztzo/9Pp/P+ZwuD+gLfk/1dwnvEAAABSAwMBAHOPwf+myub/sNHp//j7/P/6/P3/8fr///r39P+sxdP/IXWq/xJJcv+NjZD/0+Lu/6TN7f6Ft+L/WXGf8QAAAFIDAwEAd5LD/7PR6/+ZxOP/0ePx/97r9f/Y5/L/3e32/8Tc7f9gseT/CHK3/zBYdv+HiY7/lL/f/pLE7/9bcJ3xAAAAUgMDAQB4k8P/xNvx/5/F5f+kyOX/qMrn/6TH5f+kyOX/sM/q/5e51P9Mm83/GHm3/xxIav9fdYf+pMvs/1x1pfIAAABTAwMBAHmSxf/O4/T/y9/y/8Hb9P/C3PX/wNv0/7vW7/+93ff/utDm/42fsf9Gjbn/EXS2/ytSbv6Fj5r/WnGc8gAAAFICAwEBepPE/tHk9f/S5PX/vMjV/7fCzP+3w8//uMPP/7XBzP+6ytf/qa+4/3h/hv9Ghaz/JoO+/jNXdP82PVnyAAAAVgACAgCBmcb/2+r3/dHh8fyPkpX/kI6N/5yam/+dnJ3/paWk/6enpf+sr6//mpSR/3Bubf9SjbD8H4C+/QsrSvcCAAB/AAAAA3yVx//j8///3u/7/52gpf6pqKf+uLm5/rq7u/7Ly8v+ycnI/paWlf6LjY/+np2f/Xh+g/5gnL7/MX+y/xcgJ80BAgNNN1OUs6W84fDA1O73mJyj/ainpv+2trb/t7e4/8fHyP/Fxsb/kZGQ/4eGhP+vucT/j6G+/W53k/NlkbnwNoOv/AgiNb8CCBsQDRo/YwsaO3B0d33arKyp9q2trfWvr6/2u7u79ru7vPawr7H1sbCt9nJ2gOQIGD6bFCFEYB0qPE1Bf6SpEz9cggAAAAMCAQEBAQAAADIyMmlDQ0ONQUFBhUFBQYVCQkGFQkJBhUhISIRNTU2OKysrZAEAAAUBAQAAAgEAAAkEAAEDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="},
   { separator: ''},
   { label: "(Меню ПКМ) Сохр./добавить текст в файл", value: "Save.SelectionToFile" },
   { label: "(Меню ПКМ) Открыть текст в редакторе", value: "Save.TextToEditor"},
];

var menuPopup = self.appendChild(document.createXULElement("menupopup"));
array.forEach((m,i)=> {
   if ("separator" in m) { menuPopup.appendChild(document.createXULElement("menuseparator")); return };
   var mItem = menuPopup.appendChild(document.createXULElement("menuitem"));
   mItem.setAttribute("label", m.label);
   mItem.setAttribute("class", "menuitem-iconic");
   if ("image" in m) mItem.setAttribute("image", m.image || array[i-1].image); 
   if ("value" in m) { 
       mItem.setAttribute('type', 'checkbox');
       mItem.setAttribute('checked', cbu.getPrefs(m.value) );
       mItem.onclick =()=> cbu.setPrefs(m.value, !cbu.getPrefs(m.value));
       }
   if ("func" in m) mItem.addEventListener("command", ()=> eval(m.func.toString()));
});
menuPopup.setAttribute("onclick", "event.stopPropagation()");


function aDate() {
 var t=new Date();
 var y=1900+t.getYear();
 var min=t.getMinutes(); if (min<10){min="0"+min};
 var h=t.getHours();
 var m=t.getMonth();switch(m){case 0: m="января";break;case 1: m="февраля";break;case 2: m="марта";break;case 3: m="апреля";break;case 4: m="мая";break;case 5: m="июня";break;case 6: m="июля";break;case 7: m="августа";break;case 8: m="сентября";break;case 9: m="октября";break;case 10: m="ноября";break;default: m="декабря";}
 var d=t.getDate();
 var curdate=d+" "+m+" "+y+" "+"г";
 var myfilename=curdate;
 return myfilename;
}
 

function WebScreenShotonImage(image) {
      var canvas = document.createElementNS(xhtmlns, 'canvas');
      canvas.width = image.naturalWidth;
      canvas.height = image.naturalHeight;
      var ctx = canvas.getContext('2d');
      ctx.drawImage(image, 0, 0);
      var base64 = canvas.toDataURL();
      gClipboard.write(base64);
   
      // стиль для изображение в сплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Запомнил изображение как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(base64, self.label, "Изображение копировано как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
};


var saveToFile = function (fileContent, fileName) {
    var uc = Components.classes['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
    uc.charset = 'utf-8';
    fileContent = uc.ConvertFromUnicode(fileContent);

    var nsIFilePicker = Components.interfaces.nsIFilePicker;
    var fp = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
    fp.init(window, '', fp.modeSave);
    fp.defaultString = fileName;
    fp.appendFilters(fp.filterHTML);
    fp.appendFilters(fp.filterAll);
    fp.open(function (rv) {
  if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
    var stream = Components.classes['@mozilla.org/network/file-output-stream;1'].createInstance(Components.interfaces.nsIFileOutputStream);
    stream.init(fp.file, 0x02|0x20|0x08, 0666, 0);
    stream.write(fileContent, fileContent.length);
    stream.close();
  }
});
};


function savePageToHTML() {
var vert = String.raw`javascript:(function(){var getSelWin=function(w){if(w.getSelection().toString())return w;for(var i=0,f,r;f=w.frames[i];i++){try{if(r=getSelWin(f))return r}catch(e){}}};var selWin=getSelWin(window),win=selWin||window,doc=win.document,loc=win.location;var qualifyURL=function(url,base){if(!url||/^([a-z]+:|%23)/.test(url))return url;var a=doc.createElement('a');if(base){a.href=base;a.href=a.protocol+(url.charAt(0)=='/'%3F(url.charAt(1)=='/'%3F'':'//'+a.host):'//'+a.host+a.pathname.slice(0,(url.charAt(0)!='%3F'&&a.pathname.lastIndexOf('/')+1)||a.pathname.length))+url}else{a.href=url};return a.href};var encodeImg=function(src,obj){var canvas,img,ret=src;if(/^https%3F:%5C/%5C//.test(src)){canvas=doc.createElement('canvas');if(!obj||obj.nodeName.toLowerCase()!='img'){img=doc.createElement('img');img.src=src}else{img=obj};if(img.complete)try{canvas.width=img.width;canvas.height=img.height;canvas.getContext('2d').drawImage(img,0,0);ret=canvas.toDataURL((/%5C.jpe%3Fg/i.test(src)%3F'image/jpeg':'image/png'))}catch(e){};if(img!=obj)img.src='about:blank'};return ret};var toSrc=function(obj){var strToSrc=function(str){var chr,ret='',i=0,meta={'%5Cb':'%5C%5Cb','%5Ct':'%5C%5Ct','%5Cn':'%5C%5Cn','%5Cf':'%5C%5Cf','%5Cr':'%5C%5Cr','%5Cx22':'%5C%5C%5Cx22','%5C%5C':'%5C%5C%5C%5C'};while(chr=str.charAt(i++)){ret+=meta[chr]||chr};return'%5Cx22'+ret+'%5Cx22'},arrToSrc=function(arr){var ret=[];for(var i=0;i<arr.length;i++){ret[i]=toSrc(arr[i])||'null'};return'['+ret.join(',')+']'},objToSrc=function(obj){var val,ret=[];for(var prop in obj){if(Object.prototype.hasOwnProperty.call(obj,prop)&&(val=toSrc(obj[prop])))ret.push(strToSrc(prop)+': '+val)};return'{'+ret.join(',')+'}'};switch(Object.prototype.toString.call(obj).slice(8,-1)){case'Array':return arrToSrc(obj);case'Boolean':case'Function':case'RegExp':return obj.toString();case'Date':return'new Date('+obj.getTime()+')';case'Math':return'Math';case'Number':return isFinite(obj)%3FString(obj):'null';case'Object':return objToSrc(obj);case'String':return strToSrc(obj);default:return obj%3F(obj.nodeType==1&&obj.id%3F'document.getElementById('+strToSrc(obj.id)+')':'{}'):'null'}};var ele,pEle,clone,reUrl=/(url%5C(%5Cx22%3F)(.+%3F)(%5Cx22%3F%5C))/g;if(selWin){var rng=win.getSelection().getRangeAt(0);pEle=rng.commonAncestorContainer;ele=rng.cloneContents()}else{pEle=doc.documentElement;ele=(doc.body||doc.getElementsByTagName('body')[0]).cloneNode(true)};while(pEle){if(pEle.nodeType==1){clone=pEle.cloneNode(false);clone.appendChild(ele);ele=clone};pEle=pEle.parentNode};var sel=doc.createElement('div');sel.appendChild(ele);for(var el,all=sel.getElementsByTagName('*'),i=all.length;i--;){el=all[i];if(el.style&&el.style.backgroundImage)el.style.backgroundImage=el.style.backgroundImage.replace(reUrl,function(a,b,c,d){return b+encodeImg(qualifyURL(c))+d});switch(el.nodeName.toLowerCase()){case'link':case'style':case'script':el.parentNode.removeChild(el);break;case'a':case'area':if(el.hasAttribute('href')&&el.getAttribute('href').charAt(0)!='%23')el.href=el.href;break;case'img':case'input':if(el.hasAttribute('src'))el.src=encodeImg(el.src,el);break;case'audio':case'video':case'embed':case'frame':case'iframe':if(el.hasAttribute('src'))el.src=el.src;break;case'object':if(el.hasAttribute('data'))el.data=el.data;break;case'form':if(el.hasAttribute('action'))el.action=el.action;break}};var head=ele.insertBefore(doc.createElement('head'),ele.firstChild);var meta=doc.createElement('meta');meta.httpEquiv='content-type';meta.content='text/html; charset=utf-8';head.appendChild(meta);var title=doc.getElementsByTagName('title')[0];if(title)head.appendChild(title.cloneNode(true));head.copyScript=function(){if('$'in win)return;var f=doc.createElement('iframe');f.src='about:blank';f.setAttribute('style','position:fixed;left:0;top:0;visibility:hidden;width:0;height:0;');doc.documentElement.appendChild(f);var str,script=doc.createElement('script');script.type='text/javascript';for(var name in win){if(name in f.contentWindow||!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name))continue;try{str=toSrc(win[name]);if(!/%5C{%5Cs*%5C[native code%5C]%5Cs*%5C}/.test(str)){script.appendChild(doc.createTextNode('var '+name+' = '+str.replace(/<%5C/(script>)/ig,'<%5C%5C/$1')+';%5Cn'))}}catch(e){}};f.parentNode.removeChild(f);if(script.childNodes.length)this.nextSibling.appendChild(script)};head.copyScript();head.copyStyle=function(s){if(!s)return;var style=doc.createElement('style');style.type='text/css';if(s.media&&s.media.mediaText)style.media=s.media.mediaText;try{for(var i=0,rule;rule=s.cssRules[i];i++){if(rule.type!=3){if((!rule.selectorText||rule.selectorText.indexOf(':')!=-1)||(!sel.querySelector||sel.querySelector(rule.selectorText))){style.appendChild(doc.createTextNode(rule.cssText.replace(reUrl,function(a,b,c,d){var url=qualifyURL(c,s.href);if(rule.type==1&&rule.style&&rule.style.backgroundImage)url=encodeImg(url);return b+url+d})+'%5Cn'))}}else{this.copyStyle(rule.styleSheet)}}}catch(e){if(s.ownerNode)style=s.ownerNode.cloneNode(false)};this.appendChild(style)};var sheets=doc.styleSheets;for(var j=0;j<sheets.length;j++)head.copyStyle(sheets[j]);head.appendChild(doc.createTextNode('%5Cn'));var doctype='',dt=doc.doctype;if(dt&&dt.name){doctype+='<!DOCTYPE '+dt.name;if(dt.publicId)doctype+=' PUBLIC %5Cx22'+dt.publicId+'%5Cx22';if(dt.systemId)doctype+=' %5Cx22'+dt.systemId+'%5Cx22';doctype+='>%5Cn'};var href = 'data:text/html;charset=utf-8,' + encodeURIComponent(doctype + sel.innerHTML + '\n<!-- This document saved from ' + (loc.protocol != 'data:' ? loc.href : 'data:uri') + ' -->');var a = document.documentElement.appendChild(document.createElement("a"));a.setAttribute("href", href);var name = selWin ? win.getSelection().toString() : (title && title.text ? title.text : loc.pathname.split('/').pop());name=name.replace(/[:\\\/<>?*|"]+/g, '_').replace(/\s+/g, ' ').slice(0, 100).replace(/^\s+|\s+$/g, '');name += (function () {var d = new Date(), z=function(n){return '_' + (n < 10 ? '0' : '') + n};return z(d.getHours()) + z(d.getMinutes()) + z(d.getSeconds());})();a.setAttribute("download", name + ".html");a.click();a.remove();})();`;
gBrowser. loadURI(vert, {triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal()});
};


function saveShortcuts() {
var file = Components.classes["@mozilla.org/file/local;1"].
           createInstance(Components.interfaces.nsIFile);
file.initWithPath(folderpath);

if( !file.exists() || !file.isDirectory() ) {   file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0x1B6);}

var savetodir=folderpath+"\\"; 
var urllink=gBrowser.currentURI.spec;
var out=getTabLabel();
var filename=savetodir+out+'.url';
var data="[InternetShortcut]\r\nURL="+urllink+"\r\n";

saveToFile(data, filename);
 // стиль для изображения во всплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
   // подсказка
   var notific = 'Сохранил в: ' + folderpath;
   var image = gBrowser.selectedBrowser.mIconURL;
   Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(image, filename, notific);
};

// Кодировать изображение или текстовой файл в base64 .............
function copyFaviconbase(){
var fp = window.makeFilePicker();
fp.init(window, "Открыть файл", fp.modeOpen);
fp.appendFilter("Text and images", "*.txt; *.text; *.css; *.js; *.ini; *.rdf; *.xml; *.html; *.htm; *.shtml; *.xhtml; *.jpe; *.jpg; *.jpeg;\
                                    *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw");
  fp.open(re=> { 
  if ( re != fp.returnOK ) return;
   var file = fp.file;
   var inputStream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
   inputStream.init(file, 0x01, 0600, 0);
   var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
   stream.setInputStream(inputStream);
   var encoded = btoa(stream.readBytes(stream.available()));
   var contentType = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService).getTypeFromFile(file);
   var dataURI = "data:" + contentType + ";charset=utf-8;base64," + encoded;
   gClipboard.write(dataURI);
   //Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Текст скопирован как  base64");
    // стиль для изображение в сплывающей подсказке ....
      var sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
      var uri = makeURI('data:text/css,'+ encodeURIComponent('#alertImage { height: 25px !important; width: 25px !important; }'));
      sss.loadAndRegisterSheet(uri, 0);
      
     // alertsService.showAlertNotification(base64, self.label, "Изображение скопировано как base64", false, "", (s, t)=> { 
     Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService).showAlertNotification(dataURI, self.label, "Изображение скопировано как base64", false, "", (s, t)=> {
         if (t == 'alertfinished')
             sss.unregisterSheet(uri, 0); // удалить стиль когда подсказка закрывается
      }, "");
});
};

// Сохранить страницу как PDF, скриптом .............
function savePageToPDF() {
    var ps = Ci.nsIPrintSettings, cfg = {

        paperWidth: 8.5,
        paperHeight: 11,
        paperSizeUnit: ps.kPaperSizeInches, // kPaperSizeMillimeters

        marginLeft: .2,
        marginRight: .2,
        marginTop: .2,
        marginBottom: .2,

        edgeLeft: .1,
        edgeRight: .1,
        edgeTop: 0,
        edgeBottom: 0,

        headerStrLeft: "&T",
        headerStrCenter: "",
        headerStrRight: "&U",

        footerStrLeft: "&PT",
        footerStrCenter: "",
        footerStrRight: "&D",

        printBGColors: true,
        printBGImages: false,

        scaling: 1,
        shrinkToFit: true, // overrides scaling
        orientation: ps.kPortraitOrientation, // kLandscapeOrientation

        printerName: "",
        printSilent: true,
        printToFile: true,
        showPrintProgress: false,
        isInitializedFromPrefs: false,
        isInitializedFromPrinter: false,
        outputFormat: ps.kOutputFormatPDF,
        outputDestination: ps.kOutputDestinationFile,
    };
    ps = Cc["@mozilla.org/gfx/printsettings-service;1"]
        .getService(Ci.nsIPrintSettingsService).newPrintSettings;
    for(var key in cfg) if (key in ps) ps[key] = cfg[key];
    (savePageToPDF = async () => {
        try {
            var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
            await IOUtils.makeDirectory(file.path);
        } catch {
            file = Services.dirsvc.get("Desk", Ci.nsIFile);
        }
        file.append(`Snap ${new Date().toLocaleString("mn").replace(/:/g, "\ua789")}.pdf`);
        ps.toFileName = file.path;
        await gBrowser.selectedBrowser.browsingContext.print(ps);
        //file.launch();
    })();
};

if (typeof window.saveImageURL != "function") var saveImageURL = internalSave.length == 15
    ? (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
        internalSave(url, null, name, a9, type, a4, a3, null, a6, null, a7, a5, null, priv, prin)
    : (url, name, a3, a4, a5, a6, a7, type, a9, priv, prin) =>
        internalSave(url, null, name, a9, type, a4, a3, null, a6, a7, a5, null, priv, prin);

// Сохранить иконку текущего сайта с диалогом сохранения .............
function saveFavicon() {
       var uri = gBrowser.currentURI;
       function getSiteName() {
                  try { var domain = uri.host.split('.') } catch(e) { return "" };
                   domain = (domain.length == 2) ? domain[0] : domain[1]
                   return domain.charAt(0).toUpperCase() + domain.slice(1).split('.')[0] + " ";  
            };
    var url = gBrowser.selectedTab.image;
    url && saveImageURL(
        url, getSiteName(), null, false, false, null, null,
        /^data:(image\/[^;,]+)/i.test(url) ? RegExp.$1.toLowerCase() : Cc["@mozilla.org/mime;1"]
            .getService(Ci.nsIMIMEService).getTypeFromURI(Services.io.newURI(url)),
        null, PrivateBrowsingUtils.isContentWindowPrivate(content || window), document.nodePrincipal
    );
};


// Копировать иконку текущего сайта в base64 .............
function copyFaviconData() {
   var img = new Image();
   img.src = gBrowser.selectedTab.image;
   WebScreenShotonImage(img);
};


// Сохранить выделенный текст или весь текст на странице как txt файл .............
function saveSelectionToTxt() {

let browserMM = gBrowser.selectedBrowser.messageManager;
        browserMM.addMessageListener('getSelection', function listener(message) {
        var sel = message.data;
       !sel && document.getElementById("cmd_selectAll").doCommand(); 
     
   // создать название файла из заголовка страницы и текущего времени и сохранить текст ....
   var fileTitle = getTabLabel() + '  ' + aDate().replace(/:/g, ".");
    saveURL(
        "data:text/plain," + encodeURIComponent(gBrowser.currentURI.spec + "\r\n\r\n" + sel),
        fileTitle + ".txt",
        null, false, false, null, null, null,
        gBrowser.selectedBrowser.browsingContext.originAttributes.privateBrowsingId > 0,
        document.nodePrincipal
    );
   !sel && goDoCommand("cmd_selectNone"); 
 browserMM.removeMessageListener('getSelection', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelection", content.document.getSelection().toString())', false);
};


// Добавляем в контекстного меню страницы новые пункты .............
((contextMenu, el)=> {

   // в контекстного меню выделенного текста ....
   var saveItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
   saveItem.id = "content-saveItem";
   saveItem.setAttribute("label", "Сохр./добавить выбранный текст в файл");
   saveItem.setAttribute("class", "menuitem-iconic");
   saveItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAADAgBEDRIXnwxQjKQNWp6pDFWXqAxXm6gMV5moDFeaqAxXmqgMV5qoDFebqAxVlqgNW5+pCkyIogwSFqgDAgBHDQoFhyszOv8hheP+IJH7/x+L8v8fjfb/H433/x+N9v8fjfb/H432/x+N9/8fi/L/IJH7/yGF5P0kLTTvDAcDgwgICIQ8Ojf/0czA+Oji1fzh18r85NzO/OTbz/zj287849vO/OPbzvzk3M/84dfK++ji1f3Sy8D5NDIvywYGB3kKCgqFQ0A8/+XXw/v979f/9uTO//rp0f/66NH/+ujR//rn0f/66NH/+ujR//bkzv/979f/5tfD/UZBPv8KCwqEDQwMhUVDQP/f08X7+OrZ/+zf0P/v5NP/8OPT/+/j0//v4tP/8OPT/+/j0//s39D/+OrZ/+DTxfxEQj//DAwMhA8PD4VKR0T/4dXG+/rr2v/v4tH/9OXU//Ll1P/z5dT/8+XU//Pl1P/05NT/7+DR//rr2v/i1cX7SkhE/w8PD4USEhKFT0xI/+XXxfv97tr/9ePR//no1P/459T/+OfU//jn1P/459T/+OfU//Xk0f/97tr/5dfF+09MSf8SEhGFFRQUhVNQTv/j2cv7+u/g//Hm2P/169v/9Orb//Tq2//06tv/9erb//br3P/x5tf/+e/g/+PZzPtTUU7/FBQUhRgXF4VXU1D/2828+/Lk0f/q2sf/7d3K/+3dyv/t3cr/7N3K/+rayP/r28n/69vI//Ll0v/azbv7VlNP/xgXF4UfHh6FTktJ/1JOTPtZVFL/Uk5L/1FNSv9RTUr/UU1K/1JPTP9YVVD/VVJP/09NSv9WUk//UU1L+05LSf8fHh2FIR8fhVVTUP9FQkD7UlBM/6Wlj/+4uJ7/sLCX/7S0mv+xsJn/oKCQ/6+vmv+hoYv/TEtH/0NCQPtVUk//IR8fhSMhIIVcWVb/SEVF+19dVv/f3sP////e//X10v///93/2di8/1lYWP+eno//5+fG/19dV/9JRkb7W1hV/yMhIYUkJCOFXltZ/0tJSPtdW1f/0NC4/+/u1P/h4cj/8PDV/7++q/8vLC7/e3lw/9fWv/9eXVf/TElJ+15bWf8lJCKEJSQjhF9cWf9LSUf5XVtX/tbVwf/5+OL/6enV//j54v/GxrX/QD0+/42Kgv/d3cr/YF5a/k5LSvlhXlv/JSUjhCkoKIZpZWT/VVJR/WNhXP/V1cT//f3s/+3t3v/8/Or/zc2//01LSf+VlIz/4eDS/2hmYv9YVVT8aWVj/ycmJoIaGRlYSEVE1DYzM8NKSUfP0dHG9/X16P/n59v+7e3g/+jo3f/X2M3+6uve/9bWzPdOTUvNOjg3y0RBQLwPDw8lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="); 
   saveItem.onclick =()=> saveSelectionToFile();

   var editorItem = contextMenu.insertBefore(document.createXULElement("menuitem"), el);
   editorItem.id = "content-editorItem";
   editorItem.setAttribute("label", "Открыть выбранный текст в редакторе");
   editorItem.setAttribute("class", "menuitem-iconic");
   editorItem.setAttribute("image", "data:image/x-icon;base64,AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAA////AIiafwC85K4AS1ZGANLsyABKU0UAy+m+AL/lsQC14aQAn9WMAJ/QjQCsrKwAqNyXAOPz3ADe8dcA2e/QANPtyQDM68EAxei4AL7lrwC14aUArt6dAJfOhACdz4sAgICAALThpQDg8doA3vHVANjuzgDR7MYAyum+AMLmtQC7460AsuCjAK3dmgCUy4AArdedANDsxQDL6sAAz+PIAMviwwDH4L4Awd62ALvbrwC02KcArdafAKbTlgCEu3EAtNWoANPqywDa8NIA1u7NANHtxwDK6cAAw+e3ALzkrwC14aYAr9+dAKXbkQCJwnMA1+3QAKncmADd8dQAyuLBAMbgvAC6264AttmoAK/XoACn1JYAotKPAJbNgwB9tWgA4+zfANju0ADT7coAz+vFAMPntgC95K8Art6eAKndlQCa1IYAi8R3AP3+/QDD37kAvt2yALjarACz2KYArdaeAKHRjwCXzoUAj8V6AI6/ewDu8e4Awea2AMrqwQDG6LoAweazALnjqwCz4KQAr9+cAKbbkwCd2IkAlc1/AKbTlQC73K8At9qqALDXowCp1ZsApdOVAKDRjQCYzoUAksx7AIi+cwCu0aEAp9yUAMXougDC5rYAveSuALfipwCw4J8AqdyXAKLajwCd2IcAlNR9AI3FdwDU6ssAqdWZAKPSkgCe0YsAmc6GAJDLfQB/tmoA3enZAJfWhACc2IkApNuRAKTbkACj2pAAodqOAKHZjgCl25IAotmOAIzHdgAPAAAA2JIKAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOzARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcrkUA9CUMAAAAAAAAAAAAAAAAAAAAAAAAAA8AAQAAAAEAAAAAAAAAVCIMAAAAAAABAAAAuwP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAACZDSMAAQAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAABAEAABHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGRkZGRkZGRkZAAAAAAAZAQEBAQEBAQEBARkAAIeHiImKi4yNjY5+AQEZAD4mJlZXRH+AgYKDhIVdGQBzJnR1dnd4eXp7fH1+ARkAGiYnaWprbG1ub3Bxcl0ZACdeJl9gYWJjZGVmZ2gBGQAAAyZUVVZXWEVZWltcXRkAAA1KS0wfTU45T1BRUlMZAAA+P0BBK0JDREVGR0hJGQAAAzIzNDU2Nzg5Ojs8PRkAACYnKCkqKywtLi8YMDEZAAAAGhscHR4fICEiIyQlGQAAAA0ODxAREhMUFRYXGBkAAAADBAUGBwYIBgkGChkAAAAAAAACAAIAAgACAAIAAPgBAADwAAAAwAAAAIAAAACAAAAAgAAAAIAAAADAAAAAwAAAAMAAAADAAAAAwAAAAOAAAADgAAAA4AEAAPqrAAA="); 
   editorItem.onclick =()=> textToEditor();


    // устанавливаем где и при каких настройках показывать новые пункты ....
   addEventListener('popupshowing', e=> {
      if (e.target != e.currentTarget) return;
      var sel = gContextMenu.isTextSelected;
      saveItem.hidden = !sel || !cbu.getPrefs("Save.SelectionToFile");
      editorItem.hidden = !sel || !cbu.getPrefs("Save.TextToEditor"); 
      }, false, contextMenu);

   // удалять новые пункти при изминениях ....
   addDestructor(()=> {
      saveItem.remove(); editorItem.remove();
   });   
})(document.getElementById("contentAreaContextMenu"), document.getElementById("context-sep-open"));


// Сохранить или добавить выделенный текст в файл в папке загрузок, если назначена,
// иначе на Рабочий стол .............
function saveSelectionToFile() {
    var line = ".".repeat(62) + "\n";
    var hint = "Нажмите чтобы открыть файл";
    var prfx = "Выделенный текст сохранен в файл ";

    var img = self.getAttribute("image");
    var desk = Services.dirsvc.get("Desk", Ci.nsIFile);
    var as = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);

    (saveSelectionToFile = async () => {
        var time = aDate(), url = gBrowser.currentURI.displaySpec;
        var text = `${line}${getTabLabel()} - ${time}\n${url}\n\n${
            gContextMenu.contentData.selectionInfo.fullText
        }\n\n\n`;
        try {
            var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);
            var msg = prfx + "в папку " + file.leafName;
            await IOUtils.makeDirectory(file.path);
        } catch(ex) {
            file && Cu.reportError(ex);
            file = desk.clone();
            var msg = prfx + "на рабочий стол";
        }
        file.append(`Save - ${time}.txt`);
        await IOUtils.writeUTF8(file.path, text, {mode: file.exists() ? "append" : "create"});

        var name = "sstf-" + Cu.now();
        as.showAlertNotification(
            gBrowser.selectedTab.image || img, msg, hint, true, "",
            (s, t) => t == "alertclickcallback" && file.launch(), name
        );
        setTimeout(as.closeAlert, 8e3, name);
    })();
};

// Создать текстовой файл с выделенным текстом в папке загрузок, если назначена,
// иначе на Рабочий стол, и открыть в редакторе .............
function textToEditor() {
 let browserMM = gBrowser.selectedBrowser.messageManager;
 browserMM.addMessageListener('getSelect', function listener(message) {
   // создать текст для записи
    var text = convertFromUnicode("UTF-8", message.data); 
    try {var file = Services.prefs.getComplexValue("browser.download.dir", Ci.nsIFile);} catch {file = Services.dirsvc.get("Desk", Ci.nsIFile);}
   file.append("TextToEditor.txt");
   custombuttonsUtils.writeFile(file.path, text);
   file.launch(); 
          

 browserMM.removeMessageListener('getSelect', listener, true);
});
        browserMM.loadFrameScript('data:,sendAsyncMessage("getSelect", content.document.getSelection().toString())', false);
};


// Конвертировать текст в юникод .............
function convertFromUnicode(charset, str) {
     var converter = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
     converter.charset = charset;
     str = converter.ConvertFromUnicode(str);
     return str + converter.Finish();
 
};

// Получить название вкладки без не сохраняемых символов и лишних пробелов ..............
function getTabLabel() { 
   var label = gBrowser.selectedTab.label;      
   var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
   return label.substring(0, 50);
};
 ((main, parts) => this.onmousedown = e => {
    if (e.button) return;
    this.onmousedown = null;

    var df = MozXULElement.parseXULToFragment(`
        <menugroup orient="vertical">
            <menuseparator/>
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить всю страницу как PNG"
                value="all"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAAAAiAcFBa4KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwoJCa8KCQmvCgkJrwsJCaECAQE/BQMDAAAAAJUgICD4V1ZW/2FhYf5hYWH/YmFh/2BgYP9fX1//X19f/19fX/9gYGD/YmFh/2FhYf9gYGD+ZmVl/1RSUuIVFBQtCgkJy1paWv+Li4v9h4eH/oiIiP6FhYX+i4uL/pKSkv6Sk5P+kpKS/ouLi/6FhYX+iIiI/oiIiP6Hh4f7lZaW/25tbYQNDQ3OcHBw/5KSkv6Li4v/i4uL/5mZmf+EhIT/ZGRk/1tbWv9kZGT/hISE/5mZmf+Li4v/jY2N/4yMjPyWl5f/iomJjQ4NDc13d3f/m5ub/pWVlf+goKD/XFxc/ygoKP8fHyD/GBsb/yAhIv8pKSn/W1tb/6CgoP+Wlpb/lpaW/J6env+Jh4eMDg4OzX1+fv+ioqL+qqqq/1hYWP8ZGRn/Ghwb/x4dHP8mIh//FhQR/xUWF/8aGhr/WFhY/6urq/+cnJz8pKSk/4qJiYwPDg7Ng4OD/7W1tf6MjIz/Ghoa/xYYGP8uKCb/ZEAo/5xyOP++saL/RD45/xISE/8bGxv/jY2N/6+vr/ypqan/ioiIjA8PD82IiIj/xMTE/l1cXP8LDAz/JiId/1o3LP9ADgD/mGog//Dt6P/VysX/Ih4Z/wsMDf9eXl7/v7+//K6urv+KiYmMEA8PzY+Pj//Kysr+SEhH/wEDBv9MPi7/hlES/3dCAP+VZAn/tJVO/7eVXf9OQTL/AAIE/0pJSf/FxcX8tLS0/4qJiYwQEBDNm5ub/9/e3/5SUlL/AAAA/0M7Mf/aya7/ybiO/5RmEf9aIAD/cjkX/z80KP8AAAD/U1JS/9nZ2fzAwMD/i4qKjBEREc2oqKn/8O/w/oeGhv8AAAD/DAsK/6qkof/17uj/nW8l/14eCf9hPTr/ExUU/wAAAP+Hh4f/6urq/MzMzf+Mi4uMERERzbCwsv/r6uz+3Nzd/yoqKv8AAAD/ExEP/2heU/9yWjv/UD0u/xcXFv8AAAD/Kioq/93d3v/l5eb81NTV/4yLi4wSERHNuLm5/+/v8P7z8/P/xsbG/yAgIP8AAAD/AQEB/wAAAP8BAQH/AAAA/yAgIP/Gxsb/9PT0/+np6vzb29v/jIuLjBIREc2+vb7/+Pj5/uvr7P/7+/v/4ODg/3Nyc/8uLi7/Hh4d/y0sLP9zc3P/4ODg//v7+//s7O3/8/P0/OHg4f+Mi4uLFBMTyMPDw//////7+Pj4/ff29v38/Pz9/////fr6+v3u7u79+vr6/f////38/Pz99/b2/fn5+f37+/v53t7e/5KSko4GBgZ7m5yc//j4+P/w8fH/8fLy//Dw8P/u7u7/8vLy//X19f/y8vL/7u7u//Dw8P/x8vL/8vLy/uXl5f/BwcH+k5GRUAAAAAQeHR1yb25uxn59fcZ9fHzGfXx8xn18fMZ9e3vGfHt7xn17e8Z9fHzGfXx8xn18fMZ9fHzGgH9/xYmIiGVaV1cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить видимую часть как PNG"
                value="page"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAIBkAAAEAIAAMDQAAFgAAACgAAAAgAAAAMgAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29fT/2tra/8jIyP/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxcX/xcXF/8jIyP/a2tr/9vX0/+zs7P/ak0b/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/9qTRv/s7Oz/7Ozs/+J9Dv/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+/6SdmP/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/+vn4//z7+v/6+fj/4n0O/+zs7P/s7Oz/4n0O//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r//Pv6//z7+v/8+/r/aFtT//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//j39v/ifQ7/7Ozs/+zs7P/ifQ7/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P9oW1P/7+zq/+/s6v/v7Or/8O3r//Dt6//w7ev/8O3r//Dt6//w7ev/8O3r/+/s6v/w7ev/9fTy/+J9Dv/s7Oz/7Ozs/+J9Dv/49/b/+Pf2//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4/2hbU//q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/y8O//4n0O/+zs7P/s7Oz/4n0O//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/+Pf2//j39v/49/b/aFtT/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe//Dt6//ifQ7/7Ozs/+zs7P/ifQ7/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P/29fT/9vX0//b19P9oW1P/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/7uro/+J9Dv/s7Oz/7Ozs/+J9Dv/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx//Ty8f/08vH/9PLx/2hbU//x7+3/8vDv//Hv7f/x7+3/8e/t//Lw7//x7+3/8e/t//Lw7//x7+3/8vDv//Hv7f/29fT/4n0O/+zs7P/s7Oz/4n0O//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//8vDv//Lw7//y8O//aFtT/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/6igmP+ooJj/qKCY/8vGwf/ifQ7/7Ozs/+zs7P/ifQ7/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f/x7+3/8e/t//Hv7f9nWlL/aFtT/2hbU/9nWlL/Z1pS/2hbU/9oW1P/Z1pS/2daUv9oW1P/aFtT/2hbU/9nWlL/pJyX/+J9Dv/s7Oz/7Ozs/+J9Dv/w7ev/8O3r//Dt6//w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Hv7f/w7ev/8O3r//Dt6//x7+3/8O3r//Dt6//w7ev/8e/t//Dt6//w7ev/8O3r//Dt6//w7ev/4n0O/+zs7P/s7Oz/4n0O/+/s6v/v7Or/7uro/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/v7Or/7+zq/+/s6v/u6uj/7+zq/+/s6v/ifQ7/7Ozs/+zs7P/ifQ7/7uro/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7uro/+zo5v/u6uj/7uro/+7q6P/s6Ob/7uro/+7q6P/u6uj/7Ojm/+7q6P/u6uj/7Ojm/+J9Dv/s7Oz/7Ozs/+J9Dv/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/7Ojm/+zo5v/s6Ob/4n0O/+zs7P/s7Oz/4n0O/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/q5uT/6ubk/+rm5P/ifQ7/7Ozs/+zs7P/ifQ7/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+nl4v/p5eL/6eXi/+J9Dv/s7Oz/7Ozs/+J9Dv/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/5uHe/+bh3v/m4d7/6eXi/+bh3v/m4d7/5uHe/+nl4v/m4d7/5uHe/+bh3v/p5eL/4n0O/+zs7P/s7Oz/4n0O/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/m4d7/5uHe/+bh3v/ifQ7/7Ozs/+zs7P/ifQ7/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+bh3v/k39z/5uHe/+Tf3P/m4d7/5N/c/+J9Dv/s7Oz/7Ozs/+J9Dv/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/i3Nn/4tzZ/+Lc2f/k39z/4n0O/+zs7P/s7Oz/4n0O/+Lc2f/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/h29j/4dvY/+Hb2P/ifQ7/7Ozs/+zs7P/ifQ7/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+DZ1v/g2db/4NnW/+J9Dv/s7Oz/9fTy/+J9Dv/8+/r/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/+vn4//r5+P/6+fj/4n0O//X08v/8+/r/6KFU/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ifQ7/4n0O/+J9Dv/ooVT//Pv6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить выбранный элемент как PNG"
                value="click"/>
    
            <menuitem class="menuitem-iconic"
                image="data:image/x-icon;base64,AAABAAEAEREAAAEAIADwBAAAFgAAACgAAAARAAAAIgAAAAEAIAAAAAAAyAQAAAAAAAAAAAAAAAAAAAAAAADDn2Hfz5pE/8eVQP7IlkH/yJZB/8iWQf/IlUH/yJVA/8iVQP/IlED/yJQ//8iUP//IlD//yJM+/8iTPv/Hkj3/nI1w//bDbP//8OH//+zW///s1///69b//+rV///p1P//59L//+XQ///izf//38n//9vG///ZxP//1b///dG////Prf/KlkX/88N4/v37///99Pj//fT6//vy9v/68fT/+u/y//rt8P/66u3/+ufq//rl6P/64eT/+93h//3a3//71d7//9LK/86XR//0xHb//vv////18///9fT///f5///4////9f7///P8///v+f//7Pb//+nz///m8f//4eb//9vZ//3Y2v//1Mb/zphH//TGd//+/////Pj1///7///Q58r/m9aV/6TZnv+i15r/otWY/6LTlv+j0pb/mc6M/9DXuf//3+P//Nnc///Wyf/OmUf/9MZ3//7////8+/j//////53WnP+Y5pn/rvGv/6PvpP+e7p//me6b/5nvm/95533/mM+L///j7f/629z//9jL/86ZR//0xnf//v////z9+v//////qtup/8Xzxf/a/tn/z/vO/8n7yf/D+sL/xPvD/6Hzo/+j05b//+Tu//re3///2cz/zplI//XGeP/+/////P36//////+n26f/uvC6/9T71P/K+Mr/xvjG/8D3wP+/+L//nfCf/6LTlf//5u//+t/g///cz//OmUj/9MZ3//7////8/fr//////6rcqv/G9MX/3//f/9n92f/V/NX/0PzQ/9H+0P+s9a7/pdSY///o8f/64OL//9zP/86aSP/0xnf//v////z9+f//////ndid/5TjlP+v7q//qeyp/6jsqf+k7KX/p+6n/4Tlh/+Z0Y7//+r0//rh4v//3tH/zppI//TGd//+/////v77///////Y8Nj/p9+n/6/jr/+t4a3/rd2p/67bpv+u2ab/p9Wc/9jgx///6Oz//OPl///e0f/Omkj/9MV1//7//////fr///78///+/f///////////////////P////j////0+///8fn//+vu///m4v/94+P//97P/86ZSP/zx3v//v/////+/f///////f////v////7////+/////v+///7+///+/f///vz/P/98Pr//+33//3p9///5OL/zppL//a1Sv/0xoL/9cR7//XEfP/1xHz/9cR8//XEfP/1xH3/9cR8//XCev/1wXr/9b94//W9d//1u3X/87l0//y6bP/Llj7/+pMA/vWBAP/1gwD/9YMA//WDAP/1gwD/9YMA//WDAP/1gwD/9YQA//WEAP/1hAD/9YQA//WEAP/zhAH//okA/8qLIv3xpzP/4ptV/+OdU//jnVP/451T/+OdU//jnVP/451T/+OdU//jnVL/451S/+OdUv/jnVL/451S/+GdVf/qnUf/2aRJ/9q0c9/8yn7/98V5/vjGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6//jGev/4xnr/+MZ6/vrIe/+jj2y4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
                label="Сохранить выбранную область как PNG"
                value="clipping"/>
        </menugroup>
    `);
    var menugroup = df.firstChild;
    menugroup.setAttribute("context", "");
    menugroup.setAttribute("oncommand", "handleCommand(event);");
    menugroup.handleCommand = e => {
        var name = _id + ":DataURLReady";
        main = main.replace("%MESSAGE_NAME%", name);

        var urls = {}, configurable = true, enumerable = true;
        Object.entries(parts).forEach(([key, part]) => Object.defineProperty(urls, key, {
            configurable, enumerable, get() {
                var value = `data:;charset=utf-8,({${
                    encodeURIComponent(main + part)
                }%0A}).init("${key}")`;
                Object.defineProperty(urls, key, {configurable, enumerable, value});
                return value;
        }}));
        var getTabLabel = () => {
            var label = gBrowser.selectedTab.label;      
            var label = label.replace(/[:+.\\\/<>?*|"]+/g, " ").replace(/\s\s+/g, " ");
            return label.substring(0, 50);
        }
        var listener = msg => {
            var fp = makeFilePicker();
            fp.init(window, "Сохранить как…", fp.modeSave);
            fp.appendFilter("", "*.png");
            fp.defaultString = getTabLabel() + ".png";
            fp.open(res => {
                if (res == fp.returnCancel || !fp.file) return;
                var wbp = makeWebBrowserPersist(), args = [
                    Services.io.newURI(msg.data), document.nodePrincipal,
                    null, null, null, null, fp.file, null
                ];
                //wbp.saveURI.length == 9 && splice(args);
                var {length} = wbp.saveURI;
                length >= 9 && splice(args);
                length == 10 && args.splice(3, 0, null);
                wbp.saveURI(...args);
            });
        }
        var splice = arr => {
            var fox74 = parseInt(Services.appinfo.platformVersion) >= 74;
            var args = [fox74 ? 7 : 2, 0, fox74 ? Ci.nsIContentPolicy.TYPE_IMAGE : null];
            (splice = arr => arr.splice(...args))(arr);
        }
        messageManager.addMessageListener(name, listener);
        addDestructor(() => messageManager.removeMessageListener(name, listener));

        (menugroup.handleCommand = e => gBrowser.selectedBrowser.messageManager
            .loadFrameScript(urls[e.target.value], false)
        )(e);
    }
    menuPopup.querySelector('menuitem[label*="ярлык"]').after(df);
})(`
    init(cmd) {
        cmd.startsWith("c")
            ? this[cmd].init(this[cmd].parent = this)
            : this[cmd]();
    },
    capture(win, x, y, width, height) {
        var canvas = win.document.createElementNS("${xhtmlns}", "canvas");
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        var tryDraw = ind => {
            try {ctx.drawWindow(win, x, y, canvas.width, canvas.height, "white")}
            catch(ex) {canvas.height = ind * canvas.width; tryDraw(--ind);}
        }
        tryDraw(17);
        sendAsyncMessage("%MESSAGE_NAME%", canvas.toDataURL("image/png"));
    },
    `, {

    all: `all() {
        var win = content;
        this.capture(win, 0, 0, win.innerWidth + win.scrollMaxX, win.innerHeight + win.scrollMaxY);
    }`,
    page: `page() {
        var win = content, doc = win.document, body = doc.body, html = doc.documentElement;
        var scrX = (body.scrollLeft || html.scrollLeft) - html.clientLeft;
        var scrY = (body.scrollTop || html.scrollTop) - html.clientTop;
        this.capture(win, scrX, scrY, win.innerWidth, win.innerHeight);
    }`,
    clipping: `clipping: {
        handleEvent(e) {
            if (e.button) return false;
            e.preventDefault();
            e.stopPropagation();
            switch(e.type) {
                case "mousedown":
                    this.downX = e.pageX;
                    this.downY = e.pageY;
                    this.bs.left = this.downX + "px";
                    this.bs.top = this.downY + "px";
                    this.body.appendChild(this.box);
                    this.flag = true;
                    break;
                case "mousemove":
                    if (!this.flag) return;
                    this.moveX = e.pageX;
                    this.moveY = e.pageY;
                    if (this.downX > this.moveX) this.bs.left = this.moveX + "px";
                    if (this.downY > this.moveY) this.bs.top  = this.moveY + "px";
                    this.bs.width = Math.abs(this.moveX - this.downX) + "px";
                    this.bs.height = Math.abs(this.moveY - this.downY) + "px";
                    break;
                case "mouseup":
                    this.uninit();
                    break;
            }
        },
        init() {
            var win = {};
            Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager)
                .getFocusedElementForWindow(content, true, win);
            this.win = win.value;

            this.doc = this.win.document;
            this.body = this.doc.body;
            if (!HTMLBodyElement.isInstance(this.body)) {
                Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService)
                    .showAlertNotification("${self.image}", ${JSON.stringify(self.label)}, "Не удается захватить!");
                return false;
            }
            this.flag = null;
            this.box = this.doc.createElement("div");
            this.bs = this.box.style;
            this.bs.border = "#0f0 dashed 2px";
            this.bs.position = "absolute";
            this.bs.zIndex = "2147483647";
            this.defaultCursor = this.win.getComputedStyle(this.body, "").cursor;
            this.body.style.cursor = "crosshair";
            ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.addEventListener(type, this, true));
        },
        uninit() {
            var pos = [this.win, parseInt(this.bs.left), parseInt(this.bs.top), parseInt(this.bs.width), parseInt(this.bs.height)];
            this.body.style.cursor = this.defaultCursor;
            this.body.removeChild(this.box);
            this.parent.capture.apply(this, pos);
            ["click", "mouseup", "mousemove", "mousedown"].forEach(type=> this.doc.removeEventListener(type, this, true));
        }
    }`,
    click: `click: {
        getPosition() {
            var html = this.doc.documentElement;
            var body = this.doc.body;
            var rect = this.target.getBoundingClientRect();
            return [
                this.win,
                Math.round(rect.left) + (body.scrollLeft || html.scrollLeft) - html.clientLeft,
                Math.round(rect.top) + (body.scrollTop || html.scrollTop) - html.clientTop,
                parseInt(rect.width),
                parseInt(rect.height)
            ];
        },
        highlight() {
            this.orgStyle = this.target.hasAttribute("style") ? this.target.style.cssText : false;
            this.target.style.cssText += "outline: red 2px solid; outline-offset: 2px; -moz-outline-radius: 2px;";
        },
        lowlight() {
            if (this.orgStyle) this.target.style.cssText = this.orgStyle;
            else this.target.removeAttribute("style");
        },
        handleEvent(e) {
            switch(e.type){
                case "click":
                    if (e.button) return;
                    e.preventDefault();
                    e.stopPropagation();
                    this.lowlight();
                    this.parent.capture.apply(this, this.getPosition());
                    this.uninit();
                    break;
                case "mouseover":
                    if (this.target) this.lowlight();
                    this.target = e.target;
                    this.highlight();
                    break;
            }
        },
        init() {
            this.win = content;
            this.doc = content.document;
            ["click", "mouseover"].forEach(type=> this.doc.addEventListener(type, this, true));
        },
        uninit() {
            this.target = false;
            ["click", "mouseover"].forEach(type=> this.doc.removeEventListener(type, this, true));
        }
    }`
});

Dumby Хотя... еще бы папку для сохранения иконок и ярлыков сайтов привязать к папке загрузок браузера, иначе - рабочий стол. И вообще там непорядок - нажимаешь сохранить ярлык, он открывает окно и выводит уведомление, что типа уже сохранил, но он еще ничего не сохранял.

Отредактировано _zt (18-05-2022 14:32:52)

Отсутствует

 

№32419-05-2022 00:41:41

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

_zt
Спасибо.

Отсутствует

 

№32521-05-2022 11:11:09

voqabuhe
Участник
 
Группа: Members
Зарегистрирован: 06-12-2011
Сообщений: 3231
UA: Firefox 100.0

Re: UCF - ваши кнопки, темы, дополнения, скрипты…

Dumby
Кнопка Save не сохраняет полностью длинные страницы на этом форуме, если выбрать "Сохранить всю страницу как PNG", низ обрезается. Если возможно, поправь плиз.

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]