gpt4 book ai didi

php - CSS 类重命名与 php 集成

转载 作者:行者123 更新时间:2023-11-28 08:21:14 24 4
gpt4 key购买 nike

我有一个 php 元素,它使用 grunt 将 sass 文件编译成 css。我想知道是否有一种类似于 Google 的 Closure Stylesheets 的 css 类重命名方法.所以这实际上是一个由两部分组成的问题:

  1. 如何用缩短的类名编译sass。

    据我所知,sass 目前没有任何类似的功能,除非它可以作为扩展添加。但是使用 grunt 我可以先编译 sass 文件,然后运行另一个任务来重命名类并输出一个映射文件。从技术上讲,我可以为此使用 Closure Stylesheets,但我正在寻找不需要安装其他依赖项的更轻量级的东西。

  2. 如何在 php 中包含这些类名。

    现在我可以为每个 css 类插入类似这样的内容:<?php echo getclassname("some-class-name") ?>这将引用上面生成的映射文件以获得正确的类名。但这似乎很乏味。有更好的方法吗?

最佳答案

如何用缩短的类名编译sass

首先编译 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
};
}

它看起来很复杂,但这里是它正在做的分解:

  1. 解析css并得到抽象语法树(ast)。
  2. 遍历树,创建类部分到计数的映射(css 文档中出现的次数)。
  3. 将 map 打包成一个数组,并根据计数对其进行排序。
  4. 遍历数组创建缩短的类名。
  5. 以oldName -> newName的形式创建最终 map
  6. 第二次遍历树,用新的类名替换旧的类名。
  7. 返回编译后的 css 以及生成的 map 。

值得指出的是,这个函数会给更频繁使用的类更短的名字,这将导致 css 文件略小。

如何在php中包含这些类名。

这可以通过输出缓冲区来完成。它可能看起来像这样(在根 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' );
?>

JavaScript(奖励)

虽然不是原始问题的一部分,但该解决方案非常有趣且并非微不足道,因此我决定将其包括在内。

首先注册另一个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*\)

Regular expression visualization

Debuggex Demo

如果函数名是 __ 那么我们就用替换 php.ini 的方法来替换它。如果不是那么它是可能是一个选择器,所以我们尝试做一个选择器类替换。

(请注意,这不会处理输入到 jQuery 函数中的 html 文本。)

你可以得到一个完整的例子here

关于php - CSS 类重命名与 php 集成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28753197/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com