Skip to content

Instantly share code, notes, and snippets.

@DarrenSem
Last active March 8, 2025 18:14
Show Gist options
  • Save DarrenSem/444cc1c0539226a4902e7f265f23820f to your computer and use it in GitHub Desktop.
Save DarrenSem/444cc1c0539226a4902e7f265f23820f to your computer and use it in GitHub Desktop.
console.save.js + DOWNLOAD contents as MarkDown.js -- download your JavaScript objects from your web browser's F12 Dev Tools console! (also Bookmarklet click defaults to saving prompt text data or body.innerText as `DL-[date].md`)
// DLasMD - DOWNLOAD contents as MarkDown.js
// old as of 15Jan2025; start using DLasMD-console.save.js
// 27Dec2024 1053am NEW promptData rules (Blank or Empty or =FILENAME.EXT defaults to document.body.innerText)
// 477 char javascript:void function(){let a=document,b=(b,c=`DL-${+new Date}.md`,d="octet-stream")=>{let e=URL.createObjectURL(new Blob([b],{type:d}));Object.assign(a.createElement("a"),{href:e,download:c}).click(),URL.revokeObjectURL(e)},c=prompt("Enter data to download...\n\n(Blank or Empty or =FILENAME.EXT defaults to document.body.innerText)")?.trim();if(null!=c){let d=c.startsWith("=")&&c.slice(1);b(c.length&&!d?c:a.body.innerText,d?`${d}${d.includes(".")?"":".md"}`:void 0)}}();
let doc=document;
let saveDataAsFilenameMime = (
data,
filename=`DL-${+new Date}.md`,
mimeType = "octet-stream"
) => {
let href = URL.createObjectURL(
new Blob(
[data],
{ type: mimeType }
)
);
Object.assign(
doc.createElement("a"),
{ href, download: filename }
).click();
URL.revokeObjectURL(href);
};
let promptData = prompt(
"Enter data to download...\n\n(Blank or Empty or =FILENAME.EXT defaults to document.body.innerText)"
)?.trim();
if(promptData != null) {
let filename = promptData.startsWith("=") && promptData.slice(1);
saveDataAsFilenameMime(
promptData.length && !filename
? promptData
: doc.body.innerText
, filename ? `${filename}${filename.includes(".") ? "" : ".md"}` : undefined
)
};
// DLasMD-console.save.js -- download your JavaScript objects from your web browser's F12 Dev Tools console! (also Bookmarklet click defaults to saving prompt text data or body.innerText as `DL-[date].md`)
// javascript:void function(){let a=document,b=Object,c=b._,d="application/octet-stream",e=console,f=()=>a.body.innerText,g=a=>a,h=(c,e=`DL-${+new Date}.md`,f)=>{let g=URL,h=g.createObjectURL(c=new Blob([c],{type:f||c?.type||d}));b.assign(a.createElement("a"),{href:h},!0===e?{target:"_blank"}:{download:e||""}).click(),g.revokeObjectURL(h)};(e.save||=(a,b,e)=>{if(a==c){let d=prompt("Enter data to download...\n\n(Whitespace or =FILENAME.EXT defaults to document.body.innerText)")?.trim();if(d==c)return c;/^=./.test(d)&&(b=d.slice(1),d=0);a=d.length?d:f(),b=!0===b?b:b?`${b}${b.includes(".")?"":".md"}`:c}let g="object"==typeof a;g&&(a=JSON.stringify(a,0,4));h(a,b||`DL-${+new Date}.${g?".json.txt":"md"}`,e||(g?"application/json":d))})()}();
// ^ Bookmarklet (741 char) -- drag-and-drop add this to your web browser's Favorites
// (15Jan2025; stop using old "DLasMD - DOWNLOAD contents as MarkDown.js")
// inspired by the simple idea @ https://coderwall.com/p/prhwzg/add-console-save-to-chrome https://archive.is/cWiF6
// this GIST url: https://gist.github.com/DarrenSem/444cc1c0539226a4902e7f265f23820f
@DarrenSem
Copy link
Author

// BTW, you can learn from this (or any!) minified code by pasting it into https://beautifier.io/
// and then opening the prettier version in Visual Studio Code, using F2 to rename the shortened variable names...



