timkelty/craftcms-classmate

HTML类辅助工具

1.1.0 2021-01-24 19:29 UTC

This package is auto-updated.

Last update: 2024-08-29 02:50:25 UTC


README

Donate

Test Status

Classmate旨在帮助HTML类组合,尤其与utility-first CSS框架,如Tailwind CSS搭配使用时非常有用。

在Classmate之前

template.twig

<h2 class="text-lg leading-6 font-medium text-gray-900 mb-3">
  Some reusable heading…
  <a href="#" class="text-orange-600 hover:text-orange-900">A link</a>
</h2>

在Classmate之后

template.twig

<h2
  class="{{ classmate.get('myHeading').remove('text-gray-900').add('mb-3', 'text-gray-400') }"
>
  Some reusable heading…
  <a href="#" class="{{ classmate.get('defaultLink') }}">A link</a>
</h2>

classmate.json

{
  "myHeading": "text-lg leading-6 font-medium text-gray-900",
  "defaultLink": "text-orange-600 hover:text-orange-900"
}

为什么?

我对使用@apply提取组件类的看法,可以由这篇推文很好地概括。

Flowchart: "Should you extract a component class with @apply"

简而言之,我尽可能避免使用@apply

Classmate专门为单个元素组件(例如按钮、链接、标题)而创建,在这些组件中,将它们提取到模板部分可能很繁琐,同时仍然希望避免使用@apply

这与@apply有什么不同?我们不是只是把问题转移到了别处吗?

是的,也可能不是。确实,使用@apply提取组件的实践与在Classmate JSON文件中定义类相似。然而,Classmate在后台(PHP)抽象化了定义,而@apply作为前端构建的一部分进行了抽象。这种做法的优点是

  • 没有组件类带来的额外CSS膨胀
  • 没有增加@apply的编译时间
  • 您生成的HTML保持全实用。对于新加入项目的开发者,尤其是如果他们已经熟悉Tailwind或任何框架,如果他们不需要解析一组组件类,那么加入项目会更容易。
  • 错误更容易被发现。
    • 使用提取的组件,可能会发生误用而未被察觉,例如在类属性中输入了拼写错误。在Classmate中,当类定义缺失时,开发者可以立即发现。
  • 配置可以与前端JS共享。

配置

./src/config.php复制到<yourProject>/config/classmate.php

filePath

您的Classmate文件的位置。支持别名和环境变量。默认为@config/classmate.json,但我建议您将其放置在与您的预编译前端资产相同的目录中,例如./src/css/classmate.json

如果您直接使用Tailwind或PurgeCSS,您还希望包含此路径。例如:

tailwind.config.js

module.exports = {
  purge: {
    content: [
      "./src/**/*.css",
      "./src/**/*.js",
      "./templates/**/*.*",
      "./config/tailwind.json",
    ],
    options: {
      safelist: [],
    },
  },
};

Classmate 文件

您的Classmate文件是一个包含单个对象的JSON文件。值可以是空格分隔的字符串或数组,也可以是两者的组合。

{
  "heading1": "text-2xl font-bold",
  "heading2": ["text-lg", "font-bold"],
  "buttonBase": [
    "text-center inline-flex items-center justify-center font-bold",
    "rounded-full"
  ],
  "buttonWhite": "bg-white text-gray-900",
  "buttonLg": "leading-none text-xl py-4 px-8",
  "buttonSm": "leading-none text-sm py-2 px-4",
  "centerX": "left-1/2 transform -translate-x-1/2",
  "centerY": "top-1/2 transform -translate-y-1/2"
}

由于这只是一个JSON文件,它也很容易由JavaScript消费!

import classmate from "../../config/classmate.json";
document.querySelector("body").class = classmate.body;

使用方法

tag 函数

{{ tag('a', classmate.get('defaultLink').asAttributes({
  text: 'A link'
  href: '#'
})) }}

tag 标签

Craft 3.6+ 仅支持

{% tag('a', classmate.get('defaultLink').asAttributes({href: '#' })) %}
  A link
{% endtag %}

attr 函数

<a {{ attr({
  href: '#'
  class: classmate.get('defaultLink').asClasses()
}) }}>A link</a>

attr 过滤器

{% set tag = '<a href="#">' %}
{{ tag|attr({
    class: classmate.get('defaultLink').asClasses()
}) }}

类字符串

<a href="#" class="{{ classmate.get('defaultLink') }}">A link</a>

API

classmate 是一个链式API,在您的Twig模板中作为全局变量可用。

get(string ...$keys): Classmate

从您的Classmate文件中检索给定$keys的类。多个键将从右至左合并。

{{ classmate.get('buttonBase', 'buttonLarge', 'buttonBlue') }}

asClasses(): array

检索一个类数组。移除重复和空值。

<div {{ attr({
  class: classmate.get('foo').asClasses()
}) }}">

asAttributes(iterable $attributes = []): array

检索一个与attr兼容的可迭代对象,其中class已合并到任何传递的$attributes中。

<div {{ attr(classmate.get('foo').asAttributes({
  id: 'buttonLarge'
})) }}">

add(string ...$classes): 同学

向当前 ClassList 添加类。

{{ classmate.get('foo').add('mb-4') }}

remove(string ...$classes): 同学

从当前 ClassList 移除类。

{{ classmate.get('foo').remove('mb-4') }}

matching(string $pattern): 同学

过滤当前 ClassList,保留与 $pattern 匹配的项。

{{ classmate.get('foo').matching('/^text-/') }}

notMatching(string $pattern): 同学

过滤当前 ClassList,移除与 $pattern 匹配的项。

{{ classmate.get('foo').notMatching('/^mb-/') }}

replace(string $search, string $replace, bool $partial = false): 同学

$search 替换为 $replace。将 $partial 设置为 true 以匹配部分字符串,否则仅替换完整匹配。

{{ classmate.get('foo').replace('text-red-500', 'text-red-100') }}
{{ classmate.get('bar').replace('md:', 'lg:', true) }}

prepend(string $string): 同学

$string 预先添加到 ClassList 的每个项中。

{{ classmate.get('foo').prepend('md:') }}

append(string $string): 同学

$string 添加到 ClassList 的每个项中。

缓存

JSON 文件的检索被缓存,并且通过文件的修改来失效,因此你真的不需要过多担心失效。然而,你可以通过 CP 或 CLI 命令选择性地清除缓存。

./craft clear-caches/classmate-cache

需求

  • Craft CMS 3.0+
  • PHP 7.4+

安装

composer require timkelty/craftcms-classmate

路线图

如何在 CSS 中使用 Classmate 类?

你无法!……目前还不行。@markhuot 在这里提到了这一点:https://twitter.com/markhuot/status/1351605237736419329

可能的一个 Tailwind/Postcss 插件可以允许这样做

例如,你可以这样写

.prose a {
  @classmate foo, bar;
}

……来获取与 classmate.get('foo', 'bar') 相同的类。

箭头函数

我很乐意允许使用箭头函数,但当前 Twig 不允许这样做。例如,对于我们的 matchesprepend 方法,我更愿意有

classmate.get('foo').filter(c => c starts with 'f')
classmate.get('foo').filter(c => c matches '/^f/')
classmate.get('foo').map(c => "md:#{c}")

虽然这适用于 Twig 的 mapfilterreduce 过滤器,但在这里不起作用。参见 twigphp/Twig#3402

CP 设置

我并不真的想这样做,但如果有人想添加,我会很高兴接受 PR。