JSFiddle - React, Tailwind, and code Playground

HTML

<div ng-app="app" ng-controller="demoCtrl">
<my-image my-image-opts= "image.options">
    <div>
        <label for="source">Source</label>
        <input class="styles" type="text" id="source" ng-model="image.options.attrs.src"/>
    </div>
    <div>
        <label for="desc">Description de l'image</label>
        <input type="text" id="desc" ng-model="image.options.attrs.alt"/> 
    </div>
    <div>
        <label for="width">Largeur</label>
        <input type="number" id="width" ng-model="image.options.styles.width.number"/>
        <button ng-repeat="unit in units" 
        ng-click="image.options.styles.width.unit = unit">{{ unit }}</button>
        <label for="width">Hauteur</label>
        <input type="number" id="height" ng-model="image.options.styles.height.number"/>
        <button ng-repeat="unit in units" 
        ng-click="image.options.styles.height.unit = unit">{{ unit }}</button>
    </div>
    <div>
        Alignement
        <button type="button"
            ng-click="image.options.styles.float = 'left'">Gauche
        </button>
        <button type="button"
            ng-click="image.options.styles.float = 'right'">droit
        </button>
    </div>
    <div>
        <label for="styles">Styles</label>
        <input class="styles" type="text" id="styles" ng-model="image.options.attrs.style"/> 
    </div>
     <div>
        <label for="classes">Styles</label>
        <input class="styles" 
         type="text" id="classes" ng-model="image.options.attrs.class"/> 
    </div>
 </my-image>
    
</div>

CSS

div {
    padding:8px 0px;
}

.code {
    color: #DB6863;
}
.styles{
    width: 80%;
}

JavaScript

var app = angular.module('app', []);

app.controller('demoCtrl', function($scope){

    $scope.image = {
        options: {
            attrs: {
                src: 'http://i.imgur.com/VValYw6.jpg',
                alt: 'desc',                
                style: 'border: 1px solid #000; border-radius:10px;',
                class: 'left small'
            },
            styles: {
                width: { number: 250, unit: 'px' },
                height: { number: 150, unit: 'px' },
                float: 'left'
            },
            html: ''
        }
    };
    
    $scope.units = ['px', '%', 'em'];
    
});

app.directive('myImage', function(){
    return {
        restrict: 'E',
        scope: {
            options: '=myImageOpts'                
        },
        transclude: true,
        template: 
        '<div ng-transclude></div>'+
        '<p>Code généré: <span class="code"> {{ options.html }}</span></p>',
        link: function(scope, elem){
            elem.find('input').bind('keyup change', function(){
                scope.$apply(function(){
                    scope.appendImg();
                });
            });
            scope.$watch('options',function(newVal, oldVal){
                if(newVal) {
                   scope.appendImg(); 
                }
            }, true);
            
            scope.setAttrs = function() {
                var attrs = '';
                var styles= '';
                var copy = angular.copy(scope.options);
                angular.forEach(copy.styles, function(option, key){
                    if(angular.isDefined(option.unit)){
                        copy.styles[key] = option.number + option.unit;
                    }
                });
                angular.forEach(copy.attrs, function(attr, key){
                    if(key !== 'style'){
                        attrs += key + '="' + attr + '" ';
                    }
                    else {
                        styles = key +...