Search code examples
cssextjssasscompasssencha-fashion

Compass inline-image syntax/configuration


I add the following block to myapp.scss:

.resourceType2 { 
    background: url('../resources/ressource2.png') no-repeat 2px 1px; 
    padding-left: 16px; 
}

After I call sencha app build production with Cmd 6.0.1.76, I see the background-image. I found that you can use inline-image and compass should make css inline images from your images. So I add to myapp.scss instead:

.resourceType2 { 
    background: inline-image('../resources/ressource2.png') no-repeat 2px 1px; 
    padding-left: 16px; 
}

After successful build, I don't see the images.

I found that MyApp-all.css still contains inline-image('../resources/ressource2.png'), just as if it wouldn't replace them properly. Am I missing some config option required to enable inline-image generation?


Solution

  • While reading the SenchaCon roadshow agenda, I more or less stumbled upon the answer.

    Summary:

    Cmd 6.0.1 does not use sass or compass any longer. It uses Sencha Fashion, which takes sass files and compiles them. Sencha Fashion does have support for sass variables, but not for compass helpers written in Ruby, because the goal was to remove the Ruby dependency. Instead, one would have to rewrite the required helpers as Sencha Fashion extensions in JavaScript.

    I have yet to find a list of available/builtin "extensions" and a full guide how to write my own. There are no javascript extensions available in the ext package as of now. There is no documentation available with all builtin SASS functions and their parameters, you can only find them by searching through the original scss files delivered with ExtJS.

    Extension example:

    If you want to have an extension that converts resource images to their data uri equivalent, you could put the following code into your sass/src directory, e.g. as inlineimage.js:

    exports.init = function(runtime) {
        if (typeof String.prototype.endsWith !== 'function') {
            String.prototype.endsWith = function(suffix) { 
                return this.indexOf(suffix, this.length - ((suffix && suffix.length) || 0)) !== -1; 
            };
        }
        function _arrayBufferToBase64( buffer ) {
            var binary = '';
            var bytes = new Uint8Array( buffer );
            var len = bytes.byteLength;
            for (var i = 0; i < len; i++) {
                binary += String.fromCharCode( bytes[ i ] );
            }
            return window.btoa( binary );
        }
        runtime.register({
            inlineImage: function (uri, mime) {
                // URI has the keys: value,unit,quoteChar,splat
                // URI has the values: ../../resources/delete.gif,,',
                if(!mime) {
                    if(uri.value.toLowerCase().endsWith(".png")) mime = "image/png";
                    else if(uri.value.toLowerCase().endsWith(".gif")) mime = "image/gif";
                    else if(uri.value.toLowerCase().endsWith(".jpg")) mime = "image/jpeg";
                    else if(uri.value.toLowerCase().endsWith(".jpeg")) mime = "image/jpeg";
                }
                var xhr = new XMLHttpRequest();
                xhr.open('GET', uri.value, false); 
                xhr.responseType = "arraybuffer";
                xhr.send(null);
                if(xhr.status==404) throw new Error("Inline image source " + uri.value + " not found");
                uri.value="url(data:"+mime+";base64,"+_arrayBufferToBase64(xhr.response)+")";
                uri.quoteChar="";
                return uri;
            }
        });
    };
    

    In your scss file, for instance sass/src/view/Viewport.scss, you would then write:

    require("../inlineimage.js");
    .icon-checklist {
        background: inlineImage('../images/checklist.png') no-repeat center center !important;
    }
    

    The image in this case would be located in sass/images, so that cmd won't copy it into the output resource folder (it should only show up in the output CSS file).

    The inlineImage in the scss file now refers to the registered javascript function inlineImage, which will be executed to download the image and return it as a data uri.

    Sources: