- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 php 元素,它使用 grunt 将 sass 文件编译成 css。我想知道是否有一种类似于 Google 的 Closure Stylesheets 的 css 类重命名方法.所以这实际上是一个由两部分组成的问题:
据我所知,sass 目前没有任何类似的功能,除非它可以作为扩展添加。但是使用 grunt 我可以先编译 sass 文件,然后运行另一个任务来重命名类并输出一个映射文件。从技术上讲,我可以为此使用 Closure Stylesheets,但我正在寻找不需要安装其他依赖项的更轻量级的东西。
现在我可以为每个 css 类插入类似这样的内容:<?php echo getclassname("some-class-name") ?>
这将引用上面生成的映射文件以获得正确的类名。但这似乎很乏味。有更好的方法吗?
最佳答案
首先编译 sass,然后通过自定义任务传递它以重命名类。我正在使用 css节点模块来解析css。让我们从查看自定义 grunt 任务开始。
免责声明:我快速编写了这段代码,因此它可能尚未准备好投入生产。
var fs = require( 'fs' ),
rename = require( './rename.js' );
// Register the rename_css task.
grunt.registerMultiTask('rename_css', 'Shorten css class names', function () {
var options = this.options(); // Pass all options directly to css.parse
this.files.forEach(function ( file ) {
var renamed = rename.rename(
fs.readFileSync( file.src[ 0 ], 'utf8' ), options );
fs.writeFileSync( file.dest, renamed.text );
fs.writeFileSync( file.map, JSON.stringify( renamed.map, null, 2 ) );
});
});
此任务的配置如下所示:
grunt.initConfig({
rename_css: {
options: { compress: true }, // Minify the output css.
main: {
src: "style.css",
dest: "style.min.css",
map: "map.json"
}
}
});
rename.js 太长,无法在此处全部显示,但您可以在 github 上查看整个文件.这是主要功能:
function rename( s, options /* passed directly to css.parse */ ) {
/**
* Give the css classes short names like a-b instead of some-class
*
* Returns an object in the form {text: `newCss`, map: `partsMap`} whare text is
* the newly generated css and partsMap is a map in the {oldPart: newPart}.
*/
var
ast = css.parse( s, options ),
countMap = walkPass1( ast.stylesheet ), // Walk the first pass.
sortedCounts = [],
map = {}, // Final map.
part,
// List of charictor positions for the short class names.
// Each number corresponds to a charictor in the `chars` string.
charPosSet = [ 0 ];
// Unpack the count map.
for ( part in countMap ) {
sortedCounts.push({
name: part,
count: countMap[ part ],
replacment: undefined
});
}
// Sort based on the number of counts.
// That way we can give the most used classes the smallest names.
sortedCounts.sort(function( a, b ) { return b.count - a.count });
// Generate the small class names.
sortedCounts.forEach(function ( part ) {
var
s = '',
i = charPosSet.length;
// Build up the replacment name.
charPosSet.forEach(function ( pos ) {
s += chars[ pos ];
});
while ( i-- ) {
charPosSet[ i ]++;
// If the current char pos is greater then the lenght of `chars`
// Then we set it to zero.
if ( charPosSet[ i ] == chars.length ) {
charPosSet[ i ] = 0;
if ( i == 0 ) { // Time to add another digit.
charPosSet.push( 0 ); // The next digit will start at zero.
}
} else {
// Everything is in bounds so break the loop.
break;
}
}
part.replacment = s;
});
// Now we pack a basic map in the form of old -> new.
sortedCounts.forEach(function ( part ) {
map[ part.name ] = part.replacment;
});
// Walk the tree a second time actually renameing the classes.
walkPass2( ast.stylesheet, map );
return {
text: css.stringify( ast, options ), // Rebuild the css.
map: map
};
}
它看起来很复杂,但这里是它正在做的分解:
值得指出的是,这个函数会给更频繁使用的类更短的名字,这将导致 css 文件略小。
这可以通过输出缓冲区来完成。它可能看起来像这样(在根 html
标记之前的页面顶部):
<?php
define(DEV_MODE, false);
function build_class( $name, $map ) {
$parts = [];
foreach ( explode( '-', $name ) as $part ) {
$newPart = array_key_exists( $part, $map )? $map[ $part ] : $part;
array_push( $parts, $newPart );
}
return implode( '-', $parts );
}
function class_rename ( $content ) {
$string = file_get_contents( 'map.json' );
$classMap = json_decode( $string, true );
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false; // Remove unnesesary whitespace.
@$doc->loadHTML( $content );
foreach ( $doc->getElementsByTagName( '*' ) as $elem ) {
$classStr = $elem->getAttribute( 'class' );
if ( ! empty( $classStr ) ) { // No need setting empty classess all over the place.
$classes = []; // This is ware we put all the renamed classes.
foreach ( explode( ' ', $classStr ) as $class ) {
array_push( $classes, build_class( $class, $classMap ) );
}
$elem->setAttribute( 'class', implode( ' ', $classes ) );
}
}
return $doc->saveHTML();
}
if (!DEV_MODE)
ob_start( 'class_rename' );
?>
虽然不是原始问题的一部分,但该解决方案非常有趣且并非微不足道,因此我决定将其包括在内。
首先注册另一个grunt任务:
var fnPattern = /(jQuery|\$|find|__)\s*\(\s*(["'])((?:\\.|(?!\2).)*)\2\s*\)/g;
grunt.registerMultiTask('rename_js', 'Use short css class names.', function () {
this.files.forEach(function ( file ) {
var
content = fs.readFileSync( file.src[ 0 ], 'utf8' ),
map = JSON.parse( fs.readFileSync( file.map ) ),
output = content.replace( fnPattern, function ( match, fn, delimiter, str ) {
var classes, i;
if ( fn == '__' ) {
classes = str.split( ' ' );
i = classes.length;
while ( i-- ) {
classes[ i ] = rename.getClassName( classes[i], map );
}
// We can safly assume that that the classes string won't contain any quotes.
return '"' + classes.join( ' ' ) + '"';
} else { // Must be a jQuery function.
return match.replace( str, rename.getClassSelector( str, map ) );
}
});
// Wrap the output in a function so that the `__` function can get removed by an optimizer.
fs.writeFileSync( file.dest, '!(function(window, undefined) {\n' + output + '\n})(window);' );
});
});
JavaScript 文件可能看起来像这样:
function __( s ) {
return s;
}
window.main = function () {
var elems = document.getElementsByClassName(__('some-class-name')),
i = elems.length;
while ( i-- ) {
elems[ i ].className += __(' some-other-class-name');
}
}
重要的部分是__
函数声明。在开发过程中,这个函数什么都不做,但是当我们构建时应用程序,此函数将替换为已编译的类字符串。使用的正则表达式将找到所有出现的__
以及 jQuery 函数(jQuery
、$
和 jQuery.find
)。然后它创建三个组:函数名称,分隔符("
或 '
)和内部字符串。这是一个图表,可帮助您更好地理解正在发生的事情:
(?:jQuery|\$|find)\s*\(\s*(["'])((?:\\.|(?!\1).)*)\1\s*\)
如果函数名是 __
那么我们就用替换 php.ini 的方法来替换它。如果不是那么它是可能是一个选择器,所以我们尝试做一个选择器类替换。
(请注意,这不会处理输入到 jQuery 函数中的 html 文本。)
你可以得到一个完整的例子here
关于php - CSS 类重命名与 php 集成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28753197/
我有一个名为 main.css 的 css 文件和另一个名为 style.css 的文件。我怎样才能在 main.css 中做到这一点? .someClass { //apply rules to
在更新我的 css 之前,我在 Login.css 中有以下内容: body { background-image: url('./pictures/fond.png'); bac
我的 share point 2013 核心 css 和我的 css 之间存在 css 冲突。所以我想把我所有的类都放在 div #s4-workspace 下但是我搜索了一种方法来将所有类分组到这个
我知道您可以覆盖 jsp 页面从 jsp 包含 CSS 文件(即全局 CSS 文件)继承的 CSS 属性。 但是,如果元素中的某个属性弄乱了特定页面,而我不想只使用内联 CSS 在该页面中使用它怎么办
我刚刚发现了 initial-scale 元属性。 以前,我一直在使用 default.css 来定义我所有的样式和大小(用于字体和元素),以便它们在桌面计算机的屏幕上显示得很好。然后,如果您使用的是
我正在尝试使用 LESS CSS 来编写我的 CSS。我已经按顺序导入了 style.less 和 less.js 文件。 现在我想提取 LESS 生成的 CSS。有什么办法可以做到吗?我不想使用脚本
我想知道是否有任何一种软件可以读取大量内联样式中的 HTML 文档并将所有这些样式转换为外部 css 文件。如果只有一页,我可以手动完成。但是有100页。有人有想法吗? 最佳答案 就像有人说的那样,“
当我想从 Styled Components 迁移到 CSS Modules 时,出现了以下问题。 假设我有以下样式组件,它接受动态参数 offset和一个动态 CSS 字符串 theme : con
有没有办法将 CSS 类定义为与另一个类相等?例如,如果我有一个类: .myClass{ background-color: blue; } 有没有一种方法可以将第二个类定义为与 myClas
我正在尝试制作一组按钮,这些按钮贴在页面底部并且由固定的空间隔开。我正在使用 angularJS 的 ng-repeat 指令通过 ajax 请求获取数据,然后我用它来显示按钮。 我的问题在于让按
浏览器是否在加载 CSS 文件时解析 CSS?还是在整个 CSS 文件被浏览器下载后才进行解析?不同浏览器的做法有区别吗?我在哪里可以找到这种底层信息? 这个问题不是 Load and executi
这个问题在这里已经有了答案: Can a CSS class inherit one or more other classes? (29 个答案) 关闭 3 年前。 标题有点乱,我给大家看一下。假
我遇到了最奇怪的问题...... 在最简单的形式中,我有一个包含以下内容的 index.html 文件: (在尝试确定根本原因的过程中,我已经大大减少了它) 当我查看页面的源代码时,我得到以下信息:
我正在使用 Mindscape Workbench 来最小化我的 scss 文件。我的页面设置为使用 *.min.css 文件。在随机时间,min 文件不会与系统的其余部分一起发布。 我有很多 css
请告诉我 CSS 框架和 CSS 网格之间的区别。 最佳答案 CSS 框架也可以是 CSS 网格框架。 CSS 网格框架用于构建 CSS 布局。有一些框架除了构建布局还有其他用途,例如 Hartija
我有无法从页面中删除或更改的 original.css 文件。原始.css table { border-collapse: collapse; border-spacing: 0;
我以前使用 bootstrap css import 很好。 但是我正在尝试使用 CSS 模块,所以我添加了几行。 { test: /\.css$/, use:
有没有办法在 css 选择器中创建一个 css 组。 例如: .SectionHeader { include: .foo; include: .bar; include: .
今天我学习了 CSS 中的两个概念,一个是 CSS 定位(静态、相对、绝对、固定),另一个是 CSS Margin,它定义了元素之间的空间。 假设我想移动一个元素,这是最好的方法吗?因为这两个概念似乎
var paths = { css: './public/apps/user/**/*.css' } var dest = { css: './public/apps/user/css/' } /
我是一名优秀的程序员,十分优秀!