Giter Club home page Giter Club logo

require-css's Introduction

require-css

RequireJS CSS requiring and optimization, with almond support.

Useful for writing modular CSS dependencies alongside scripts.

For LESS inclusion, use require-less, which behaves and builds the css exactly like this module apart from the preprocessing step.

Overview

Allows the construction of scripts that can require CSS, using the simple RequireJS syntax:

define(['css!styles/main'], function() {
  //code that requires the stylesheet: styles/main.css
});

Fully compatible in IE 6+, Chrome 3+, Firefox 3.5+, Opera 10+, iOS.

  • CSS builds When run as part of a build with the RequireJS optimizer, css! dependencies are automatically inlined into the built layer within the JavaScript, fully compatible with layering. CSS injection is performed as soon as the layer is loaded.
  • Option to build separate layer CSS files A separateCSS build parameter allows for built layers to output their css files separately, instead of inline with the JavaScript, for manual inclusion.
  • CSS compression CSS redundancy compression is supported through the external library, csso.

Installation and Setup

Download the require-css folder manually or use Bower:

bower install require-css

To allow the direct css! usage, add the following map configuration in RequireJS:

map: {
  '*': {
    'css': 'require-css/css' // or whatever the path to require-css is
  }
}

Use Cases and Benefits

Motivation

The use case for RequireCSS came out of a need to manage templates and their CSS together. The idea being that a CSS require can be a dependency of the code that dynamically renders a template. When writing a large dynamic application, with templates being rendered on the client-side, it can be beneficial to inject the CSS as templates are required instead of dumping all the CSS together separately. The added benefit of this is then being able to build the CSS naturally with the RequireJS optimizer, which also supports separate build layers as needed.

Script-inlined CSS Benefits

By default, during the build CSS is compressed and inlined as a string within the layer that injects the CSS when run.

If the layer is included as a <script> tag, only one browser request is needed instead of many separate CSS requests with <link> tags.

Even better than including a layer as a <script> tag is to include the layer dynamically with a non-blocking require. Then the page can be displayed while the layer is still loading asynchronously in the background. In this case, the CSS that goes with a template being dynamically rendered is loaded with that same script asynchronously. No longer does it need to sit in a <link> tag that blocks the page display unnecessarily.

Modular CSS

RequireCSS implies a CSS modularisation where styles can be scoped directly to the render code that they are bundled with.

Just like JS requires, the order of CSS injection can't be guaranteed. The idea here is that whenever there are style overrides, they should be based on using a more specific selector with an extra id or class at the base, and not assuming a CSS load order. Reset and global styles are a repeated dependency of all modular styles that build on top of them.

Optimizer Configuration

Basic Usage

Optimizer configuration:

{
  modules: [
  {
    name: 'mymodule',
    exclude: ['css/normalize']
  }
  ]
}

If the contents of 'mymodule' are:

  define(['css!style', 'css!page'], function(css) {
    //...
  });

Then the optimizer output would be:

-mymodule.js containing: style.css and page.css which will be dynamically injected

The css/normalize exclude is needed due to r.js issue #289

Separate File Output

To output the CSS to a separate file, use the configuration:

{
  separateCSS: true,
  modules: [
  {
    name: 'mymodule'
  }
  ]
}

This will then output all the css to the file mymodule.css. This configuration can also be placed on the module object itself for layer-specific settings.

Optimization is fully compatible with exclude and include.

IE8 and 9 Selector Limit

In IE9 and below, there is a maximum limit of 4095 selectors per stylesheet.

In order to avoid this limit, CSS concatenation can be disabled entirely with the IESelectorLimit option.

{
  IESelectorLimit: true,
  modules: [
  {
    name: 'mymodule'
  }
  ]
}

Ideally build layers would avoid this limit entirely by naturally being designed to not reach it. This option is really only as a fix when nothing else is possible as it will degrade injection performance.

This option is also not compatible with the separateCSS option.

Excluding the CSS Module in Production

When dynamic CSS requires are not going to be made in production, a minimal version of RequireCSS can be written by setting a pragma for the build:

{
  pragmasOnSave: {
    excludeRequireCss: true
  }
}

siteRoot Configuration

When building the CSS, all URIs are renormalized relative to the site root.

It assumed that the siteRoot matches the build directory in this case.