javascript: void
function() {
    let a = Object,
        b = document,
        c = (c, d, e) => {
            let f = URL,
                g = f.createObjectURL(c = new Blob([c], {
                    type: e || c?.type || "application/octet-stream"
                }));
            a.assign(b.createElement("a"), {
                href: g
            }, !0 === d ? {
                target: "_blank"
            } : {
                download: d || ""
            }).click(), f.revokeObjectURL(g)
        },
        d = a => a,
        e = () => {
            if (b.onselectstart && b.onselectstart !== d) return b.onselectstart = d, alert("Text selecting was disabled!\n\nTry again, it is now enabled...");
            let a = b.getSelection(),
                c = a && "Range" === a.type && a.getRangeAt(0),
                e = c && b.createElement("div"),
                f = e ? (e.appendChild(c.cloneContents()), e.innerText) : "";
            return f
        },
        f = a.assign(console, {
            save: (a, d, f) => {
                a == null && (a = e(), "" === a.trim() && (a = b.body.innerText));
                let g = "object" == typeof a;
                g && (a = JSON.stringify(a, 0, 4));
                c(a, d || `DL-${+new Date}.${g?".json.txt":"md"}`, f || (g ? "application/json" : "octet-stream"))
            }
        });
    f.save()
}();



javascript: void
function() {

    let obj = Object,

        doc = document,

        downloadData = (dataOrBlob, filenameOrTrueForNewWindow, optionalMimeType) => {

            let U = URL,

                url = U.createObjectURL(dataOrBlob = new Blob([dataOrBlob], {
                    type: optionalMimeType || dataOrBlob?.type || "application/octet-stream"
                }));

            obj.assign(doc.createElement("a"), {
                href: url
            }, true === filenameOrTrueForNewWindow ? {
                target: "_blank"
            } : {
                download: filenameOrTrueForNewWindow || ""
            })
            .click(),
            
            U.revokeObjectURL(url)
        },

        fnIdentity = v => v,

        getSelectedText = () => {

            if (doc.onselectstart && doc.onselectstart !== fnIdentity) return doc.onselectstart = fnIdentity, alert("Text selecting was disabled!\n\nTry again, it is now enabled...");

            let selection = doc.getSelection(),

                range = selection && "Range" === selection.type && selection.getRangeAt(0),

                element = range && doc.createElement("div"),

                text = element ? (element.appendChild(range.cloneContents()), element.innerText) : "";

            return text

        },

        con = obj.assign(console, {

            save: (data, filename, mimeType) => {

                data == null && (data = getSelectedText(), "" === data.trim() && (data = doc.body.innerText));

                let isJson = "object" == typeof data;
                isJson && (data = JSON.stringify(data, 0, 4));

                downloadData(data, filename || `DL-${+new Date}.${isJson?".json.txt":"md"}`, mimeType || (isJson ? "application/json" : "octet-stream"))

            }
            
        });

    con.save()

}();

@DarrenSem
Copy link
Author

PS: try typing console.save(document.location, true) for a surprise!

@DarrenSem
Copy link
Author

// DLasMD-console.save

// DOWNLOAD contents as MarkDown.js, plus adds console.save() function

// FULL BOOKMARKLET...

// 15Jan2025 904pm START merging the 2 bookmarklets into 1, on "click" will call DLasMD(), END 1022pm [empty console.save() call no longer selectedText!]
// 741 char  (no need for NULL, just UNDEF) javascript:void function(){let a=document,b=Object,c=b._,d="application/octet-stream",e=console,f=()=>a.body.innerText,g=a=>a,h=(c,e=`DL-${+new Date}.md`,f)=>{let g=URL,h=g.createObjectURL(c=new Blob([c],{type:f||c?.type||d}));b.assign(a.createElement("a"),{href:h},!0===e?{target:"_blank"}:{download:e||""}).click(),g.revokeObjectURL(h)};(e.save||=(a,b,e)=>{if(a==c){let d=prompt("Enter data to download...\n\n(Whitespace or =FILENAME.EXT defaults to document.body.innerText)")?.trim();if(d==c)return c;/^=./.test(d)&&(b=d.slice(1),d=0);a=d.length?d:f(),b=!0===b?b:b?`${b}${b.includes(".")?"":".md"}`:c}let g="object"==typeof a;g&&(a=JSON.stringify(a,0,4));h(a,b||`DL-${+new Date}.${g?".json.txt":"md"}`,e||(g?"application/json":d))})()}();
// ^ final version. Because I didn't comment this clearly on 15Jan2025 130pm.



