/* Static Methods */
/**
- * Gets a list of local file paths which are referenced in a CSS style sheet
+ * Gets a list of local file paths which are referenced in a CSS style sheet.
*
- * This function will always return an empty array if the second parameter is not given or null
- * for backwards-compatibility.
+ * If you wish non-existent files to be listed too, use getAllLocalFileReferences().
*
- * @param string $source CSS data to remap
- * @param string $path File path where the source was read from (optional)
+ * For backwards-compatibility, if the second parameter is not given or null,
+ * this function will return an empty array instead of erroring out.
+ *
+ * @param string $source CSS stylesheet source to process
+ * @param string $path File path where the source was read from
* @return array List of local file references
*/
public static function getLocalFileReferences( $source, $path = null ) {
return array();
}
+ $files = self::getAllLocalFileReferences( $source, $path );
+
+ // Skip non-existent files
+ $files = array_filter( $files, function ( $file ) {
+ return file_exists( $file );
+ } );
+
+ return $files;
+ }
+
+ /**
+ * Gets a list of local file paths which are referenced in a CSS style sheet, including
+ * non-existent files.
+ *
+ * @param string $source CSS stylesheet source to process
+ * @param string $path File path where the source was read from
+ * @return array List of local file references
+ */
+ public static function getAllLocalFileReferences( $source, $path ) {
+ $stripped = preg_replace( '/' . self::COMMENT_REGEX . '/s', '', $source );
$path = rtrim( $path, '/' ) . '/';
$files = array();
$rFlags = PREG_OFFSET_CAPTURE | PREG_SET_ORDER;
- if ( preg_match_all( '/' . self::URL_REGEX . '/', $source, $matches, $rFlags ) ) {
+ if ( preg_match_all( '/' . self::URL_REGEX . '/', $stripped, $matches, $rFlags ) ) {
foreach ( $matches as $match ) {
$url = $match['file'][0];
break;
}
- $file = $path . $url;
- // Skip non-existent files
- if ( file_exists( $file ) ) {
- break;
- }
-
- $files[] = $file;
+ $files[] = $path . $url;
}
}
return $files;
return false;
}
+ /**
+ * Serialize a string (escape and quote) for use as a CSS string value.
+ * http://www.w3.org/TR/2013/WD-cssom-20131205/#serialize-a-string
+ *
+ * @param string $value
+ * @return string
+ * @throws Exception
+ */
+ public static function serializeStringValue( $value ) {
+ if ( strstr( $value, "\0" ) ) {
+ throw new Exception( "Invalid character in CSS string" );
+ }
+ $value = strtr( $value, array( '\\' => '\\\\', '"' => '\\"' ) );
+ $value = preg_replace_callback( '/[\x01-\x1f\x7f-\x9f]/', function ( $match ) {
+ return '\\' . base_convert( ord( $match[0] ), 10, 16 ) . ' ';
+ }, $value );
+ return '"' . $value . '"';
+ }
+
/**
* @param $file string
* @return bool|string
// Check for global @embed comment and remove it. Allow other comments to be present
// before @embed (they have been replaced with placeholders at this point).
$embedAll = false;
- $rule = preg_replace( '/^((?:\s+|' . CSSMin::PLACEHOLDER . '(\d+)x)*)' . CSSMin::EMBED_REGEX . '\s*/', '$1', $rule, 1, $embedAll );
+ $rule = preg_replace(
+ '/^((?:\s+|' .
+ CSSMin::PLACEHOLDER .
+ '(\d+)x)*)' .
+ CSSMin::EMBED_REGEX .
+ '\s*/',
+ '$1',
+ $rule,
+ 1,
+ $embedAll
+ );
// Build two versions of current rule: with remapped URLs
// and with embedded data: URIs (where possible).