If this is different, then specify the server path of the siteRoot relative to the baseURL in the configuration.

For example, if the site root is www and we are building the directory www/lib, we would use the configuration:

{
  appDir: 'lib',
  dir: 'lib-built',
  siteRoot: '../',
  modules: [
  {
    name: 'mymodule'
  }
  ]
}

Almond Configuration

Almond doesn't support the packages configuration option. When using Almond, rather configuration RequireCSS with map configuration instead, by including the following configuration in the production app:

  requirejs.config({
    map: {
      '*': {
        css: 'require-css/css'
      }
    }
  });

Disabling the Build

To disable any CSS build entirely, use the configuration option buildCSS:

{
  buildCSS: false,
  modules: [
  {
    name: 'mymodule'
  }
  ]
}

CSS requires will then be left in the source "as is". This shouldn't be used with stubModules.

CSS Compression

CSS compression is supported with csso.

To enable the CSS compression, install csso with npm:

  npm install csso -g

The build log will display the compression results.

When running the r.js optimizer through NodeJS, sometimes the global module isn't found. In this case install csso as a local node module so it can be found.

Injection methods

When loading a CSS file or external CSS file, a <link> tag is used. Cross-browser support comes through a number of careful browser conditions for this.

If CSS resources such as images are important to be loaded first, these can be added to the require through a loader plugin that can act as a preloader such as image or font. Then a require can be written of the form:

require(['css!my-css', 'image!preload-background-image.jpg', 'font!google,families:[Tangerine]']);

License

MIT

require-css's People

Contributors

aintaer avatar alundiak avatar aparshin avatar bitdeli-chef avatar bvalosek avatar danse avatar deanrad avatar gaubee avatar guybedford avatar jardilio avatar jcppman avatar kmontag avatar marioestrada avatar miguelcastillo avatar mm-sam avatar netforce1 avatar nicholasstephan avatar osmestad avatar prantlf avatar rangermeier avatar rxaviers avatar samhowie avatar satazor avatar sney2002 avatar tigrawap avatar victordidenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

require-css's Issues

absolute path import normalization

Hello,

Our app structure looks like
--- app
------- style
----------- base.less
------- components
----------- component-1
--------------- component1.less

component-i.less files contain the line
@import '/style/base.less';

It works in ordinary mode but fails under optimizer:
r.js tries to open 'c:/style/base.less' instead of 'c:/path/to/app/style/base.less'.

The only way I could find to resolve the problem is the following change in normalize.js:

