pug / bemto
为Pug编写BEM的智能混入
Requires
- php: >=7.0
- phug/compiler: ^1.0.0
- phug/formatter: ^1.0.0
Requires (Dev)
- js-phpize/js-phpize-phug: ^2.1
- machy8/xhtml-formatter: ^1.0
- phpunit/phpunit: ^6.5 || ^7.5 || ^8.5
- phug/phug: ^1.0.0
This package is auto-updated.
Last update: 2024-09-07 23:19:13 UTC
README
为Pug-php编写BEM的智能混入。
本项目是将 kizu/bemto 移植到 Phug,并且与 Pug-php 兼容。
目录
安装 & 使用
composer require pug/bemto
// Working with Pug-php: Pug::addExtension(PhugBemto\PhugBemto::class); // Working with Phug: Phug::addExtension(PhugBemto\PhugBemto::class);
这将使bemto功能可用在你的模板中
+b.block1 +e.element1 Foo +b.block2 +e.A(href="#bar").element Bar +e.element2 Baz
将渲染成类似
<div class="block1"> <div class="block1__element1"> Foo </div> <div class="block2"> <a class="block2__element" href="#bar">Bar</a> </div> <div class="block1__element2"> Baz </div> </div>
功能
块
“块”是其中的主要部分。它从第一个传入的类创建块并为所有嵌套元素创建上下文。
你可以通过调用带有一些类的 b
混入来创建块
+b.foo bar
这将渲染为
<div class="foo">bar</div>
当然,简单块的语法比简单的Pug标签更复杂,但主要目的是创建元素的上下文。
元素
“元素”是块的辅助元素。你可以在 bem方法论 中了解元素的概念,或者在 Nicolas Gallagher 的 优秀文章(见“结构化类名”部分)中了解。元素通常使用块的名字加上元素的名字,中间用一些分隔符(通常是 __
或 -
)连接。
Bemto提供了一个方便的方式来声明元素:只需在任何块上下文中使用 e
混入即可
+b.foo +e.bar baz
这将渲染为
<div class="foo"> <div class="foo__bar">baz</div> </div>
元素的上下文
请注意,bemto使用块的第一个类名作为后续元素的上下文。如果你想使用另一个类而不改变顺序,可以在末尾加上 __
+b.foo.bar__ +e.baz
这样,bemto会从 bar
开始构建嵌套元素,而不是从 foo
开始
<div class="foo bar"> <div class="bar__baz"> </div> </div>
修饰符
“修饰符”是块或元素的状态。它通常在其类型和/或值之后添加单个下划线,如 block_mode_foo
或仅 block_foo
。然而,在大多数情况下,块必须包含原始块/元素的类,或者修饰符类。
Bemto使编写这样的修饰符变得容易,因为你现在不需要两次写同一个块的名字
+b.block_foo bar
变成
<div class="block block_foo">bar</div>
看!你只写了 .block_foo
,但实际上得到了 .block.block_foo
!
但如果你需要在一个块或元素上使用多个修饰符怎么办?Bemto有办法做到这一点:在你的块或元素上添加一个以修饰符标记开始的类
+b.block_foo._bar._baz +e.element_type_lol._mode_moddy Blah
这将渲染为
<div class="block block_foo block_bar block_baz"> <div class="block__element block__element_type_lol block__element_mode_moddy"> Blah </div> </div>
你还可以使用更短的修饰符语法,如 class="block -modifier"
(但只有当此语法不会用于分隔完整的修饰符或元素时)。
+b.-foo.-bar.-baz
这将渲染为
<div class="block -foo -bar -baz"> </div>
更改标签名
默认情况下,块和元素以 div
的形式渲染。您可以通过传递所需的标签名作为第一个类的首字母大写来更改它。
+b.SPAN.foo bar
或者通过传递一个包含 tag
参数的 options
对象。
+b({tag: 'span'})foo bar
无论哪种方式渲染都是
<span class="foo">bar</span>
属性
与任何 Pug 标签或混合一样,块和元素可以接受要传递给所需标签的属性
+b.foo(title="Oh, it's a title") +e.A.bar(href='#baz') baz
将呈现为
<div class="foo" title="Oh, it's a title"> <a class="foo__bar" href="#baz">baz</a> </div>
自动属性
有些标签,如 img
,必须设置至少一个属性。Bemto 会为这类标签创建一些预定义值的属性。所以,对于图像,这段代码 +b.image(src="foo.png")
会渲染 <img alt="" class="image" src="foo.png"/>
—— 您可以看到,在这种情况下,添加了一个空的 alt
属性。
此外,在某些情况下,需要根据其他属性调整某些属性。对于 img
,如果设置了 alt
但未设置 title
,则需要将其设置为空,因为在浏览器之间(IE 会为 alt
显示 title
气泡)会有不一致性。另一方面,如果只有 title
设置在图像中,我们需要将其克隆到 alt
中。Bemto 会做所有这些事情。
上下文
看看前面的例子:您可以看到一些多余的代码,您可以将其删除。这是 ('a')
部分 —— 只要您设置了 href
属性,块就会自动成为链接。还有其他可以省略的标签:在 ul
或 ol
上下文中的 li
,或者在任何已内联的上下文中的 span
。
所以,这里有一个更大的例子
+b.UL.list +b.list-item +e.link(href="foo") +e.text foo +b.list-item +e.link(href="bar") +e.text bar
将渲染为
<ul class="list"> <li class="list-item"> <a class="list-item__link" href="foo"> <span class="list-item__text">foo</span> </a> </li> <li class="list-item"> <a class="list-item__link" href="bar"> <span class="list-item__text">bar</span> </a> </li> </ul>
目前就这些了,但将来会有更多的 bemto 上下文。
重新定义标签的元数据
如果您想使某个标签设置不同的上下文,例如覆盖其 content_type,您可以使用块/元素的 metadata
选项。例如,如果您想使链接具有块上下文,您可以这样重新定义它
+b({ metadata: { content_type: 'block' } }).A.foo +e.bar
将呈现为
<a class="foo"> <div class="foo__bar">baz </div></a>
设置
您可以为 BEM 的不同语法设置一些设置。
为此,您必须在包含 bemto
之后设置它们,如下所示
- set_bemto_settings({ prefix: '', element: '__', modifier: '_' })
在这里,您可以看到所有可用的设置及其默认值。
添加前缀
如果您想为所有 bemto 生成的块添加前缀,您可以设置 prefix
设置为字符串或对象。
前缀设置的字符串
如果设置了一个字符串,它将简单地作为所有块名称的前缀。
- set_bemto_settings({ prefix: 'b-' }) +b.block +e.element foo
然后渲染为
<div class="b-block"> <div class="b-block__element"> foo </div> </div>
请注意,如果您已经在类名中使用了此前缀,则不会添加它,因此您不会出现偶尔重复的前缀。
前缀设置的对象
如果您想对前缀有更多的控制,可以使用特殊的对象而不是字符串。
- set_bemto_settings({ prefix: { '': 'b-', 'js-': true, 'is-': 'is-', 'global-': '', 'nope-': false, 'sc-': 'shortcut-' } })
看看上面的例子,它展示了前缀对象接受的全部变体。
-
空字符串作为键的工作方式与字符串设置相同:您将为此键获取 prepended 所有类名而不检测到前缀的值。
-
如果一个键的值是
true
,则此前缀始终被视为此类,并且不会被其他前缀 prepended。 -
如果一个键的值是
false
或空字符串,则具有此前缀的类名将不带前缀渲染。 -
在其他情况下,键和值都是字符串时,源代码中的所有键前缀都会被替换为值前缀,并且所有这些前缀都会被视为已注册的,因此您不会为它们添加其他前缀。
元素语法的设置
如果您不喜欢默认的元素语法中的 __
分隔符,您可以使用 element
设置。
- set_bemto_settings({ element: '-' }) +b.block +e.element foo
这将渲染为
<div class="block"> <div class="block-element"> foo </div> </div>
修饰符语法的设置
如果您想使用不同的修饰符语法,例如Nicolas Gallagher在其文章中提到的语法,您可以使用modifier
设置
- set_bemto_settings({ modifier: '--' }) +b.block--modifier-name.--other-modifier foo
这将展开为
<div class="block block--modifier-name block--other-modifier"> foo </div>
允许嵌套元素的设置
有些情况下,您可能想制作元素的元素,即使用元素名称而不是块名称时
+b.block-element +e.element2
默认渲染为
<div class="foo__bar"> <div class="foo__baz"> </div> </div>
如果您希望在输出中拥有foo__bar__baz
,可以将flat_elements
设置为false
- set_bemto_settings({ flat_elements: false }) +b.foo__bar +e.baz
这将使用嵌套元素渲染
<div class="foo__bar"> <div class="foo__bar__baz"> </div> </div>
设置的适用范围
如果您需要在特定范围内使用某些设置,您可以在bemto_scope
混入中包裹您的代码,将您希望的设置直接传递给它
+b.foo_bar +bemto_scope({ prefix: 'b-', element: '-', modifier: '--' }) +b.nnnn +e.mmmm--kkkk +e.baz
这将渲染为
<div class="foo foo_bar"> <div class="b-nnnn"> <div class="b-nnnn-mmmm b-nnnn-mmmm--kkkk"> </div> </div> <div class="foo__baz"> </div> </div>
元素/修饰符输出语法的设置
如果您想在Pug源代码和HTML输出中使用不同的元素/修饰符分隔符语法,您可以使用output_element
和output_modifier
设置,否则将使用与element
和modifier
设置相同的分隔符。
- set_bemto_settings({ element: '-', modifier: '--', output_element: '__', output_modifier: '_' }) +b.block.block2- +e.element--modifier foo
将输出
<div class="block block2"> <div class="block2__element block2__element_modifier">foo </div> </div>
您可以看到源代码如何使用-
作为元素和--
作为修饰符,但结果会变成__
和_
。
类名之间的分隔符设置
如果您想在使用渲染的类名之间有额外的分隔符以提高可读性,您可以使用class_delimiter
设置
- set_bemto_settings({ class_delimiter: '|' }) +b.foo.bar_baz
将渲染为
<div class="foo | bar | bar_baz"> </div>
请注意,将始终在给定的分隔符周围添加空格,因此您不需要在设置值中包含它们。
用于构建复杂混入
这一点虽然很明显,但我必须提到,bemto块非常适合用作构建更复杂块的砖块。Pug混入以这种方式工作,您可以通过任何内部bemto块将任何属性传递到任何内部块。因此,您可以这样做
mixin link(url) +b.SPAN.link(href=url)&attributes(attributes) block
然后以这种方式使用它
+link('#Foo') Foo +link('https://github.com')._external Github +link('http://kizu.ru').url(rel="me") Here I am +link Ah, I'm not a link +link('https://github.com') +e.icon(src="http://favicon.yandex.net/favicon/github.com") +e.text Github
这将渲染为
<a class="link" href="#Foo">Foo</a> <a class="link link_external" href="https://github.com">Github</a> <a class="link url" href="http://kizu.ru" rel="me">Here I am</a> <span class="link">Ah, I'm not a link</span> <a class="link" href="https://github.com"> <img alt="" role="presentation" class="link__icon" src="http://favicon.yandex.net/favicon/github.com"/> <span class="link__text">Github</span> </a>
在那里,您可以看到几乎所有可以用于具有附加到其中任何内部bemto块上的attributes
变量的混入的bemto功能。
安全联系方式
要报告安全漏洞,请使用Tidelift安全联系方式。Tidelift将协调修复和披露。