tomjn / block-comments

A prototype for block editor based comments
https://tomjn.com
31 stars 2 forks source link

Web Component? #4

Open chriscoyier opened 5 years ago

chriscoyier commented 5 years ago

(Not really an issue... feel free to close.)

Theme styling can interrupt the block editor UX. Improvements to this plugins stylesheet

Interesting problem here. I wonder if making the controls a web component (ala <gutenberg-controls>) or whatever would be useful as then you have a Shadow DOM to work with with totally isolated styles.

tomjn commented 5 years ago

Ah! I’m going to dig into that, thanks :)

On Tue, 23 Jul 2019 at 23:10, Chris Coyier notifications@github.com wrote:

(Not really an issue... feel free to close.)

Theme styling can interrupt the block editor UX. Improvements to this plugins stylesheet

Interesting problem here. I wonder if making the controls a web component (ala ) or whatever would be useful as then you have a Shadow DOM to work with with totally isolated styles.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/tomjn/block-comments/issues/4?email_source=notifications&email_token=AAAOLZZZLYJUFFO4SDJJSALQA56WBA5CNFSM4IGKEPN2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HBB5YZQ, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAOLZ4RUMFHP7RX5HXNWYTQA56WBANCNFSM4IGKEPNQ .

tomjn commented 4 years ago

So I've done some research on this. Mainly because without it, my new improvements leave much to be desired:

Screenshot 2020-08-16 at 19 48 07

Wrapping everything in a web component should be easy, however, the problem is loading the block editors assets into the shadow DOM.

I can enqueue the existing script and have it swap the target element for a <blockeditor> instead of a <div> that React gets mounted on. Ii'll then need to load the script and styles for the editor itself into the shadow DOM. I can't rely on the standard wp_enqueue_script method though.

I suspect the solution is here:

https://wordpress.stackexchange.com/a/373085/736

If I use wp_localise_script and pass in that data as a JSON array of scripts that the shadow DOM can then use by creating link and script tags dynamically, that might do the trick.

Another alternative, is to have a REST API endpoint that returns the raw scripts in the order that they're needed, but i don't like that idea much. it simplifies the frontend by doing work on the server

tomjn commented 4 years ago

I circled back to this today and devised this mini plugin to test out rendering the script tags of a WP asset by its handle:

<?php
/**
 * Plugin Name: Dependency Tests
 * Author: Tom J Nowell
 */

function get_script_dependencies( array $handles ) : array {
    $dependencies = [];
    $handler = wp_scripts();

    // Get all its dependencies:
    $handler->all_deps( $handles );

    // add each dependency to an array
    foreach ( $handler->to_do as $handle ) {
        $dependencies[] = $handler->registered[ $handle ];
    }

    return $dependencies;
}

function get_style_dependencies( array $handles ) : array {
    $dependencies = [];
    $handler = wp_styles();

    // Get all its dependencies:
    $handler->all_deps( $handle );

    // add each dependency to an array
    foreach ( $handler->to_do as $handle ) {
        $dependencies[] = $handler->registered[ $handle ];
    }

    return $dependencies;
}

function get_handle_script_tags( array $handles ) : string {
    ob_start();
    $scripts = wp_scripts();
    $scripts->do_items( $handles );
    $result = ob_get_clean();
    return $result;
}

add_action( 'wp_loaded', function() {
    if ( empty( $_GET['script'] ) ) {
        return;
    }
    $dependencies = get_script_dependencies( [ $_GET['script'] ] );
    $handles = wp_list_pluck( $dependencies, 'handle' );
    $result = get_handle_script_tags( $handles );
    $json = json_encode( $result, JSON_PRETTY_PRINT );
    echo $json;
    exit;
} );

usage: example.com/?script=wp-editor

With this I believe I can register the script then load it into the shadow dom by creating a second script that registers/implements the web component and bootstraps the first script