Tailwind Controls not available when using "open in wrapper"

I noticed that I have access to the tailwind controls when I open the page normally inside the Pinegrow builder, but now when I’m opening it in a wrapper. Is this by design or a bug?

Steps to reproduce.

  1. Start a new Tailwind Project
  2. Open the index.html file normally and see that you can use the tailwind controls
  3. Open the index.html file in a wrapper
  4. And note that the Tailwind controls are no longer available

@adamslowe it appears Tailwind CSS is not detected on the wrapper page. Detection is done by looking for a stylesheet containing “tailwind” in its name. Is the theme using a non-standard name, or scrambled by CDN?

You can manually activate it by running this code in the Dev tools console:

frames[0].$.fn.crsacss('showFrameworkManager', frames[0].pinegrow.getSelectedPage());

to open the Framework manager. We might have to bring this dialog back in.

Ahh, interesting!

I’m testing Pinegrow and the Winden plugin working together and it looks like they are using Javascript to add the CDN. It looks like this is a “them” problem more than a Pinegrow problem, so that’s good to know.

<!-- Tailwind CSS: CDN -->
<script type="module" id="winden-tailwind-css-cdn">
    let importShim;
    try {
        await (0, eval)('import("")')
    } catch (error) {
        if (error instanceof TypeError) {
            importShim = (0, eval)('u=>import(u)');
        } else {
            var s = document.createElement('script');
            s.src = 'https://unpkg.com/shimport';
            document.head.appendChild(s);
            importShim = __shimport__.load;
        }
    }

    const require = async (m) => {
        let result;
        try {
            result = await importShim('https://cdn.skypack.dev/' + m + '?min');
            console.log('importShim', m, 'success');
            window.countModulesToLoad--;
        } catch (error) {
            console.log('Cannot find module "' + m + '"');
        }
        return result.default || result;
    }

    (async () => {
        console.log('Loading Modules...');

        window.countModulesToLoad = 4;
let shim_5b55b192f52bfe183b17b6d540dc1bb0 = (await require('@tailwindcss/typography'));
let shim_478e11c8d44b15f9e94c007cc50d9c5b = (await require('@tailwindcss/forms'));
let shim_19061aff58693e64426688d4211f85b6 = (await require('flowbite/plugin'));
let shim_9b6791af47f48611a818b54209c27df1 = (await require('daisyui'));

        // Block the execution until modules are loaded
        await new Promise(resolve => {
            console.log('waitingForModulesLoaded. remaining count:', window.countModulesToLoad);
            let waitingForModulesLoaded = setInterval(() => {
                if (
                    window.countModulesToLoad === 0
                ) {
                    var s = document.createElement('script');
                    s.src = 'https://cdn.tailwindcss.com/3.2.4';
                    s.id = 'tailwindcss-cdn';
                    document.head.appendChild(s);
                    clearInterval(waitingForModulesLoaded);
                    resolve();
                }
            }, 50);
        });

        // Block the execution until Tailwind CDN are loaded
        await new Promise(resolve => {
            console.log('Loading Tailwind CDN...');
            let waitingForTailwindLoaded = setInterval(() => {
                if (typeof tailwind !== 'undefined' && tailwind !== undefined) {
                    console.log('Tailwind CDN loaded');
                    clearInterval(waitingForTailwindLoaded);
                    resolve();
                }
            }, 50);
        });

                tailwind.config = {
	theme: {
		extend: {
			colors: {
				clifford: '#da373d',
			},
			// ...
		},
	},
	plugins: [
		//shim_5b55b192f52bfe183b17b6d540dc1bb0,
    	//shim_478e11c8d44b15f9e94c007cc50d9c5b,
		// flowbite components
		//shim_19061aff58693e64426688d4211f85b6,
		// daisyUI components
		//shim_9b6791af47f48611a818b54209c27df1
	],
	corePlugins: {
		preflight: false,
	}
}
        
        const bc = new BroadcastChannel('winden_channel');
        const cssEl = document.getElementById('winden-tailwind-css-custom-css');

        bc.onmessage = (event) => {
            if (event.data.key === 'global_css') {
                cssEl.innerHTML = event.data.value;
            }
        }
    })();
</script>

<!-- Tailwind CSS: Custom CSS -->
<style type="text/tailwindcss" id="winden-tailwind-css-custom-css">
    @tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
    .winden-avatar {
        @apply h-12 w-12 rounded-full ring-2 ring-white;
    }
    .winden-card {
        background-color: theme('colors.black');
        border-radius: theme('borderRadius.lg');
        padding: theme('spacing.6');
        box-shadow: theme('boxShadow.xl');
    }
}</style>

@adamslowe they do this on production sites? It is a very un-optimal way to use Tailwind CSS because it gets compiled at run-time in the browser.

They use the CDN in development mode, then compile it when you switch over to production mode.

The big benefit of Winden is that it allows us to modify the Tailwind config since Pinegrow doesn’t.


@adamslowe this makes sense. Thanks for details!

1 Like

Hi @matjaz,

I have explored the source code a bit and found an interesting code.

// \wp-content\plugins\pinegrow\pinegrow\frameworks\tailwindcss\tailwindcss.js

return e.hasStylesheet(/tailwind/i) || e.hasScript(/cdn\.tailwindcss\.com/i)

can we have a variable registered on the window. scope that we can invoke to force the tailwind detection instead relied on the above snippet code?

For example, we call it on the browser console:

window.pgFramework.tailwind.detected = true;
window.pgFramework.tailwind.version = 3;

Hi @suabahasa, detection runs on the source DOM model, without executing JS, so we could not detect this value if it would be set at runtime with JS.

How about we expand the auto detection by searching for script#winden-tailwind-css-cdn"? This would work if the script is visible in View source of the page.

1 Like