Skip to content

Instantly share code, notes, and snippets.

@KevinBatdorf
Last active May 7, 2024 18:51
Show Gist options
  • Save KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822 to your computer and use it in GitHub Desktop.
Save KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822 to your computer and use it in GitHub Desktop.
Auto copy the Alpine code from Tailwind UI's copy button
// ==UserScript==
// @name Add AlpineJs to Tailwind UI
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Add Alpine JS code to Tailwind Ui copy/paste
// @author https://gist.github.com/KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822
// @match https://tailwindui.com/components/*
// @grant none
// ==/UserScript==
// Requires Tampermonkey
// Chrome - https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en
// FF - https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/
// Find me on Twitter: https://twitter.com/kevinbatdorf
// Get the version that downloads the code into a file here:
// https://gist.github.com/KevinBatdorf/322c68f532af6a4cc6773f906da0684d
// If it seems to not be working, check the classes here are matching
const code = Array.from(document.querySelectorAll('button')).filter(
b => b.classList.value === 'group relative ml-2 hidden h-9 w-9 items-center justify-center sm:flex'
);
code.forEach(node => {
node.addEventListener('click', function(event) {
event.preventDefault();
// This is the iFrame the component is in
const iFrame = event.target.closest('[id^=component-]').querySelector('[name][id^=frame]');
const contentArea = iFrame.contentWindow.document.querySelector('body > div');
const markup = contentArea.innerHTML;
// This will attempt to extract the function used in the x-data, like x-data="Component.popover"
const scripts = Array.from(contentArea.querySelectorAll('[x-data]'))
.filter((n) => /\(.*\)/.test(n.getAttribute('x-data').toString()))
.map((n) => {
const fnNameSplit = n
.getAttribute('x-data')
.replace('window.', '')
.replace(/\(.*\)/, '')
.split('.');
// We need to get the string representation of the method
const method = new Function(`return ${iFrame.contentWindow[fnNameSplit[0]][fnNameSplit[1]]};`);
// This adds checks to create the global object then register it.
return `
window.${fnNameSplit[0]} = window.${fnNameSplit[0]} ?? {}
window.${fnNameSplit[0]}['${fnNameSplit[1]}'] = ${method}()
`
})
.join(';')
.toString();
const textarea = document.createElement('textarea');
textarea.textContent = scripts ? `<script>${scripts}</script>` + markup : markup;
document.body.appendChild(textarea);
setTimeout(() => {
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}, 50);
})
})
@MartijnHarmenzon
Copy link

MartijnHarmenzon commented Oct 17, 2022

I just tried it out on the first nav item and it seems to work still. Make sure it's active on the site. You should see a red 1 in a square

Screen Shot 2022-10-15 at 11 53 23 AM

Thanks @KevinBatdorf. It is working now. You are correct. Tampermonkey was not active. My bad.

@gregnewman
Copy link

This doesn't seem to be working anymore. Trying to use it on command palettes. I tried in both safari and chrome. Chrome only copies a nearly empty container. Safari copies exactly what is in the code preview.

@KevinBatdorf
Copy link
Author

Does it work on other components? It won't copy if the content is larger than the clipboard can hold. You could try the gist I mention in the comment on line 18

https://gist.github.com/KevinBatdorf/322c68f532af6a4cc6773f906da0684d

@gregnewman
Copy link

@KevinBatdorf no it doesn't work on other components. Just grabs the empty div with id of app. Tried the gist you linked to also and does the same thing.

@gregnewman
Copy link

Just got it to work on a modal component. It seems spotty in what it can extract.

@KevinBatdorf
Copy link
Author

Can you share a component it's not working on? I tried it on the hero sections and a few others and it's working

Screen Shot 2023-02-01 at 10 38 11 AM

@KevinBatdorf
Copy link
Author

Just got it to work on a modal component. It seems spotty in what it can extract.

Saw this after I commented. I can try to see why some aren't working. It could be they changed something.

@ovp87
Copy link

ovp87 commented Feb 6, 2023

@KevinBatdorf Kudos for still maintaining this 👍

@aitoehigie
Copy link

It no longer seems to work?

@KevinBatdorf
Copy link
Author

@aitoehigie I just tried it on a dropdown and it worked. Which componen isn't working?

@morgler
Copy link

morgler commented May 7, 2024

I can confirm, it worked for me on the full Application UI Sidebar layout

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