-
-
Save KevinBatdorf/8bd5f808fff6a59e100dfa08a7431822 to your computer and use it in GitHub Desktop.
// ==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); | |
}) | |
}) |
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
@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.
Just got it to work on a modal component. It seems spotty in what it can extract.
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.
@KevinBatdorf Kudos for still maintaining this 👍
It no longer seems to work?
@aitoehigie I just tried it on a dropdown and it worked. Which componen isn't working?
I can confirm, it worked for me on the full Application UI Sidebar layout
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.