postcss 插件
到现在为止,我相信您已经很认真并真正地聚集了,使PostCSS惊奇的是它蓬勃发展的插件生态系统。 一个巨大的原因是,有这么多很棒的插件,而且每时每刻都有更多的插件出现,这是因为PostCSS使得创建自己的插件对于任何有JavaScript经验的人都可以访问。
制作PostCSS插件不需要特殊权限; 如果您想制造一个,那就继续前进吧。 通过这种自由,您可以将CSS开发过程变成您想要的任何东西,更不用说有机会与快速发展的PostCSS社区的其他成员共享您的工作。
在本教程中,您将学习如何为PostCSS创建自己的基本插件。 我们不会过多地使用插件API,也不会使用任何超级硬核编码。 我本人是前端开发人员,我JavaScript技能达到了您期望他们成为前端人员的水平,但这并没有阻止我在短短几个小时内制作出我的第一个PostCSS插件。
跟随并亲眼看看PostCSS插件开发的发展水平!
我们将要建立的
我们将创建一个插件,该插件可通过以下语法轻松地将字体堆栈插入到font-family声明中:
h1 {
font-family: "Open Sans", fontstack("Arial");
}
编译后,以上代码将变为:
h1 {
font-family: "Open Sans", Arial, "Helvetica Neue", Helvetica, sans-serif;
}
设置一个项目以在内部工作
即使您正在创建自己的插件,仍然需要从创建一个空的Gulp或Grunt项目开始。 您将以在本系列中一直使用其他人的插件的方式将插件加载到该项目中。
您可以在之前的教程中阅读有关如何为PostCSS设置Gulp或Grunt项目的信息:
但是,如果您不想从头开始手动设置项目,则可以下载本教程附带的源文件 ,并将提供的Gulp或Grunt入门项目提取到一个空项目文件夹中。 然后,在终端或命令提示符指向该文件夹的情况下,运行命令npm install 。
创建一个基本的插件外壳
在“ node_modules”中创建一个名为“ postcss-myplugin”的文件夹。 通常使用前缀postcss-来明确您的插件是用于PostCSS的。
所有PostCSS插件都是节点模块,因此我们需要将新文件夹转换为一个。 打开终端/命令提示符,指向新创建的文件夹,然后运行npm init 。 这将执行节点模块的基本设置,因此只需遵循终端中出现的提示,将“入口点”字段保留为默认的“ index.js”。
完成后,在终端仍指向文件夹的情况下,运行命令npm install postcss --save 。 这会将PostCSS安装为该模块的依赖项,所有PostCSS插件都需要这样做。
在“ postcss-myplugin”文件夹中创建一个名为“ index.js”的文件。 添加以下代码以加载到主要的postcss模块中:
var postcss = require('postcss');
然后在其下面添加此基本包装,它将围绕我们插件的处理代码:
var postcss = require('postcss');
module.exports = postcss.plugin('myplugin', function myplugin(options) {
return function (css) {
options = options || {};
// Processing code will be added here
}
});
加载新插件
现在,我们准备将您新创建的插件加载到您的项目中。 它不会做任何事情,但是我们只想完成必要的设置。
通过Gulp加载插件
如果您使用的是Gulp,请将此变量添加到文件中已存在的变量下面:
var myplugin = require('postcss-myplugin');
现在,将新的变量名称添加到processors数组中:
var processors = [
myplugin
];
通过运行gulp css命令并检查项目的“ dest”文件夹中是否出现了新的“ style.css”文件,来快速测试一切是否正常。
通过Grunt加载插件
如果您使用的是Grunt,请将嵌套在options对象下的processors对象更新为以下内容:
processors: [
require('postcss-myplugin')()
]
通过运行grunt postcss命令并检查项目的“ dest”文件夹中是否出现了新的“ style.css”文件,来快速测试一切是否正常。
添加插件功能
添加测试CSS
在开始向插件添加处理代码之前,我们将在样式表中添加一些插件可以使用的测试代码。
在您的“ src / style.css”文件中添加以下CSS:
h1 {
font-family: "Open Sans", fontstack("Arial");
}
现在,由于我们的插件尚未执行任何操作,因此,如果您编译CSS,则只会看到完全相同的代码,直接复制到“目标”文件夹的“ style.css”文件中。
遍历规则和声明
现在我们要开始扫描文件CSS,以便我们找到fontstack()任何实例并进行处理。 要开始此操作,请在options = options || {};之后添加以下代码。options = options || {};线:
css.walkRules(function (rule) {
rule.walkDecls(function (decl, i) {
});
});
在第一行中使用walkRules()遍历CSS中的每个规则; 规则基本上是选择器以及在花括号之间设置的样式。 在我们的测试CSS中,一条规则是:
h1 {
font-family: "Open Sans", fontstack("Arial");
}
然后,在每个规则中, walkDecls()遍历每个声明。 声明本质上是样式中的每一行。 在以上CSS中,声明为:
font-family: "Open Sans", fontstack("Arial");
检查是否使用fontstack()语法
当我们使用刚刚添加的代码遍历每个声明时,当前声明由decl表示,这使我们可以分别通过decl.prop和decl.value来访问声明的属性及其值。
对于我们CSS示例, decl.prop将为我们提供font-family而decl.value将为我们提供"Open Sans", fontstack("Arial") 。
我们想要检查样式表中的每个decl.value ,看是否包含字符串fontstack( 。如果确实如此,我们知道有人正在尝试使用我们的插件向其CSS添加字体堆栈。
在walkDecl()循环中,添加:
var value = decl.value;
if (value.indexOf( 'fontstack(' ) !== -1) {
console.log("found fontstack");
}
首先,我们获取decl.value并将其存储在变量value 。 对decl.value任何更改将发送到已编译的样式表中; 我们将其内容存储在变量value这样我们就可以弄乱它。
然后,我们使用indexOf()方法在新的value变量中搜索字符串fontstack( 。如果找到了,则将“ found fontstack”记录到控制台,以便我们检查到目前为止是否一切正常。
运行grunt postcss gulp css或grunt postcss ,您应该在终端/命令提示符中看到一次“ found fontstack”输出。
定义一些字体库
现在,我们的插件能够在样式表中找到fontstack()实例,我们可以准备将其转换为字体堆栈,即字体名称列表。 但是在执行此操作之前,我们需要先定义这些字体堆栈。
在文件顶部的现有postcss变量下,创建一个名为fontstacks_config的变量。 我们将把这个变量变成一个包含键值对的对象。
对于对象中的每个条目,键应为字体堆栈中的第一个字体,例如'Arial' 。 这将是用户传递的字符串,用于指定他们要使用的字体堆栈,例如fontstack("Arial")或fontstack("Times New Roman") 。
每对中的值应为字体堆栈中包含的字体的完整列表的字符串,例如'Arial, "Helvetica Neue", Helvetica, sans-serif' 。
使用CSS Font Stack提供的字体堆栈 ,将两个条目添加到fontstacks_config对象中,一个用于“ Arial”,另一个用于“ Times New Roman”。
您的fontstacks_config变量应如下所示:
// Font stacks from http://www.cssfontstack.com/
var fontstacks_config = {
'Arial': 'Arial, "Helvetica Neue", Helvetica, sans-serif',
'Times New Roman': 'TimesNewRoman, "Times New Roman", Times, Baskerville, Georgia, serif'
}
检查请求哪个Fontstack
找到正在使用的fontstack()实例时,我们要做的第一件事是弄清楚用户请求了哪个字体栈,即他们在方括号之间设置了什么字符串。
例如,如果用户输入fontstack("Arial")我们希望提取字符串Arial 。 我们想要这个字符串的原因是它将为我们提供一个密钥,我们可以使用该密钥从我们的fontstacks_config对象中查找相应的字体栈。
将此代码立即添加到我们之前添加的if语句中,替换console.log("found fontstack"); 线:
// Get the name of the fontstack requested by matching the string inside the brackets of fontstack().
// Then replace any double or single quotes therein.
var fontstack_requested = value.match(/\(([^)]+)\)/)[1].replace(/["']/g, "");
我们在这里执行两个步骤来提取字体堆栈的名称作为字符串。
首先,我们使用match()方法查找值中括号之间的任何字符串。 这将给我们一个字符串,例如"Arial"或'Arial' 。
我们只需要字体名称,而没有任何双引号或单引号,因此我们使用replace()方法从字符串中去除它们,从而留下未加引号的字符串,例如Arial 。
此字符串存储在fontstack_requested变量中。
标题大小写要求的Fontstack
我们将使用新创建的fontstack_requested变量从fontstack_config选项中查找字体堆栈。 棘手的部分是此对象中的键区分大小写,因此,如果我们尝试使用键arial查找Arial条目,它将失败。
为了解决这个问题,我们将字符串“ Title Case”,例如,将times new roman转换为Times New Roman 。 我们将通过简短的自定义函数进行此操作。
在您的fontstacks_config变量下, fontstacks_config添加到toTitleCase()函数:
// Credit for this function to http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript/196991#196991
function toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
现在,我们将此函数应用于fontstack_requested变量。 在创建fontstack_requested变量的行下,添加以下代码:
// Title case the words in the font name, just in case the user didn't do it themselves
fontstack_requested = toTitleCase(fontstack_requested);
这将通过我们的toTitleCase()函数传递fontstack_requested变量,以更新其值。
从配置中查找字体库
现在我们已经正确设置了fonstack_requested变量,我们可以使用它来查找相应的字体堆栈。 在刚添加的行之后,插入以下代码:
// Lookup the requested fontstack in the fontstack_config object
var fontstack = fontstacks_config[fontstack_requested];
这将在fontstacks_config对象中找到具有与我们的fontstack_requested变量中包含的字符串匹配的键的键值。
例如,如果fontstack_requested包含字符串Arial ,则将在fontstacks_config中fontstacks_config带有Arial键的条目,并返回值'Arial, "Helvetica Neue", Helvetica, sans-serif' 。
然后,此返回值存储在变量fontstack 。
检查在fontstack()之前设置的字体
现在,我们已经检索了字体堆栈字符串,并准备将其插入CSS,但是还需要做一件事。 您会记得在我们的测试代码中,我们将字体“ Open Sans”作为首选字体,并将字体堆栈作为后备。 我们还需要从值中检索此字体名称,以便可以将其添加到我们插入到已处理样式表中CSS中。
在fontstack变量行下方,添加以下代码:
// Find and store any font names that might be already be in the value, before the fontstack() call
var first_font = value.substr(0, value.indexOf('fontstack('));
此代码使用substr()方法查找value的开头(用0表示)和fontstack()实例(使用indexOf()方法定位)之间的任何内容。 无论找到什么内容,都将存储在变量first_font 。
例如,在我们的测试代码中, value等于"Open Sans", fontstack("Arial") ,因此first_font变量将设置为"Open Sans", first_font
创造新价值
现在,我们拥有创建新值所需的所有内容,用它来替换测试代码的原始值"Open Sans", fontstack("Arial") 。
在您添加的最后一个代码之后,插入以下代码:
// Create the new value for this rule by combining the first_font and fontstack variables
var new_value = first_font + fontstack;
在这里,我们将first_font和fontstack变量组合为一个字符串,并将其存储在变量new_value 。
在我们的测试代码中,这意味着将"Open Sans",和Arial, "Helvetica Neue", Helvetica, sans-serif组合在一起。
然后,我们的new_value变量将包含字符串"Open Sans", 'Arial, "Helvetica Neue", Helvetica, sans-serif' 。
现在,这为我们提供了要添加到已处理样式表中的完整值,以便:
font-family: "Open Sans", fontstack("Arial");
...转换为:
font-family: "Open Sans", 'Arial, "Helvetica Neue", Helvetica, sans-serif';
将新值发送回样式表
现在我们已经准备好将新值插入已处理的样式表中,我们要做的就是更新decl.value 。 PostCSS将处理其余的工作,为我们添加新值到已处理CSS中。
在您添加的最后一行之后添加以下代码:
// Send the new value back into the stylesheet
decl.value = new_value;
这decl.value设置为等于new_value变量的内容。
测试您的插件
您的插件现在可以使用了。 通过用grunt postcss gulp css或grunt postcss编译样式表(使终端指向您的项目文件夹,而不是插件文件夹)来进行测试。
您的“ dest / style.css”文件现在应显示完整的字体堆栈:
h1 {
font-family: "Open Sans", Arial, "Helvetica Neue", Helvetica, sans-serif;
}
(可选)添加用户可配置的字体堆栈选项
您可能希望允许插件的用户设置自己的选项,就像设置本系列中使用PostCSS插件的方式一样。
我们希望用户能够设置fontstacks选项,或者添加额外的字体栈,或者重新定义现有的字体栈,例如:
fontstacks: {
'Extra Stack': '"Extra Stack", "Moar Fonts", Extra, serif',
'Arial': 'Arial, "Comic Sans"'
}
注意 :此步骤是可选的。 如果您愿意,可以跳过它,并且您的插件可以正常运行,而无需任何用户设置配置。
我们已经拥有在插件中启用用户设置选项的最重要部分。 在我们的module.exports行中,您会注意到正在传递一个options参数。
module.exports = postcss.plugin('myplugin', function (options) {
我们将收到用户为此设置的所有用户选项。
您还将看到我们一行:
options = options || {};
这将检查options是否具有任何值,如果没有,则将其设置为空对象。 这可以确保在开始使用未定义的options时不会出现任何错误。
首先,我们将在其项目中安装Underscore.js,因为我们将使用其方便的extend()方法。 运行以下命令将其安装到您要构建的插件中:
npm install underscore --save
现在,在现有的postcss变量下添加一个_变量以将postcss加载到您的插件中:
var postcss = require('postcss');
var _ = require('underscore');
接下来,我们要做的是获取已在插件内部创建的fontstacks_config对象,并将其“扩展”为用户通过其选项配置设置的所有字体栈。
直接在options = options || {};下添加此代码options = options || {};线:
// Extend the default fontstacks_config option with any custom fontstacks set in the plugin's options
fontstacks_config = _.extend(fontstacks_config, options.fontstacks);
用户设置的fontstacks选项由options.fontstacks表示。
通过使用Underscore的extend()方法, options.fontstacks中的所有字体堆栈都将添加到fontstacks_config已经存在的fontstacks_config 。 只要有匹配的键, options.fontstacks的值就会覆盖fontstacks_config中的fontstacks_config 。 这使用户可以重新定义任何现有的字体堆栈。
在您的Gulpfile或Gruntfile中,设置一个fontstacks选项并传递一个新的字体堆栈,以及重新定义一个现有的字体堆栈:
/* Gulpfile */
var processors = [
myplugin({
fontstacks: {
'Extra Stack': '"Extra Stack", "Moar Fonts", Extra, serif',
'Arial': 'Arial, "Comic Sans"'
}
})
];
/* Gruntfile */
processors: [
require('postcss-myplugin')({
fontstacks: {
'Extra Stack': '"Extra Stack", "Moar Fonts", Extra, serif',
'Arial': 'Arial, "Comic Sans"'
}
})
]
现在,在您的“ src / style.css”文件中添加一些额外CSS,以便我们可以测试刚刚通过选项添加的新字体栈:
h2 {
font-family: "Droid Sans", fontstack("Extra Stack");
}
重新编译CSS,您应该看到'Arial'字体堆栈现在具有不同的输出,并且'Extra Stack'字体堆栈具有正确的输出:
h1 {
font-family: "Open Sans", Arial, "Comic Sans";
}
h2 {
font-family: "Droid Sans", "Extra Stack", "Moar Fonts", Extra, serif;
}
您完成的插件
而已! 大功告成 您已经完成了第一个PostCSS插件。
如果需要将代码与其进行比较以供参考,这就是GitHub上的全部内容 。
回顾一下
您刚刚创建了一个完整的PostCSS插件,并且希望关于您喜欢制作的其他插件的想法能引起您的注意。 在编写CSS时,也许有一件小事总是困扰您,也许现在您可以提出自己的解决方案以永久摆脱它。 或者也许您确实认为CSS应该有一些额外的东西-好了,现在您可以自己添加它了!
总结一下我们所涵盖的内容:
- 通过设置可以使用的Gulp或Grunt项目开始开发新插件。
- 在项目内创建一个新的节点模块,它将成为您的插件。
- 将新插件加载到项目中。
- 以您希望插件使用的语法添加一些测试CSS。
- 使用PostCSS API中的方法浏览样式表。
- 找到正在使用的插件语法的实例。
- 编写JavaScript并使用PostCSS API对原始代码进行适当的转换(和/或添加),然后将其发送到已处理CSS中。
对于TypeScript用户
作为PostCSS 5.0版本的一部分 ,Jed Mao贡献了一大堆 TypeScript定义,这些定义可以通过在您键入时提供自动补全和内联文档来帮助大量插件开发。
如果您发现自己从事PostCSS插件开发,那么确实值得将其纳入您的工作流程中。 我本人不是TypeType专家,但是无论如何,几乎都将使用它进行编码,因此我可以充分利用此功能。
如果您想尝试此操作,则无需在Windows上使用Visual Studio,也可以使用Visual Studio,因为您可以使用免费的开放源代码Visual Studio Code ,该代码可在Windows,Mac和Linux上运行,并基于Electron构建。 ,为Atom Editor提供支持的外壳程序。
有关如何将这些TypeScript定义合并到项目中的示例,请查看postcss-font-pack插件。 分叉它,并在Visual Studio Code中发挥作用,以查看自动完成和内联文档的工作方式。
PostCSS深入探讨:总结
非常感谢您关注这个PostCSS Deep Dive系列。 希望您喜欢阅读它,也喜欢创建它! 更重要的是,我希望您对如何在日常的Web开发生活中使用PostCSS充满想法。
PostCSS确实是对前端世界的不可思议的新增功能,因为它促进插件的方式为我们在CSS开发中前所未有的可能性打开了大门。 现在可用的插件范围已经足够完全重塑一个人的日常工作流程,而这正是在短短几年内创造出来的。
我建议PostCSS尚未达到顶峰,并且由于它开始成为大多数CSS开发人员至少知道的东西,即使不发誓,我们也会看到它真正进入了大步前进。 随着更多前端开发人员的加入,我们将看到对插件生态系统的更多贡献,添加新插件并帮助构建现有插件。
这些插件可以自由地迎合开发人员可以梦想的任何类型CSS转换,因此PostCSS的未来确实非常吸引人。 我期待参与其中,希望您也能参与其中!
翻译自: https://webdesign.tutsplus.com/tutorials/postcss-deep-dive-create-your-own-plugin--cms-24605
postcss 插件
849

被折叠的 条评论
为什么被折叠?



