Xslt-style HTML file inheritance

    Problem


    Once, during the rewriting of a large project, it became necessary to improve the mechanism for customizing html templates for different versions of our web application. In the old version, customization looked like this:

    {{if app.version==versions.main}}
    
    {{else if app.version==versions.custom1}}
    
    {{else if app.version==versions.custom2}}
    
    {{endif}}
    

    And with such noodles the whole project was permeated. Such code is difficult to maintain and modify, with active use, templates turn into an incomprehensible mess, where the business logic of displaying individual blocks is intertwined with customization for different versions.

    Having gotten used to convenient methods of version control of the application using dependency injection, when different interface implementations are used depending on the version, I decided to invent my bike for XSLT-like version control of html files: grunt-html-inheritance . It allows you to replace pieces of the basic html file with small patches.

    When rewriting the project, AngularJS was chosen as the framework, so the layout in the application is stored as a set of html files, loaded if necessary, which made it easy to implement a system for building these files with customization for different versions of the application.

    Example


    Let's imagine that we have the following piece of layout in the HTML file "myfile.html":
    Blah blah blah
    Main version


    And, as often happens in different versions of the application, we needed that in the version “myversion” instead of one text “Main version” another one would be displayed: “My version”. To do this with html-inheritance, you need to do 2 simple steps:

    1. Add the attribute starting with “bl-” to the tag to be tagged:

    Blah blah blah
    Main version


    2. Create a file “myfile.myversion.html” with a patch for the parent file:

    Custom version


    All! During the build of the project, all html files will be neatly folded into the specified folder by version:

    dist
      |
      main /
         myfile.html
      myversion /
         myfile.html
    

    Now it’s enough to tell your application where to load the html files from depending on the version, and everything will work by itself!

    Installation


    To add grunt-html-inheritance to your project, you need to install the npm module with the command
    npm install grunt-html-inheritance --save-dev

    or add dependency to package.json, load the task into Gruntfile.js with the command
    grunt.loadNpmTasks('grunt-html-inheritance');

    and configure the task as follows:
    
    grunt.initConfig({
      html_inheritance: {
          main: {
              files: { 
                src: "**.html" //селектор для файлов
              },
              options: {
                  modules: ["version1", "version2"], //список модулей
                  dstDir: "../dist", //папка, в которую будут складываться скомпиленные файлы
              },
          },
      },
    });
    

    In an AngularJS application, an important condition for easily switching between versions of HTML files is to use a helper to build paths to template files instead of hard-coded these paths in directives and routings.

    Benefits


    The most interesting advantage of such a customization system is that the main version of the project can be used without compiling html files, since bl attributes do not prevent the browser from displaying the source file. Also, to use this method, you do not need to learn the new syntax of any template engine; all the logic is implemented using the usual html-attributes familiar to every developer.

    Using


    In addition to replacing the base tag in the patch described in the example above, the following modes are also available:
    1. Delete - deletes the parent element in the patch
    2. Insert - insert in the patch of the element, while in the main version of the element will not be
    3. Modification of attributes - deleting and adding attributes to the parent element, deleting and adding classes.

    Full documentation is available on the package page or in the github repository . The module is covered by tests and needs further improvement. I invite the community to help in the development, send pull requests!

    Also popular now: