Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

get-css-data

jhildenbiddle264.4kMIT2.1.0

A micro-library for collecting stylesheet data from link and style nodes

ajax, component, css, cssom, csstext, custom properties, custom property, custom, dom, es6, iframe, import, javascript, js, legacy, link, module, root, runtime, shadow dom, shadow root, shadow, shadowroot, style, stylesheet, web component, web, xhr

readme

get-css-data

NPM GitHub Workflow Status (master) Codacy code quality Codacy branch coverage License: MIT Tweet

A micro-library for collecting stylesheet data from link and style nodes.



Features

  • Collects CSS data from <link> and <style> nodes
  • Collects static Node.textContent or live CSS Object Model (CSSOM) data
  • Returns CSS data as a concatenated string and a DOM-ordered array of strings
  • Allows document, iframe, and shadow DOM traversal
  • Handles @import rules
  • Handles absolute and relative URLs
  • Inspect, modify and/or filter CSS data from each node
  • Modify XHR object before each request
  • UMD and ES6 modules available
  • Compatible with modern and legacy browsers (IE9+)
  • Lightweight (less than 1.5k min+gzip) and dependency-free

Installation

NPM:

npm install get-css-data --save
// file.js
import getCssData from 'get-css-data';

getCssData({
  onComplete: function(cssText, cssArray, nodeArray) {
    // Do stuff...
  }
});

Git:

git clone https://github.com/jhildenbiddle/get-css-data.git

CDN (jsdelivr.com shown, also on unpkg.com):

<!-- ES5 (latest v2.x.x) -->
<script src="https://cdn.jsdelivr.net/npm/get-css-data@2"></script>
<script>
  getCssData({
    onComplete: function(cssText, cssArray, nodeArray) {
      // Do stuff...
    }
  });
</script>
<!-- ES6 module (latest v2.x.x) -->
<script type="module">
  import getCssData from 'https://cdn.jsdelivr.net/npm/get-css-data@2/dist/get-css-data.esm.min.js';

  getCssData({
    onComplete(cssText, cssArray, nodeArray) {
      // Do stuff...
    }
  });
</script>

Example

HTML:

<!-- file.html -->
<head>
  <link rel="stylesheet" href="style1.css">
  <style>
    @import "style2.css";
    p { color: blue; }
  </style>
</head>

CSS:

/* style1.css */
p { color: red; }
/* style2.css */
p { color: green; }

JavaScript (see Options for details)

getCssData({
  onComplete: function(cssText, cssArray, nodeArray) {
    console.log(cssText); // 1
    console.log(cssArray); // 2
    console.log(nodeArray); // 3
  }
});

// 1 => 'p { color: red; } p { color: green; } p { color: blue; }'
// 2 => ['p { color: red; }', 'p { color: green; } p { color: blue; }']
// 3 => [<linkElement>, <styleElement>]

Options

Example

// Default values shown
getCssData({
  rootElement : document,
  include     : 'link[rel=stylesheet],style',
  exclude     : '',
  filter      : '',
  skipDisabled: true,
  useCSSOM    : false,
  onBeforeSend: function(xhr, node, url) {
    // ...
  },
  onSuccess: function(cssText, node, url) {
    // ...
  },
  onError: function(xhr, node, url) {
    // ...
  },
  onComplete: function(cssText, cssArray, nodeArray) {
    // ...
  }
});

options.rootElement

  • Type: object
  • Default: document

Root element to traverse for <link> and <style> nodes.

Examples

// Document
getCssData({
  rootElement: document // default
});

// Iframe (must be same domain with content loaded)
getCssData({
  rootElement: (myIframe.contentDocument || myIframe.contentWindow.document)
});

// Shadow DOM
getCssData({
  rootElement: myElement.shadowRoot
});

options.include

  • Type: string
  • Default: "link[rel=stylesheet],style"

CSS selector matching <link> and <style> nodes to collect data from. The default value includes all style and link nodes.

Example

getCssData({
  // Include only <link rel="stylesheet"> nodes
  // with an href that does not contains "bootstrap"
  include: 'link[rel=stylesheet]:not([href*=bootstrap])',
});

options.exclude

  • Type: string

CSS selector matching <link> and <style> nodes to exclude from those matched by options.include.

Example

getCssData({
  // Of matched `include` nodes, exclude any node
  // with an href that contains "bootstrap"
  exclude: '[href*=bootstrap]',
});

options.filter

  • Type: object

Regular expression used to filter node CSS data. Each block of CSS data is tested against the filter, and only matching data is processed.

Example

getCssData({
  // Test each block of CSS for the existence
  // of ".myclass". If found, process the CSS.
  // If not, ignore the CSS.
  filter: /\.myclass/,
});

options.skipDisabled

  • Type: boolean
  • Default: true

Determines if disabled stylesheets will be skipped while collecting CSS data.

Example

getCssData({
  skipDisabled: true // default
});

options.useCSSOM

  • Type: boolean
  • Default: false

Determines how CSS data will be collected from <style> nodes.

When false, static CSS data is collected by reading each node's textContent value. This method is fast, but the data collected will not reflect changes made using the deleteRule() or insertRule() methods. When true, live CSS data is collected by iterating over each node's CSSRuleList and concatenating all CSSRule.cssText values into a single string. This method is slower, but the data collected accurately reflects all changes made to the stylesheet.

Keep in mind that browsers often drop unrecognized selectors, properties, and values when parsing static CSS. For example, Chrome/Safari will drop declarations with Mozilla's -moz- prefix, while Firefox will drop declarations with Chrome/Safari's -webkit prefix . This means that data collected when this options is set to true will likely vary between browsers and differ from the static CSS collected when it is set to false.

Example

getCssData({
  useCSSOM: false // default
});

options.onBeforeSend

  • Type: function
  • Arguments:
    1. xhr: The XHR object containing details of the request
    2. node: The source node object reference
    3. url: The source URL string (<link> href or @import url)

Callback before each XMLHttpRequest (XHR) is sent. Allows modifying the XML object by setting properties, calling methods, or adding event handlers.

Example

getCssData({
  onBeforeSend: function(xhr, node, url) {
    // Domain-specific XHR settings
    if (/some-domain.com/.test(url)) {
      xhr.withCredentials = true;
      xhr.setRequestHeader("foo", "1");
      xhr.setRequestHeader("bar", "2");
    }
  }
});

options.onSuccess

  • Type: function
  • Arguments:
    1. cssText: A string of CSS text from node and url
    2. node: The source node object reference
    3. url: The source URL string (<link> href, @import url, or page url for <style> data)

Callback after CSS data has been collected from each node. Allows modifying the CSS data before it is added to the final output by returning any string value or skipping the CSS data by returning false or an empty string ("").

Note that the order in which <link> and @import CSS data is "successfully" collected (thereby triggering this callback) is not guaranteed as these requests are asynchronous. To access CSS data in DOM order, use the cssArray argument passed to the options.oncomplete callback.

Example

getCssData({
  onSuccess: function(cssText, node, url) {
    // Replace all instances of "color: red" with "color: blue"
    const newCssText = cssText.replace(/color:\s*red\s;/g, 'color: blue;');

    return newCssText;
  }
});

options.onError

  • Type: function
  • Arguments:
    1. xhr: The XHR object containing details of the request
    2. node: The source node object reference
    3. url: The source URL string (<link> href or @import url)

Callback after <link> or @import request has failed or when xhr.responseText appears to be HTML instead of CSS.

Example

getCssData({
  onError: function(xhr, node, url) {
    console.log(xhr.status); // 1
    console.log(xhr.statusText); // 2
  }
});

// 1 => '404'
// 2 => 'Not Found'

options.onComplete

  • Type: function
  • Arguments:
    1. cssText: A string of concatenated CSS text from all nodes in DOM order.
    2. cssArray: An array of per-node CSS text in DOM order. The node containing each CSS text block is available at the same nodeArray index.
    3. nodeArray: An array of processed <style> and <link> nodes in DOM order. The CSS text for each node is available at the same cssArray index.

Callback after CSS data has been collected from all nodes.

Example

getCssData({
  onComplete: function(cssText, cssArray, nodeArray) {
    // ...
  }
});

Contact

License

This project is licensed under the MIT License. See the LICENSE for details.

Copyright (c) John Hildenbiddle (@jhildenbiddle)

changelog

Change Log

2.1.0

2022-04-21

  • Add support for <link> elements using data URIs

2.0.2

2021-03-16

  • Fix empty <link> stylesheet triggering onError() callback

2.0.1

2021-01-30

  • Update version number in CDN URLs

2.0.0

2021-01-30

  • Remove nodes skipped during onSuccess() from onComplete() arguments
  • Support XHR status < 400 for file:// URLs
  • Remove distributable files from version control

1.9.1

2020-11-20

  • Fix detection of SVG <style> nodes

1.9.0

2020-10-30

  • Add support for file:// URLs from local files on supporting browsers

1.8.0

2020-04-26

  • Add options.skipDisabled which determines if disabled stylesheets will be skipped while collecting CSS data.

1.7.1

2020-02-15

  • Restore babel transpilation for ES modules (removed in 1.7.0)

1.7.0

2020-02-12

  • Add support for HTML <base> tag (#3)
  • Remove babel transpilation for ES modules

1.6.3

2019-01-30

  • Fix IE9 CORS check

1.6.2

2019-01-09

  • Update preferred CDN link to jsdelivr.

1.6.1

2018-11-14

  • Fix bug that prevented IE10 from fetching <link> CSS data from external domains.

1.6.0

2018-11-12

  • Update options.onSuccess callback to better handle falsey return values (e.g. false, null, 0, "").

1.5.0

2018-11-11

  • Add check to prevent HTML returned from stylesheet 404 redirects from being processed as CSS.

1.4.0

2018-09-28

  • Add options.rootElement for specifying the root element to traverse for <link> and <style> nodes.

  • Add options.useCSSOM to determine if CSS data should be collected from CSSRule.cssText or Node.textContent values.

1.3.2

2018-05-17

  • Fix options.onSuccess bug that resulted in a return value not being processed instead of the original cssText.

  • Fix options.onSuccess behavior so that it is triggered for each @import (was only being triggered for <link> nodes).

1.3.1

2018-05-16

  • Add options.onBeforeSend callback.

  • Fix @import bug that caused duplicate requests to be sent when fetching multiple imports in the same file.

  • Fix @import bug that caused requests to fail when fetching multiple imports from different directories in the same file.

1.2.0

2018-04-23

  • Fix bug that caused callbacks to be triggered for each @import statement in each <link> or <style> node.

1.1.4/1.1.5

2018-04-21

  • Update README

1.1.3

2018-04-21

  • Update dev dependencies

  • Update rollup configuration

  • Update README

1.1.2

2018-01-31

  • Update dev dependencies

  • Update rollup configuration

  • Update README

1.1.1

2018-01-20

  • Update README

1.1.0

2018-01-18

  • Fix: style and link nodes that triggered an onError callback due to a failed @import would result in an empty string being added to the cssText and cssArray arguments of the options.onComplete callback. The original css text (with the unresolved @import statement) is now added as expected.

  • Update: An array of nodes is now passed to options.onComplete as the third argument. The CSS text for each node is available at the same cssArray index (the second argument).

1.0.2

2018-01-17

  • Fix: onComplete callback now fires when zero elements are matched by options.include.

1.0.1

2018-01-17

  • Fix: RegEx detection of @import URLs. Previous RegEx did not account for all valid URL characters. New RegEx captures all @import URL characters between single or double quotes.

  • Update: unminified dist files now include JSDOC comments. This allows documentation to be displayed in IDEs.

1.0.0

2018-01-16

  • Initial release