Allow callback functions during Export to transform output

This will get somewhat lengthy, but hopefully someone from the BSS team could make something out of it. Here we go:

First, some background. I’m writing my front-end stuff using Laravel Blade templates (HTML on steroids). Blade uses a concept called template inheritance in which we define a master/base HTML that defines the structure of our website (navigation menu, left/right panes, footer etc.) and several content HTML files, which provide the actual stuff of that page. This saves us from writing the same HTML over and over in every page and also makes it very easy to make structural changes.

Blade provides two server-side tags named @section and @yield that define where a particular piece of content page will be placed in the master page. Works like this:

Master page

<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

Content page

@extends('layouts.app')

@section('title', 'Page Title')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@endsection

@section('content')
    <p>This is my body content.</p>
@endsection

OK. Enough background. So I’m using BSS to design my front-end. Whenever I want to make a change, I just go to BSS, make changes, export the stuff and just replace existing files in my actual front-end. It generally works since Blade is mostly HTML, but there are a few key problems that make the job a bit more tedious than it should be:

  • Firstly, those server-side tags are not supported in BSS. I’m currently working around it by using Custom Code elements. This approach works correctly, although not as clean as built-in elements (e.g. have to keep track of starting/ending tags etc.)
  • Output files have html extension. I’m using a PowerShell script to bulk-rename them to .blade.php. BSS allows running post-export scripts, so this step can be managed elegantly.
  • The fact that BSS treats all pages as standard HTML pages and creates <html>, <head> and <body> tags. There is no concept of component pages (so to speak) in BSS, which could just store sections of HTML instead of full HTML pages. There is no simple workaround for it. I have to manually remove this stuff every time from my content pages after export. This also answers your question as to why I want to remove <head> section.

Now I understand that that BSS was probably not supposed to be used like this, but the fact is that most of the web applications that use one of those popular frameworks (Laravel, React, Vue, Angular) need some sort of post-export manipulation to shape the raw HTML correctly.

The Export Script feature provided by BSS is one step in the right direction, but falls short of providing true element level control. My suggestion is to allow users to write small Javascript functions that BSS would call at more granular levels. For example, BSS could invoke callback functions:

  • Export_started
  • Page_started (ref output_file_name)
  • Element_generated(ref string content)
  • Page_saved(string path)
  • Export_completed Those ref parameters (sorry, couldn’t resist my C#, LOL) indicate that the called script should be able to modify the incoming value and BSS would then use that modified value in the export.

All this will still be an optional/advanced usage, leaving the standard use of BSS intact, thereby not affecting existing users and their work.

Hopefully the BSS team would do some brainstorming about it and make something concrete from it. This will take BSS to new heights and make it easily integrate into the regular development cycle of professionals, where front-end design keeps evolving over the life of the project and people need to go back to BSS, make changes and then bring them back into their actual server-side/client-side code. Using this approach, they’ll not have to hand-edit the output every time.

Note: This is just an improvement idea. I'm not asking for an alternate solution for the specific problem example I quoted above. That problem can be solved using alternate scripts or writing small console apps. Problem is that those solutions are not generic enough and need to be tweaked every time. With the solution that I presented above, BSS will become just a normal part of the development cycle and people will be able to come back to it, make small changes to the design and generate their new HTML, ready to be served, without requiring an additional stage of transformations.

Thank you for sharing this idea! Calling user supplied code would be an interesting approach. I see a few problems with this though:

  • Code isolation - user code needs to be isolated both in security terms and in performance terms. We don't want user code to crash the app or make the export hang or become very slow.
  • Debugging - when writing complex code it's indispensable to do step by step debugging to work around issues. So some kind of debugger will be needed.

These are difficult problems to solve and given that very few people will actually use this feature, I don't think we can afford to work on it.

But I can propose an alternative. Since you are an experienced developer, I think that enhancing your export script can give the same (or even better) results. You can write a C# program that parses the HTML of the generated pages, and transforms the tree in any way that you need. This way you can have full control over your export logic, use any library that you need and debug it with a real debugger.

Thanks for getting back. It is always good to know that someone from the team is looking into these ideas.

So I see the problems you've listed. One way to get around these issues is to make these callbacks out-of-process, i.e. instead of accepting raw javascript, allow user to specify an exe or script for each of those events (much like BSS currently does with the post-export script), and then read back from the standard output buffer, thus making BSS independent of the actions/state of the called script. This will handle stability issues too.

I understand that the post-export script can be used to manipulate the generated HTML in any way I want and I have actually done that in a past project. It works for small one-way exports, however it falls short when we talk about a full-circle integration of BSS in our development model, i.e. instead of using BSS as a quick one-time prototyping tool, we'd use it as a standard front-end design tool, which we could come back to whenever we want to make changes to the UI and re-generate new code to directly replace existing UI code.