diff --git a/Extension/Background.js b/Extension/Background.js index 12c3549..9b3930b 100644 --- a/Extension/Background.js +++ b/Extension/Background.js @@ -7,10 +7,8 @@ const loc_dlWithTags = "Download with tags", loc_getTagsString = "Get tags string", loc_specifyTemplate = "Specify custom filename template...", loc_highlightTags = "Highlight fetched tags?", + loc_clampUnicode = "Allow Unicode >05FF in tags?", loc_supressSaveAs = "Supress 'Save As' dialog?", - loc_thumnailWarning = "You have requested to save a thumbnail. If you want a full-sized picture instead, either:\n"+ - "- click on it to enlarge before saving\n"+ - "- use the 'Save link as...' context menu option.", loc_pixivOnChrome = "PIXIV refuses to serve pictures without the correct referrer. Currently there is no way around it."+ "Tags window is invoked.\n Copy the tags and use the default 'Save As...' dialogue."; @@ -29,7 +27,8 @@ const validComboSets = [ // valid combinations of tags origin, image hoster, ]; var invokeSaveAs = true, - useDecoration = false; + useDecoration = false, + clampUnicode = false; var firefoxEnviroment = false, useIcons = false; var fileNameTemplate = "{handle}@{OR} {ID} {name} {caption} {tags}"; @@ -44,7 +43,7 @@ function validateAnswer(tagsOrigin, hosterUrl, requesterUrl) { return false; }; -//TODO: maybe add DB & PIXIV expanding to maximum resolution availible? +//TODO: maybe add DB expanding to maximum resolution availible? function processURL( /* object */ image, tabId) { /* Cleans the URL of image object, shifts some information to name if needed */ let url = image.url, @@ -71,15 +70,14 @@ function processURL( /* object */ image, tabId) { if (image.origin === "PX") { // ! PIXIV — special case: additional tag 'page_' (since pixiv_xxxx can hold many images) let PXpage = filename.substring(filename.indexOf('_p') + 2, filename.indexOf('.')); - let PXthumb = ""; - if (PXpage.indexOf('master') > -1) { - PXpage = PXpage.substring(0, PXpage.indexOf('_master')); - PXthumb = "-THUMBNAIL!-"; // if user wants to save a rescaled thumbnail, add a tag - sir.displayWarning(tabId, loc_thumnailWarning); + if (PXpage.indexOf('master') > -1) { // if a re-mastered image is selected, try to download the best availible one + PXpage = PXpage.replace(/\_master[\d]+/g,''); // url ex.: https://i.pximg.net/img-master/img/1970/01/01/11/59/59/12345678_p0_master1200.jpg + url = url.replace(/\/img-master\//g,'/img-original/'); // first part of the url + url = url.replace(/_master[\d]+\./g,'.'); // the file name }; - image.tags = image.tags + " page_" + PXpage + PXthumb; + image.tags = image.tags.replace(/(pixiv_[\d]+)/g,'$1 page_'+PXpage); }; image.url = url; @@ -90,6 +88,14 @@ function generateFilename(image) { if (image.ext.length > 5) image.ext = "maybe.jpeg"; // make sure that extention did not go out of bounds if (image.tags === "") image.tags = "tagme"; // make sure the name is not left blank + if (clampUnicode) { // if the Unicode limiter is set, clean the characters higher than Hebrew + let author_protection = ""; // but try to avoid the author tag during the processing + let handleEstimate = image.tags.match(/[^\s]*@[A-Za-z]{2}\s/g)[0]; // handle@XX format with trailing space + if (handleEstimate) author_protection = handleEstimate; + image.tags = image.tags.substring(handleEstimate.length); + image.tags = author_protection + " " + image.tags.replace(/[^\u0000-\u05ff]+/g,''); + } + image.tags = image.tags.replace(/[,\\/:*?"<>|\t\n\v\f\r]/g, '') // make sure the name in general doesn't contain any illegal characters .replace(/\s{2,}/g, ' ') // collapse multiple spaces .trim(); @@ -102,6 +108,7 @@ function generateFilename(image) { image.filename = image.tags + "." + image.ext; }; +// singleton var sir = { makeMenuItem: function (id, item, icon, clickable, useIcon) { /* adds an individual item to the context menu and gives it the id passed into the function */ @@ -133,13 +140,14 @@ var sir = { chrome.contextMenus.create({type: "separator", id:"separator2", contexts: ["image"]}); chrome.contextMenus.create({type: "checkbox", id: "useDecoration", title: loc_highlightTags, checked: useDecoration, contexts: ["image"]}); + chrome.contextMenus.create({type: "checkbox", id: "clampUnicode", title: loc_clampUnicode, checked: !clampUnicode, contexts: ["image"]}); chrome.contextMenus.create({type: "checkbox", id: "saveSilently", title: loc_supressSaveAs, checked: !invokeSaveAs, contexts: ["image"]}); }, makeMenu: function () { /* gets browser info and passes it to makeMenuItems to determine if things like icons are supported */ if (firefoxEnviroment) { - var gettingBrowserInfo = browser.runtime.getBrowserInfo(); + let gettingBrowserInfo = browser.runtime.getBrowserInfo(); gettingBrowserInfo.then(sir.makeMenuItems); } else { sir.makeMenuItems(); @@ -341,6 +349,9 @@ chrome.contextMenus.onClicked.addListener(function (info, tab) { // ! info is an useDecoration = !useDecoration; sir.setupConnection(tab.id, "Highlight toggled."); break; + case 'clampUnicode': + clampUnicode = !clampUnicode; + break; case 'tmpl': sir.promptTemplate(tab.id, fileNameTemplate); break; diff --git a/Extension/Parsers/AS.js b/Extension/Parsers/AS.js index 61455b9..585b709 100644 --- a/Extension/Parsers/AS.js +++ b/Extension/Parsers/AS.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "AS"; +var ID_prefix = "artstation_"; var windowDisplacement = 90; //For somewhat more robust anchoring instead of pre-calculated 35 one can use @@ -28,5 +29,5 @@ function getTags() { function getPictureID() { let pic_ID = document.URL.substring(AS_ID_DISPLACEMENT).replace(/[\W]/g, ''); //Artstation IDs contain A-z 0-9 - return (pic_ID)?"artstation_"+pic_ID:""; + return (pic_ID)?ID_prefix+pic_ID:""; } \ No newline at end of file diff --git a/Extension/Parsers/DA.js b/Extension/Parsers/DA.js index 7458fd4..dcedd2b 100644 --- a/Extension/Parsers/DA.js +++ b/Extension/Parsers/DA.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "DA"; +var ID_prefix = "deviantart_"; var windowDisplacement = 0; const styleTargets = "div.dev-title-container a.discoverytag, a[href*='/tag/'], aside div h1.h3"; @@ -27,5 +28,5 @@ function getTags() { function getPictureID() { let pic_ID = document.URL.substring(document.URL.lastIndexOf('-')).replace(/[\D]/g, ''); //Deviantart IDs are numbers after last dash - return (pic_ID)?"deviantart_"+pic_ID:""; + return (pic_ID)?ID_prefix+pic_ID:""; } \ No newline at end of file diff --git a/Extension/Parsers/DB.js b/Extension/Parsers/DB.js index 542f342..c09446c 100644 --- a/Extension/Parsers/DB.js +++ b/Extension/Parsers/DB.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "DB"; +var ID_prefix = "danbooru_"; var windowDisplacement = 0; const styleTargets = "aside section a.search-tag"; @@ -27,7 +28,7 @@ function getPictureID() { let lefter = pick("post-information").innerText.trim(); let id_string = lefter.match(/Id: [\d]+$/gim)[0]; if (id_string) { - return "danbooru_" + id_string.substring(4); //add the danboroo_ ID to the tags array + return ID_prefix + id_string.substring(4); //add the danboroo_ ID to the tags array } return ""; } \ No newline at end of file diff --git a/Extension/Parsers/DF.js b/Extension/Parsers/DF.js index 0fee7b1..26422a2 100644 --- a/Extension/Parsers/DF.js +++ b/Extension/Parsers/DF.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "DF"; +var ID_prefix = "drawfriends_"; var windowDisplacement = 0; const styleTargets = "div#tag_list li a"; @@ -31,7 +32,7 @@ function getPictureID() { var lefter = safeQuery('div [id="tag_list"]').innerText.trim(); let id_string = lefter.match(/Id: [\d]+$/gim)[0]; if (id_string) { - return "drawfriends_" + id_string.substring(4); //add the drawfriends_ ID to the tags array + return ID_prefix + id_string.substring(4); //add the drawfriends_ ID to the tags array } return ""; } \ No newline at end of file diff --git a/Extension/Parsers/HF.js b/Extension/Parsers/HF.js index 89a4512..eeb4384 100644 --- a/Extension/Parsers/HF.js +++ b/Extension/Parsers/HF.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "HF"; +var ID_prefix = "hfoundry_"; var windowDisplacement = 0; const styleTargets = "div.boxbody td a[rel='tag']"; @@ -30,5 +31,5 @@ function getTags() { function getPictureID() { let URLwithNoName = document.URL.substring(0,document.URL.lastIndexOf('/')); let pic_ID = URLwithNoName.substring(URLwithNoName.lastIndexOf('/')).replace(/[\D]/g, ''); - return (pic_ID)?"hfoundry_"+pic_ID:""; + return (pic_ID)?ID_prefix+pic_ID:""; } \ No newline at end of file diff --git a/Extension/Parsers/IG.js b/Extension/Parsers/IG.js index c39c122..01ab46a 100644 --- a/Extension/Parsers/IG.js +++ b/Extension/Parsers/IG.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "IG"; +var ID_prefix = "instagram_"; var windowDisplacement = 0; //For somewhat more robust anchoring instead of pre-calculated 28 one can use @@ -36,7 +37,7 @@ function getTags() { function getPictureID() { if (document.URL.indexOf('/p/') === -1) return; let pic_ID = document.URL.substring(IG_ID_DISPLACEMENT).replace(/[\W]/g, ''); //Instagram IDs contain A-z 0-9 and underscore - return (pic_ID)?"instagram_"+pic_ID:""; + return (pic_ID)?ID_prefix+pic_ID:""; } // ! Instagram-specific Image|Video unfvckery diff --git a/Extension/Parsers/MW.js b/Extension/Parsers/MW.js index 61152c7..a9088a9 100644 --- a/Extension/Parsers/MW.js +++ b/Extension/Parsers/MW.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "MW"; +var ID_prefix = "medicalwhiskey_"; var windowDisplacement = 0; //For somewhat more robust anchoring instead of pre-calculated 29 one can use @@ -30,5 +31,5 @@ function getTags() { function getPictureID() { let pic_ID = document.URL.substring(MW_ID_DISPLACEMENT).replace(/[\D]/g, ''); - return (pic_ID)?"medicalwhiskey_"+pic_ID:""; + return (pic_ID)?ID_prefix+pic_ID:""; } \ No newline at end of file diff --git a/Extension/Parsers/PX.js b/Extension/Parsers/PX.js index f6e9c21..c28bd61 100644 --- a/Extension/Parsers/PX.js +++ b/Extension/Parsers/PX.js @@ -1,11 +1,12 @@ "use strict"; var tagsOrigin = "PX"; +var ID_prefix = "pixiv_"; var windowDisplacement = 0; -const styleTargets = "aside section h2 div div a, figcaption div h1, figcaption div footer ul li"; +const styleTargets = "aside section h2 div div a div, figcaption div h1, figcaption div footer ul li"; function getAuthorHandle() { - return safeQuery('aside section h2 div div a').innerText.replace(/[ ,\\/:?<>\t\n\v\f\r]/g, '-'); + return safeQuery('aside section h2 div div a div').innerText.replace(/[ ,\\/:?<>\t\n\v\f\r]/g, '-'); }; function getAuthorName() { @@ -19,7 +20,7 @@ function getPictureName() { // with enlish translation following, no hash function getTags() { - var tagString = " "; + let tagString = " "; for (let tag of safeQueryA('figcaption div footer ul li a')) { tagString += tag.innerText.replace(/[ ]/g, '_') + " "; }; @@ -28,5 +29,25 @@ function getTags() { function getPictureID() { let pic_ID = document.URL.substring(document.URL.lastIndexOf('/')).replace(/[\D]/g, ''); - return (pic_ID)?"pixiv_"+pic_ID:""; -} \ No newline at end of file + return (pic_ID)?ID_prefix+pic_ID:""; +} + +function promptToNavigate() { + let url = document.URL; + if ( (url.indexOf('img-master') > -1) && + (url.indexOf('_master') > -1 ) && + confirm("Open this image in original quality?") ) { + + let ID = url.substring(url.lastIndexOf('/') + 1, url.indexOf('_')); + if (confirm("This won't work unless you had already requested the image from the original post page:\nhttps://www.pixiv.net/artworks/" + ID + "\nTry anyway? ('No' to open the post link)")) { + url = url.replace(/\/img-master\//g,'/img-original/'); // first part of the url + url = url.replace(/_master[\d]+\./g,'.'); // the file name + + window.location = url; // adds to the History, allowing to roll back + } else { + window.location = "https://www.pixiv.net/artworks/" + ID; // the same as above + } + } +} + +setTimeout(promptToNavigate, 200); \ No newline at end of file diff --git a/Extension/Parsers/TU.js b/Extension/Parsers/TU.js index bd03bad..888d8d3 100644 --- a/Extension/Parsers/TU.js +++ b/Extension/Parsers/TU.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "TU"; +var ID_prefix = ""; var windowDisplacement = 0; const styleTargets = "a[href*='/tagged/'], header div figcaption, header div h1 a"; diff --git a/Extension/Parsers/TW.js b/Extension/Parsers/TW.js index 513d645..1ffa891 100644 --- a/Extension/Parsers/TW.js +++ b/Extension/Parsers/TW.js @@ -1,5 +1,6 @@ "use strict"; const tagsOrigin = "TW"; +var ID_prefix = ""; var windowDisplacement = 0; const styleTargets = "a[href*='/hashtag/']"; @@ -33,7 +34,7 @@ function getPictureID() { function promptToNavigate() { if ( (document.URL.indexOf('twimg') > -1) && (document.URL.indexOf('orig') < 1 ) && (document.URL.indexOf('4096x4096') < 1) && confirm("Open this image in original quality?") ) { if (document.URL.indexOf('?') > -1) { - window.location.replace(document.URL.replace(/(&?name=[\w\d]+&?)/g,'') + "&name=orig"); + window.location.replace(document.URL.replace(/(&?name=[\w\d]+&?)/g,'') + "&name=orig"); // won't add the changed location to the browser history as the new object } else { window.location.replace(document.URL.substring(0, (document.URL.lastIndexOf(':')>10)?document.URL.lastIndexOf(':'):document.URL.length) + ":orig"); // 10 because there is always : in http:// }; diff --git a/Extension/Parsers/VA.js b/Extension/Parsers/VA.js index fb05f2e..44cbe00 100644 --- a/Extension/Parsers/VA.js +++ b/Extension/Parsers/VA.js @@ -1,5 +1,6 @@ "use strict"; var tagsOrigin = "VA"; +var ID_prefix = "vidyart_"; var windowDisplacement = 0; const styleTargets = "div#tag_list li a"; @@ -31,7 +32,7 @@ function getPictureID() { var lefter = safeQuery('div [id="tag_list"]').innerText.trim(); let id_string = lefter.match(/Id: [\d]+$/gim)[0]; if (id_string) { - return "vidyart_" + id_string.substring(4); //add the vidyart_ID to the tags array + return ID_prefix + id_string.substring(4); //add the vidyart_ID to the tags array } return ""; } \ No newline at end of file diff --git a/Extension/manifest.json b/Extension/manifest.json index 3d0734b..57a66ee 100644 --- a/Extension/manifest.json +++ b/Extension/manifest.json @@ -7,7 +7,7 @@ "48": "SIR_48x48.png", "16": "SIR_16x16.png" }, - "version": "1.6.0", + "version": "1.7.0", "manifest_version": 2, "permissions": ["downloads", "contextMenus"], "content_scripts": [ diff --git a/README.md b/README.md index fe35851..320d5a8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ * Option to bypass 'Save As…' dialog * Fetched Tags String preview & copy _(with hotkeys!)_ * Pixiv thumbnail warning on save request -* Twitter max quality promoter & navigation prompt on 'View Image…' +* Twitter, Pixiv max quality promoter & navigation prompt on 'View Image…' * Automatic handling of long names & multiple artists collaboration ## Description ## @@ -57,7 +57,7 @@ If the active tab has this script responding, context menu items would be enable By user request (`"SIR Image Renamer"` → `"Download with tags"`), content scripts parse the page and pass the info to renaming procedure. This procedure suggests the file downloader a name to save the file by. "Save As" dialogue is invoked depending on whether the `Suppress 'Save As'` option was selected. By default, the image is saved in your browser's default download directory. -*In addition, it is possible to manually get the list of tags by pressing `Ctrl+Shift+1` or selecting `"Get tags string"` in the context menu.* +*In addition, it is possible to manually get the list of parsed tags by pressing `Ctrl+Shift+1` or selecting `"Get tags string"` in the context menu.* One can see what info is discovered by **SIR** (`"SIR Image Renamer"` → `"Highlight fetched tags?"`): ![Example of tag highlighting](./Img/tag_highlighting.png) @@ -65,9 +65,7 @@ One can see what info is discovered by **SIR** (`"SIR Image Renamer"` → `"High For currently shown image or video on *Instagram*, the extension first promotes it to maximum available quality and then removes (right-click preventing) obstructions. This enables proper behavior not only for **SIR**, but for all the regular context menu options too (including third-party extensions depending on context menus, ex. `Image Search Options`!). When opening single images from `twimg.com` domain (*Twitter* hosting server), **SIR** will prompt you for navigation to their full-sized original counterparts. -Additionally, if you're on *Pixiv* and are trying to save a thumbnail, **SIR** will halt you (but won't restrict your ability to proceed): - -![Example alert](./Img/thumbnail_warning.png) +Additionally, on *Pixiv* invoking a menu from a thumbnail, queues the download of the full-resolution picture. ## Installation ## diff --git a/package.json b/package.json index 3baac6a..2bd8141 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sir_image_renamer", - "version": "1.6.0", + "version": "1.7.0", "description": "SIR is an Image Renamer.\nProvides meaningful image names when saving on Pixiv, Deviantart, Artstation, etc.", "scripts": { "test": "web-ext lint --source-dir=./Extension/", diff --git a/test.js b/test.js index f4c05a2..6ad339a 100644 --- a/test.js +++ b/test.js @@ -1,5 +1,5 @@ // TODO: Implement proper testing suite -var Links_to_test = [ +let Links_to_test = [ "https://www.artstation.com/artwork/zARRXD", // ID is alphanumeric "https://deviantart.com/view/787225844", // Original was "https://www.deviantart.com/chrissiezullo/art/Nejire-Hadou-787225844" "https://danbooru.donmai.us/posts/3887268", // Special case: tags string > 230 characters limit @@ -7,6 +7,7 @@ var Links_to_test = [ "https://www.hentai-foundry.com/pictures/774805", // Original was "https://www.hentai-foundry.com/pictures/user/BBC-Chan/774805/Elyzabeth-1" "http://medicalwhiskey.com/?p=12513", // "https://www.pixiv.net/artworks/79196939", // Special case: thumbnail detection + "https://www.pixiv.net/request", // Special case: creators accepting requests & qualifier handling "https://blurryken.tumblr.com/post/185528821532/do-you-want-to-share-a-bubble-tea-with-me", // NO IDS KNOWN - ID tracking not implemented "https://twitter.com/RGVaerialphotos/status/1280334509863579648", // NO IDS KNOWN - ID tracking not implemented Special case: image must be ORIG "https://vidyart.booru.org/index.php?page=post&s=view&id=375444", // Special cases: >6 artists; very long tags string