function convertURIBase(uri, fromBase, toBase) {
if ( uri.indexOf('/') === 0 ) return uri.substr(1);

Another problem is that I have to specify '.less' extension explicitly.
Otherwise it could not find imports neither in ordinary mode nor under optimizer.

Thank you

Single File Build Question

In development, it loads CSS perfectly fine, though for my build step, I'd want to build all my required CSS built into one concatenated CSS file. It seems like you have support with "separateCSS" ? Though I do a single file build instead of a whole project build (because my apps use two separate base directories (app and common)) to load files from.

Is there a way to do a single file CSS build ? Like trace all dependancies from a given JS entry point, and concat all CSS found ?

I could try and get the project build working, though it seems the copy-to-build-directory step fails with paths like ../../framework/lib/jquery.

Any ideas ?

Overriding normalizeName for the optimizer generated code

Not a bug but a potential feature request.

I've finally solved all my problems with the optimizer and evything is fine so I'm starting to nitpick a bit and went to see how if I could do even better to reduce the number of requests issued to the server.

As I work on a mobile webapp it's a bit more important for my use case than for most.

And there I saw that require was taking normalize.js from the server despite the fact that it was embedded in one of my optimized file.

So I tracked down which call it was and it is from the cod that inline the css inside my optimized file.

The generated code is :

require(['css', 'common/js/libs/require/normalize', 'require'], function(css, normalize, require) {

while all the other call either call "normalize" or "./normalize" which seems to work fine.

One solution would be to include normalize two times in my optimization, one with the name "normalize" and one with the name "common/js/libs/require/normalize" but that would be quite dirty since I would have the code in double afaik.

So another option would be to add a config param, say overrideNormalizeName, which would be used instead of the calculated name when present in the function onLayerEnd.

I tried it on my end and this code did the trick :

var normalizeName = '';
if(typeof cssAPI.config.overrideNormalizeName != 'undefined')
   normalizeName = cssAPI.config.overrideNormalizeName;
else {
   var normalizeParts = req.toUrl('css').substr(baseUrl.length - 1).split('/');
   normalizeParts[normalizeParts.length - 1] = 'normalize';
   normalizeName = normalizeParts.join('/');
}

As usual look into it and if you think it's a good idea feel free to adapt it to your taste and needs :)

@import inlining

Hi! I'm having some issues trying to flatten a CSS file that includes @imports (so that the imports get inlined with the CSS) and at the same time using require-css optimizer to inject the file in the JS.

The optimized JS file still includes the @imports directives, but I think it should either inline them, or even better, require them so that there's a single declaration of the imported CSS in the JS output.

Is this possible? I read something about @import handling on css.js, but that doesn't seems to be used when building, right?

I'm guessing that maybe this might work out of the box when r.js runs over an entire appDir, but I need to run it over the individual files, since the project folders contains other stuff which I don't want r.js to touch.

Module Timeout cross-domain with FF

New version of master is breaking on one of my pages, but not the other. Still trying to figure it out. But:

'css!styles/jquery/plugins/jquery.tinyscrollbar.css' is timing out for me ( with or without the.css` )

It's spitting out a very strange stack with "_unnormalized" on it.
css-timeout

Any idea what would have changed in update?

Timeout issue with built version of code

Hi,

I'm having a problem getting this code to work when built via the Node/r.js build script.

Here is the example/demo project I'm working with: https://github.com/Integralist/RequireJS-CSS-Loader

The pre-build files /www/work fine, but the built version /www-built/ doesn't. Instead it executes the callback (as if the styles have been loaded) but it doesn't render the styles. Then after a few seconds the RequireJS timeout error appears in the console.

This happens regardless of whether the styles are inlined or kept external via the separateCSS option in the build script.

Would it be possible for you to take a quick scan through the example repo and let me know what the problem might be.

Thanks.

Loading Cross Domain

Not sure if this is a bug or not but requiring ['css!http://framework.jpillora.com/js/lib/prettify/prettify'], interprets it as script and does not work. Is there a way you can make cross domain paths just add the css as link tag with src tag, opposed to inserting the css contents into a style tag ?

Source maps for builds

Source maps would apply to separateCSS built CSS only (it is worth experimenting to see if style injection can be used with source maps, but I suspect not).

Then alongside the separate CSS file, a source map file would also have to be compiled and referenced with the source map comment at the end of the separate CSS file.

Suggestion: Improve Injection Method

Hey Guy,

I've posted an issue about CSS loading from external domains a while back, it's not an issue for me at the moment though maybe one day it will and I came across this today:
https://github.com/SlexAxton/yepnope.js/blob/master/plugins/yepnope.css.js
yepnope's method of injecting external CSS with a callback, heres the key to it:

      function poll() {
        try {
            var sheets = document.styleSheets;
            for(var j=0, k=sheets.length; j<k; j++) {
                if(sheets[j].ownerNode.id == id) {
                    // this throws an exception, I believe, if not full loaded (was originally just "sheets[j].cssRules;")
                    if (sheets[j].cssRules.length)
                        return onload();
                }
            }
            // if we get here, its not in document.styleSheets (we never saw the ID)
            throw new Error;
        } catch(e) {
            // Keep polling
            setTimeout(poll, 20);
        }
      }
      poll();

Just a heads up

Cheers
Jaime

adding to the buffer in an optimized file is not (always) synchronous

css-builder writes async requires to the output file to call addBuffer. This causes extra loads for the css files because modules that define the css file as a dependency are loaded before the async require executes.
I fixed it by wrapping the call to addBuffer in a define(), but I'm not sure if that's really the way to go.

cssAPI.write = function(pluginName, moduleName, write, extension, parse) {
  // ....
  if (separateCSS)
    //...
  else 
    write.asModule(pluginName + '!' + moduleName, 'define(function(){' + 
        'require("css").addBuffer("' + moduleName + (parse ? '.less", true' : '.css"') + ')' + 
    '})');
}

normalizeName in css-builder incorrect when require-css outside of baseUrl

My app directory structure goes something like this:


app/
    scripts/
    styles/
    vendor/
          /scripts
                 /require-css
build/
app.build.js

where in app.build.js I have something like (very much simplified):

({

    optimize: "none",

    appDir: "app",
    baseUrl: "scripts",
    mainConfigFile: 'app/scripts/main.js',
    dir: "build",

    paths: {
      'require-css':    '../vendor/scripts/require-css',
    },

    modules: [
      {
         name: 'main',
         excludeShallow: [
          'require-css/css-builder'
         ]
      }
    ]
})

And when I run the optimization tool, the path injected into my main.js file by css-builder is:

cripts/require-css/normalize

when it should be:

vendor/scripts/require-css/normalize

I discovered that this has to do with the following in css-builder:

//derive the absolute path for the normalize helper
var normalizeParts = req.toUrl('css').substr(baseUrl.length - 1).split('/');
normalizeParts[normalizeParts.length - 1] = 'normalize';
var normalizeName = normalizeParts.join('/');

which makes the assumption that the path to normalize (or rather, css) is going to be in baseUrl

I know that I could place my vendor directory in app/scripts but I have always preferred to place my vendor scripts outside of my app's scripts directory. The assumption that normalize is going to be in baseUrl prevents me from using the flexibility of the paths config option.

In the meantime, I have hacked together a solution (not worthy of a PR), but would love it if this issue was addressed.

Thanks for the great plugin!

Normalize re-mapping issue

I think there a cases where the url is mapped wrong. I've added debug logs to the convertURIBase func as shown below.

When optimizing via r.js it looks ok:

URI images/animated-overlay.gif
from D:/P4/Head/Java/build/app/lib/jquery-ui-theme/jquery-ui-1.10.1.custom.css
to   D:/P4/Head/Java/build/app/
res  lib/jquery-ui-theme/images/animated-overlay.gif

but when loading the optimized result in the browser the paths are re-mapped with "../lib"

URI lib/jquery-ui-theme/images/animated-overlay.gif
from /mywebcontext/build/app
to   /mywebcontext/build/app/
res  ../lib/jquery-ui-theme/images/animated-overlay.gif

My guess is that it is due to the '/' at the end of the toBase.

// given a relative URI, and two absolute base URIs, convert it from one base to another
  function convertURIBase(uri, fromBase, toBase) {
    uri = removeDoubleSlashes(uri);
    // absolute urls are left in tact
    if (uri.match(/^\/|([^\:\/]*:)/))
      return uri;

    console.log("URI " + uri);
    console.log("from " + fromBase);
    console.log("to   " + toBase);


    var res = relativeURI(absoluteURI(uri, fromBase), toBase);
    console.log("res  " + res);
    return res;
  };

Gruntjs integration fails optimizing requirejs + require-css

I'm using the requirejs plugin for grunt (grunt-contrib-requirejs, version 0.4.0 and r.js version 2.1.5).

It was working when I was optimizing my JS files, but then I integrated require-css and the build gives this error:

Fatal error: Load timeout for modules: env!env/file,env!env/optimize,env!env/quit
http://requirejs.org/docs/errors.html#timeout

I followed the instructions and it works without optimization. However, when I try to optimize it, the CSS file is generated, but this error is triggered.

After build, both link and inline css are injected

After I've built the two layers of my application, the css is properly injected inline into the page, but it is also injecting the link tags. This obviously defeats the benefits of having the code injected. Can you think of a reason why it would still be injecting the link tags after build?

I can provide my build file or any other information if that might help.

Thanks!

question: basePath for url resolution

Hi,
I cannot figure out how to provide a basePath for resolution of relative urls in the stylesheet. In css.api.js you write:
//CSS paths are normalized based on an optional basePath and the requirejs config
//If a basePath is provided, this is assumed to specify the location of the css root
Just how do I supply a basePath?
Many thanks in advance,
Joop

Flattr

This is super useful. Thank you. Would be nice if you had a flattr button. :)

separateCss comportement is a bit strange with modules

I'm working on the rhino implementation for separateCSS but when I tried to make it work I found the comportement of the option a bit strange.

I have modules but wanted all of them to have separate css so I put the option in the global section of the build configuration.

But it did not work because when you have modules you seem to expect if to be present inside each module configuration.

I propose to take by default the config and override it if it's defined inside the module.

the code would be :

if (typeof curModule == 'number' && typeof cssAPI.config.modules[curModule].separateCSS !== 'undefined')
            separateCSS = cssAPI.config.modules[curModule].separateCSS;

I tested it it seems to work fine.

Even better to be fully in the spirit of require it should be :

if (typeof curModule == 'number'
        && typeof cssAPI.config.modules[curModule].override !== 'undefined'
        && typeof cssAPI.config.modules[curModule].override.separateCSS !== 'undefined')
            separateCSS = cssAPI.config.modules[curModule].override.separateCSS;

Because this is the way they override global config for a specific module in the main project.

I tested only on rhino and I don't know if it's what you wanted to do or not.

I'm still working on the rhino implementation after that but it should be ready soon :)

Optimizer not working with Rhino

The optimizer process was not working with rhino and after investigating the problem it was on the java code used to read the css file.

It seems you copied it from the text plugin but did not adapt it to your need.

So I did and the resulting block for the loadFile function :

var encoding = "utf-8",
       file = new java.io.File(path),
       lineSeparator = java.lang.System.getProperty("line.separator"),
       input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
       stringBuffer, line;
try {
    stringBuffer = new java.lang.StringBuffer();
    line = input.readLine();
   if (line && line.length() && line.charAt(0) === 0xfeff)
       line = line.substring(1);
   stringBuffer.append(line);
   while ((line = input.readLine()) !== null) {
      stringBuffer.append(lineSeparator).append(line);
   }
   return String(stringBuffer.toString());
}
finally {
   input.close();
}

Basicly you just needed to return the content of the StringBuffer instead of putting it in content and doing nothing with it :)

If I have time later I will also check what you tried to do with the javacode for separateCss (or even better give me the algorythm and I will implement it in Java) as I am a Java developper it should be easy and might help some other fellas ;)

resolving file's relative parent path during optimization

I am able to build just fine when referencing css files that are children of the current directory (i.e. css!css/core). However, If I try to access a css folder that's a child of the parent directory it fails (i.e. css!../css/core).

My current setup:
/MyApp/css
/MyApp/css/core.css
/MyApp/js
/MyApp/js/example.js

When I try to build referencing a css file, it ends up resolving the url to the actual location of the plugin. So when I try to build referencing 'css!../css/core' from example.js, instead of resolving to /MyApp/css/core.css it resolves to /MyApp/js/lib/require/plugins/require-css/css/core.css and fails because that file does not exist.

Any thoughts on why this might be happening? I've tried it with my baseUrl at both /MyApp (css!css/core.css) and at /MyApp/js (css!../css/core.css) and both tried to resolve to the plugin folder instead of the actual file.

require-css not compatible with @import's on firefox

If I have 2 files with @imports inside them, the tag will contain @imports in the middle of the aggregated css declarations.

This doesn't work well for firefox because firefox (and possible other browsers) only interpret them if they are the first declarations within the stylesheet.

This would be resolved automatically if #10 is done.

bower issues

I've been installing your plugin through bower and using:

bower install git://github.com/guybedford/require-css.git

But a couple of hours ago you added a component.json which have been causing issues for me. I'm accually using require-less but I believe the issues originates from here.

$ bower install git://github.com/guybedford/require-less.git
bower cloning git://github.com/guybedford/require-less.git
bower caching git://github.com/guybedford/require-less.git
bower fetching require-less
bower checking out require-less#c2f29278f95b1152150220b5bbf1a2721f3a51f7
bower cloning git://github.com/guybedford/require-css.git
bower caching git://github.com/guybedford/require-css.git
bower fetching css
bower error Could not find tag satisfying: css#0.0.1

There were errors, here's a summary of them:
- css Could not find tag satisfying: css#0.0.1
The tag 0.0.1 could not be found within the repository

really not sure why it is doing that though. css isn't a dependency. maybe the name must correlate with the repo name.. Or maybe it's an issue with bower, there seems to exist a couple of them.. :(

Replace browser detection with engine detection

Using engine detection we can target the following environments:

This covers all engines and would provide comprehensive support using the <link> load method, allowing the <style> injection to be deprecated.

Double quotes not escaping

I have double quotes in my styles, like this:

font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;

And in result build module they are saved, breaking resulting string, that wrapped in double quotes.
But single quotes was escaped :)

Multiple slashes in URLs breaks path normalisation

If a page is loaded with additional slashes in the URL, e.g.
http://www.example.com/path//to////page.html

And that page then implements require-css to load CSS with relative url()'s, the normalised paths are incorrect.

I believe this happens because of the various places where the URLs get .split('/'), because

"/path//to////page.html".split('/') = ["", "path", "", "to", "", "", "", "page.html"]

and those extra empty parts end up confusing the normalisation process.

The fix most apparent to me is to simply reduce multiple slashes down to a single slash. I've done this by modifying the start of normalize.js to:

define(['require', 'module'], function(require, module) {

  var slashes = /\/+/g;

  function convertURIBase(uri, fromBase, toBase) {

    // Fix any double-slashing
    uri = uri.replace(slashes, '/');
    fromBase = fromBase.replace(slashes, '/');
    toBase = toBase.replace(slashes, '/');

I feel this is a valid use-case, even if strictly speaking the double-slashed URI is invalid, as most browsers/servers will honour this request and serve the page up, however the scripts will fail to run properly due to the broken path(s).

r.js optimised code may not correctly normalise paths

I've been having some strange issues with path normalisation after running files through r.js and inlining CSS.

I have a JS file with inlined CSS which is at a URL like:
http://host/~djessup/assets/themes/default/js/script.js

The original CSS location is:
http://host/~djessup/assets/themes/default/css/components/script.css

The CSS includes url()'s with relative paths to images such as:
http://host/~djessup/assets/themes/lib/img/image.jpg (so the relative URL is ../../../lib/img/image.jpg)

Everything works fine pre-requirejs optimisation, but after optimising the paths get mangled and come out as:
http://host/djessup/assets/themes/lib/image.jpg (note the missing ~).

After a bit of poking around, the issue seems to relate to the relativeURI() function, which was showing the following input/output:
INPUT URI: ~djessup/assets/themes/lib/img/image.jpg BASE: /~djessup/
OUTPUT ../../djessup/assets/themes/lib/img/image.jpg

The comments on relativeURI() seem to suggest that it expects to receive a doc-root relative URL (i.e. one which starts with a /) but clearly isn't in this case. I notice that lines 140/141 in css.js appear to be trying to make sure URLs passed into normailze.js do always start with a /, but optimised code bypasses this process as far as I'm aware.

I've been able to "fix" this for my purposes by adding these lines to the beginning of normalizeCSS()
//make base url absolute
if (fromBase.substr(0, 1) != '/')
fromBase = convertURIBase( '/' + fromBase, toBase, '/');

However I'm conscious that I may be misunderstanding how this process is supposed to work, and may not be the "right" way to fix this issue.

I hope that makes sense - let me know if you need more details.

Normalization is not working properly in my use case

I'm using a folder structure like this:

app
  bootstrap.js -> contains the requirejs config
  // config files
src
  // source files
vendor
  // external lib files
web
  dev
    root -> (symlink to root project folder)
    // index.html and other files
  prod
    // index.html and other files
    // contains all concatenated and minified files

The dev index.html file includes the bootstrap.js file which has the following configuration:

// Loader configuration
requirejs.config({
    baseUrl: './root/src',
    // Other things
    packages: [
        // css plugin
        {
            name: 'css',
            location: '../vendor/require-css',
            main: 'css'
        }
});

The css's mentioned in @imports where not translated correctly.
If I just return the uri param in relativeURI function, everything works correctly:

  function relativeURI(uri, base) {
     return uri;
  }

I can give you access to project where this happens if necessary.

Build error on windows

In my module I do this:

require([
    'domReady!',
    'jquery',
    'css!/style/main'
], function (domReady, $){

// some code

});

And it's work fine.
But when I try to build this with r.js, just getting error

Error: Error: ENOENT, no such file or directory 'c:\style\main.css'
    at Object.fs.openSync (fs.js:338:18)

    at build (c:\_PROJS\old\node_modules\requirejs\bin\r.js:14100:23)
    at requirejs.optimize.runBuild (c:\_PROJS\old\node_modules\requirejs\bin\r.js:15301:30)
    at Object.context.execCb (c:\_PROJS\old\node_modules\requirejs\bin\r.js:1789:33)
    at Object.Module.check (c:\_PROJS\old\node_modules\requirejs\bin\r.js:1090:51)
    at Object.Module.enable (c:\_PROJS\old\node_modules\requirejs\bin\r.js:1331:22)
    at Object.Module.init (c:\_PROJS\old\node_modules\requirejs\bin\r.js:989:26)
    at Object.context.require (c:\_PROJS\old\node_modules\requirejs\bin\r.js:1591:28)
    at requirejs (c:\_PROJS\old\node_modules\requirejs\bin\r.js:1873:24)
    at Function.requirejs.optimize (c:\_PROJS\old\node_modules\requirejs\bin\r.js:15311:13)
    at c:\_PROJS\old\build.js:67:15

All build config had worked before css including

normalization breaks data URIs

Currently double slashes are removed from URI regardless of the type of the URI.

We use CSS files with base 64 encoded images included as data URI. The normalization will change double or triple slashes in the base 64 encoded image to a single slash, resulting in broken images.

poor performance for big buffers

When using an optimized build, all css / less is injected into one big style element, this causes ie 8 to hang when a lot of css is used. We also notice a 'flickering' in Chrome when loading, I assume this is caused by overwriting the style element contents (the browser needs to reapply all styles instead of just calculating the changes caused by the new buffer).
Locally solved / worked around this by injecting a style element per buffer.

Some numbers:
cssAPI.inject is called 5 times with a total of 275761 characters.

Does not wait for load when using http:

I have a popup that opens after a require call to JS and CSS files. With an empty cache, on first run, my JS will never see there is padding on my elements from my callback. Re-opening the popup will work everytime after since the CSS is now on the page.

Before using a "real" autoloader I had my own code for CSS. If nothing has changed too much, I remember FireFox being hard to work with. I needed to make a tag, set its textContent to the import of the href, and then use an interval to wait for link.sheet.cssRules to exist.

It was something hideous like this:

firefox_interval = setInterval( function() {

  try {
    link.sheet.cssRules; // <--- MAGIC: only populated when file is loaded
    fileLoaded();
  } catch (e) {}

}, 10 );

Bug in Opera

There is a bug that prevents the plug-in from working in Opera. The code creates a variable called "agentMatch", which is always null in Opera, so the following line blows up:

var useLinks = (browserEngine && (parseInt(agentMatch[4]) > 5 || parseInt(agentMatch[3]) > 8 || parseInt(agentMatch[2]) > 9 || parseInt(agentMatch[1]) > 18)) || undefined;

Problem with the normalization and absolute URLS

Hello,

since you corrected the bug for android 2.1 (thanks a lot) I wanted to update but ran into a bug in the URL normalization process that I didn't have before (My former version is from last week).

I put some output in the convertURIBase method to see what happened and got this result :

uri : ../../css/images/icons-36-white.png
fromBase : //mob-web/mob/common/css/jquery.mobile-1.2.0.min.css
toBase : /mob-web/mob/
absoluteURI return : //mob-web/mob/css/images/icons-36-white.png
relativeURI returns : ../..

Therefore my image becomes ../.. and is not found.

I tracked down the problem to the line :

fileUrl = '/' + normalize.convertURIBase(fileUrl, pathname, '/');

If I delete the first '/' everything works fine. I think you need to only add it if the returned URL is not already absolute to avoid the double / in the fromBase.

Thank you again for your great work!

Problem in normalizeCSS

Hello,

I localized the problem to the following code snippets based on the normalizeCSS code.

In the following snippet, css contains two the same urls, the first one is processed twice, the second one is not processed at all.

var source = 'url(a.png)\nurl(a.png)'; // two the same urls
urlRegEx = /(url\(\s*"(.*)"\s*\))|(url\(\s*'(.*)'\s*\))|(url\(\s*(.*)\s*\))/g;
while (result = urlRegEx.exec(source)) {
  url = 'lib/path/' + (result[2] || result[4] || result[6]); // convertURIBase(result[2] || result[4] || result[6], fromBase, toBase);
  source = source.replace(result[2] || result[4] || result[6], url);
}
console.log(source);

Result:

url(lib/path/lib/path/a.png)
url(a.png)

In the following snippet, the only difference is more long prefix 'lib/long-long-path/'.

var source = 'url(a.png)\nurl(a.png)';
urlRegEx = /(url\(\s*"(.*)"\s*\))|(url\(\s*'(.*)'\s*\))|(url\(\s*(.*)\s*\))/g;
while (result = urlRegEx.exec(source)) {
  url = 'lib/long-long-path/' + (result[2] || result[4] || result[6]); // convertURIBase(result[2] || result[4] || result[6], fromBase, toBase);
  source = source.replace(result[2] || result[4] || result[6], url);
}
console.log(source);

Result: it hangs.

Thank you

Load imports as CSS dependencies via sub-requires

Still considering the value of this approach, but as discussed in #9, this could be a useful feature for allowing imports to act as CSS dependency specifications.

Basically, the parser would determine the import array, normalized to the baseUrl (which is done anyway), then run a require to this import array before injecting the current css, remove the imports from the css and then perform injection.

CSS ordering

The load order of JS modules follows the dependency chain which is fine since we have a callback mechanism. The same can be a problem for CSS files since the order allows you to override and extend the previously loaded definitions.

When a moduleA requires a CSS file and depends on another moduleB that also requires a CSS file then they are included in the following order: moduleA, moduleB. In my case moduleB is a core module that loads a reset CSS that we may potentially want to override from depending modules.

Any thoughts? As a workaround I may end up using extra class names so that I don't have to override the existing definitions.

Normalize doesn't work for multiple URLs per line

I have the following CSS rule (for a font-icon style thing):

@font-face {
  font-family: 'Splunk Icons';
  src: url('../fonts/splunkicons-regular-webfont.eot');
  src: url('../fonts/splunkicons-regular-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/splunkicons-regular-webfont.woff') format('woff'), url('../fonts/splunkicons-regular-webfont.ttf') format('truetype'), url('../fonts/splunkicons-regular-webfont.svg#EntypoRegular') format('svg');
  font-weight: normal;
  font-style: normal;/*    unicode-range: U+00-FF;*/
}

Unfortunately, require-css is choking on this in a weird way. Here is the input and output from relativeURI:

URI: static/appfx/fonts/splunkicons-regular-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/splunkicons-regular-webfont.woff') format('woff'), url('../fonts/splunkicons-regular-webfont.ttf') format('truetype'), url('../fonts/splunkicons-regular-webfont.svg#EntypoRegular') format('svg
Base: webfx/
Output: ../static/appfx/fonts/splunkicons-regular-webfont.eot?#iefix') format('embedded-opentype'), url('../fonts/splunkicons-regular-webfont.woff') format('woff'), url('../fonts/splunkicons-regular-webfont.ttf') format('truetype'), url('../fonts/splunkicons-regular-webfont.svg#EntypoRegular') format('svg

As you can see, only the first URL is changed. However, if I split the above rule into multiple lines, everything works fine.

normalize.css exposes a lot of global variables

I got a bug in my site when I inadvertently exposed a variable called "url" as global and found out that it was overwritten by normalize.js since almost all your variables declarations are missing the var keyword and seems to be exposed as globals.

I don't know if it's voluntary since it's not the case in css.js where everything has the right scope.

Strangely, I didn't get the error when I was running with optimized code.

External timeouts on mobile browsers

Okay so I still have forceLinks config as true since my last FF 17 restarted to 18 this week.

I then got word that the CSS loader is failing for external links on droids and the kindle fire.

I downloaded the latest css.js and took the config out and am still getting a timeout. Any ideas?

innerHtml doesn't work well on Android 2.1

Hello,

I had a problem on Android 2.1 and tracked it down to the line 78 where you set the innerHtml of the style tag.

It seems android 2.1 doesn't support that.

I changed the code with :

if (stylesheet.styleSheet)
   cssAPI.inject = function(css) {
      stylesheet.styleSheet.cssText += css;
   }
else if(stylesheet.innerHTML)
   cssAPI.inject = function(css) {
      stylesheet.innerHTML += css;
   }
else
   cssAPI.inject = function(css) {
      var cssNode = document.createTextNode(css);
      stylesheet.appendChild(cssNode);
   }

And it solved my problem. I cannot do a pull request because my work's firefall is a bit too stuborn!

I have no idea what colateral damages my code could cause so I just give it to you for consideration ;)

I stole the solution from there : http://stackoverflow.com/questions/5969368/javascript-injection-problem-in-android-2-1-emulator-but-fine-in-2-2

Best regards,

Mathieu

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.