Alpine.js 지시문 및 WordPress 삭제

WordPress에는 신뢰할 수 없는 HTML을 필터링하려는 경우 합리적인 기본값이 있는 기능이 있습니다. 기본 허용 목록을 확장하려면 wp_kses_allowed_html 필터를 사용할 수 있습니다.

대부분 덜 알려진 태그와 속성이 나타나는 복잡한 SVG 구조를 다룰 때 사람들이 이 문제에 접근하는 것을 봅니다.

또 다른 시나리오는 Alpine.js 또는 Vue.js 과 같은 지시문을 사용하여 JavaScript 라이브러리로 작업하는 경우입니다.

지시문 및 WordPress의 문제



기본적으로 Alpine.js 지시문이 포함된 HTML을 트로프wp_kses_post 실행하면 모두 제거됩니다.

$alpineJsHtml = <<<'EOD'
    <div x-data="{ isVisible: false }">
        <button type="button"
            x-on:click.debounce.250="isVisible = !isVisible">
            Toggle with debounce
        </button>
        <p x-show="isVisible">I'm visible</p>
    </div>
EOD;

echo wp_kses_post($alpineJsHtml);


출력:

<div>
    <button type="button">
        Toggle with debounce
    </button>
    <p>I'm visible</p>
</div>


뒤에서 WordPress는 wp_kses_attr_check 함수를 사용하여 속성이 허용되는지 확인합니다. data-* wildcard attribute 외에 다른 모든 속성은 정확히 사전 정의되어야 하며 불행히도 사용자 정의 조건을 전달하기 위해 함수에 연결된 필터가 없습니다.

Alpine.js( 2.6.0 )에는 14개의 지시문이 있으며 대부분은 동적 부분이나 수정자가 없습니다. 허용하면 다음과 같이 보일 수 있습니다.


add_filter(
    'wp_kses_allowed_html',
    static function ($tags) {
        $alpinizedTags = ['div', 'section', 'template'];
        $alpineDirectives = [
            'x-cloak' => true,
            'x-data' => true,
            'x-if' => true,
            // ...
        ];

        foreach ($alpinizedTags as $alpinizedTag) {
            if (!isset($tags[$alpinizedTag])) {
                continue;
            }

            $tags[$alpinizedTag] = array_merge($alpineDirectives, $tags[$alpinizedTag]);
        }

        return $tags;
    }
);


동적 지시문 및 수정자



그러나 사용자 정의 이벤트를 수신하고 밀리초를 나타내는 수정자를 추가할 수 있는 x-on와 같은 지시문을 사용하면 가능한 모든 변형을 사전 정의하는 정상적인 방법이 없습니다. 허용된 속성은 정확히 일치해야 합니다. 와일드카드는 지원되지 않습니다.

한 가지 옵션은 새 조합을 사용할 때마다 목록을 간단히 업데이트하는 것입니다.

$alpineDirectives = [
    'x-on' => true, // not enough
    'x-on:click.debounce.250' => true,
    'x-on:change' => true,
    'x-on:open-menu' => 'true',
    // ...
];


또 다른 솔루션은 전역 목록에 의존하는 대신 사례별로 지시문을 처리하는 것입니다. wp_kses 함수를 사용하면 다음과 같이 표시됩니다.

echo wp_kses($alpineJsHtml, [
    'div' => [
        'x-data' => true,
    ],
    'button' => [
        'type' => true,
        'x-on:click.debounce.250' => true,
    ]
]);


그러나 이 아이디어를 더 발전시켜 지시문 목록을 동적으로 구성하고 자동으로 허용할 수 있습니다.

function allowedPostTagsWithAlpineAttrs($content)
{
    global $allowedposttags;

    // Anything that looks like an Alpine.js directive
    preg_match_all('/(x-[\w:.-]*)/', $content, $matches);

    if ($matches === false || empty($matches[0])) {
        return $allowedposttags;
    }

    $allowedTags = $allowedposttags;
    $alpineAttrs = [];

    foreach ($matches[0] as $match) {
        $alpineAttrs[$match] = true;
    }

    foreach ($allowedTags as $tag => $attributes) {
        $allowedTags[$tag] = array_merge($alpineAttrs, $attributes);
    }

    return $allowedTags;
}

echo wp_kses($alpineJsHtml, allowedPostTagsWithAlpineAttrs($alpineJsHtml));


이 접근 방식을 사용하면 Alpine.js가 새로운 것을 도입하는 경우 수정자를 추적하거나 지시문 목록을 업데이트할 필요가 없습니다.

좋은 웹페이지 즐겨찾기