// [FULL BOOKMARKLET...]

let doc = document;

let obj = Object;

let UNDEF = obj._;

// let DEBUG_DEFAULT_SELECTED_TEXT_NOT_PROMPT = !!"DEBUG_DEFAULT_SELECTED_TEXT_NOT_PROMPT"; // console.save.js
let DEBUG_DEFAULT_SELECTED_TEXT_NOT_PROMPT = !"DEBUG_DEFAULT_SELECTED_TEXT_NOT_PROMPT"; // DLasMD.js

let OCTET_STREAM = "application/octet-stream"; // different than just "octet-stream"

let CON = console; // for final step: ( CON.save ||= consoleSave )();

let bodyText = _ => doc.body.innerText;

let fnIdentity = v => v;



let saveDataAsFilenameMime = (
  dataOrBlob,
  filenameOrTrueForNewWindow = `DL-${+new Date}.md`, // filename extension automatically added based on Blob.type
  optionalMimeType
) => {

  let U = URL;
  let href = U.createObjectURL(
    dataOrBlob = new Blob(
      [dataOrBlob],
      { type: optionalMimeType || dataOrBlob?.type || OCTET_STREAM }
    )
  );

  obj.assign( doc.createElement("a"),
    { href },
    filenameOrTrueForNewWindow === true
    ? { target: "_blank" }
    : { download: filenameOrTrueForNewWindow || "" } // including if <false> or <null> was passed (but not <undefined>)
  ).click();

  U.revokeObjectURL(href);

};



let selectedText = () => {
  if (doc.onselectstart && doc.onselectstart !== fnIdentity) {
    doc.onselectstart = fnIdentity;
    return alert("Text selecting was disabled!\n\nTry again, it is now enabled...");
  };

  let selection = doc.getSelection();
  let range = selection && selection.type === "Range" && selection.getRangeAt(0); // NOT the same as checking this flag: selection.isCollapsed
  let el = range && doc.createElement("div");
  let result = !el ? "" : (
    el.appendChild( range.cloneContents() ),
    el.innerText
  );

  return result;
};

let consoleSave = (dataOrBlob, filenameOrTrueForNewWindow, optionalMimeType) => {

  if (dataOrBlob == UNDEF) {

    // if (DEBUG_DEFAULT_SELECTED_TEXT_NOT_PROMPT) {
    //   dataOrBlob = selectedText();
    //   if (dataOrBlob.trim() === "") {
    //     dataOrBlob = bodyText();
    //   };
    // } else {

      let promptData = prompt(
        "Enter data to download...\n\n(Whitespace or =FILENAME.EXT defaults to document.body.innerText)"
      )?.trim();
  
      if (promptData == UNDEF) return UNDEF;
  
      if ( /^=./.test(promptData) ) {
        filenameOrTrueForNewWindow = promptData.slice(1);
        promptData = 0;
      };
  
      dataOrBlob = promptData.length ? promptData : bodyText();
  
      filenameOrTrueForNewWindow = (
        filenameOrTrueForNewWindow === true ? filenameOrTrueForNewWindow
        : filenameOrTrueForNewWindow ? `${filenameOrTrueForNewWindow}${filenameOrTrueForNewWindow.includes(".") ? "" : ".md"}`
        : UNDEF
      );

    // }; // if (DEBUG_DEFAULT_SELECTED_TEXT_NOT_PROMPT) {

  }; // if (dataOrBlob == UNDEF) {

  let isJson = typeof dataOrBlob === "object";
  if (isJson) {
    dataOrBlob = JSON.stringify(dataOrBlob, 0, 4);
  };

  saveDataAsFilenameMime(
    dataOrBlob,
    filenameOrTrueForNewWindow || `DL-${+new Date}.${isJson ? ".json.txt" : "md"}`,
    optionalMimeType || ( isJson ? "application/json" : OCTET_STREAM )
  );

};



( CON.save ||= consoleSave )();

// [/FULL BOOKMARKLET.]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment