Files
kate522 9375b1c30c refactor(assets): vendor 资产迁入标准目录并全仓去除 zibll 标识
- assets/vendor 全量迁移: fontawesome5→assets/fontawesome5, css→assets/css,
  js→assets/js/runtime(避开 14 个同名自有文件), img 合并去重→assets/img,
  fonts→assets/fonts; 删除 assets/vendor
- libs 五个与 widgets/third-party 字节相同的库不重复入库, loader paths 改指向
- 运行时切换: _win.uri=assets 根, loader baseUrl=/js/runtime, enlighter 注入
  路径同步; PHP 7 个引用文件切换并改名 $zibll_*→$runtime_*
- 去品牌: Qinver 头注释/品牌 console.log/演示链接清除, 默认文案中性化
- 功能标识符改名: zib__→aksrt__, zib_ajax→aksrt_ajax, window.zib→
  window.aksrtLegacy, zibllblock/*→aksrtblock/*, .zib-widget→.aksrt-panel,
  .zib-slider→.aksrt-slider, zib_menu_options meta 键等
- 自有 CSS 改名: legacy-utilities/compat-vars/footer shell
- admin SPA 重建; 契约测试同步(路径/断言/文件更名)
- 例外保留: tests/visual 对照环境与 fixtures 前缀(外部 Zibll 产品引用)

验证: php -l 133 个改动文件通过; runtime 86 个 JS node --check 通过;
契约测试 68/70(2 个失败经 stash 对照确认为存量问题)
2026-08-22 16:16:30 +08:00

811 lines
29 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* AKSRT Gutenberg Blocks
*
* Custom Gutenberg block extensions for the AKSRT theme.
* Provides 9 generic content blocks adapted from legacy.
*
* Blocks: tabs, tab, enlighter, quote, alert, buttons, collapse, feature, iframe
*
* @package AKSRT
*/
(function () {
'use strict';
if (!window.wp || !window.wp.blocks) return;
var el = wp.element.createElement;
var Fragment = wp.element.Fragment;
var RawHTML = wp.element.RawHTML;
var registerBlockTypeRaw = wp.blocks.registerBlockType;
var blockEditor = wp.blockEditor || wp.editor || {};
var InspectorControls = blockEditor.InspectorControls || null;
var InnerBlocks = blockEditor.InnerBlocks || null;
var RichText = blockEditor.RichText || null;
var MediaUpload = blockEditor.MediaUpload || null;
var ColorPicker = wp.components.ColorPicker;
var PanelBody = wp.components.PanelBody;
var SelectControl = wp.components.SelectControl;
var TextControl = wp.components.TextControl;
var ToggleControl = wp.components.ToggleControl;
var RangeControl = wp.components.RangeControl;
var Notice = wp.components.Notice;
var useSelect = window.wp.data && window.wp.data.useSelect;
if (!registerBlockTypeRaw || !el) return;
// ── Helper: create element shorthand ──
function h(tag, props, children) {
var args = [tag, props];
if (children !== undefined) {
if (Array.isArray(children)) {
args = args.concat(children);
} else {
args.push(children);
}
}
return el.apply(null, args);
}
// ── Helper: InspectorControls wrapper ──
function withInspector(title, children) {
if (!InspectorControls) return null;
return h(InspectorControls, { key: 'inspector' },
h(PanelBody, { title: title }, children)
);
}
var CATEGORY = 'aksrt-blocks';
var BLOCK_ICON = h('svg', { viewBox: '0 0 24 24', width: 20, height: 20 },
h('path', { d: 'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5', fill: 'none', stroke: 'currentColor', strokeWidth: 2 })
);
// Register category BEFORE any registerBlockType (filter-after-register is too late).
if (window.wp.hooks && window.wp.hooks.addFilter) {
wp.hooks.addFilter('blocks.getBlockCategories', 'aksrt/block-categories', function (categories) {
var list = Array.isArray(categories) ? categories.slice() : [];
var hasAksrt = list.some(function (c) { return c && c.slug === CATEGORY; });
if (hasAksrt) return list;
list.push({
slug: CATEGORY,
title: 'AKSRT',
icon: null,
});
return list;
});
}
// WP 6.9+ expects apiVersion 3 for iframe editor compatibility.
function registerBlockType(name, settings) {
settings = settings || {};
if (settings.apiVersion == null) {
settings.apiVersion = 3;
}
if (!settings.category) {
settings.category = CATEGORY;
}
return registerBlockTypeRaw(name, settings);
}
// ================================================================
// 1. Tabs Block
// ================================================================
registerBlockType('aksrt/tabs', {
title: '标签页',
icon: BLOCK_ICON,
category: CATEGORY,
description: '可切换的标签页内容容器',
attributes: {
style: { type: 'string', default: 'default' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('标签页设置',
h(SelectControl, {
label: '样式',
value: props.attributes.style,
options: [
{ label: '默认', value: 'default' },
{ label: '线条', value: 'line' },
{ label: '卡片', value: 'card' },
],
onChange: function (v) { props.setAttributes({ style: v }); }
})
),
h('div', { className: 'aksrt-block-tabs aksrt-block-tabs--' + props.attributes.style },
h(InnerBlocks, {
allowedBlocks: ['aksrt/tab'],
template: [['aksrt/tab', { title: '标签 1' }], ['aksrt/tab', { title: '标签 2' }]],
})
)
);
},
save: function (props) {
return h('div', { className: 'aksrt-block-tabs aksrt-block-tabs--' + props.attributes.style },
h(InnerBlocks.Content, null)
);
},
});
registerBlockType('aksrt/tab', {
title: '标签页项',
icon: BLOCK_ICON,
category: CATEGORY,
parent: ['aksrt/tabs'],
attributes: {
title: { type: 'string', default: '标签' },
},
edit: function (props) {
return h(Fragment, null,
h(TextControl, {
label: '标签标题',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); }
}),
h('div', { className: 'aksrt-block-tab__content' },
h(InnerBlocks, null)
)
);
},
save: function (props) {
return h('div', { className: 'aksrt-block-tab', 'data-title': props.attributes.title },
h(InnerBlocks.Content, null)
);
},
});
// ================================================================
// 2. EnlighterJS Code Block
// ================================================================
registerBlockType('aksrt/enlighter', {
title: '代码高亮',
icon: 'editor-code',
category: CATEGORY,
description: '带语法高亮的代码块(EnlighterJS)',
attributes: {
code: { type: 'string', default: '' },
language: { type: 'string', default: 'javascript' },
theme: { type: 'string', default: '' },
linenumbers: { type: 'boolean', default: true },
},
edit: function (props) {
return h(Fragment, null,
withInspector('代码块设置',
h(SelectControl, {
label: '语言',
value: props.attributes.language,
options: [
{ label: 'JavaScript', value: 'javascript' },
{ label: 'TypeScript', value: 'typescript' },
{ label: 'PHP', value: 'php' },
{ label: 'Python', value: 'python' },
{ label: 'Java', value: 'java' },
{ label: 'C/C++', value: 'cpp' },
{ label: 'C#', value: 'csharp' },
{ label: 'Go', value: 'go' },
{ label: 'Rust', value: 'rust' },
{ label: 'Ruby', value: 'ruby' },
{ label: 'Swift', value: 'swift' },
{ label: 'Kotlin', value: 'kotlin' },
{ label: 'HTML', value: 'html' },
{ label: 'CSS/SCSS', value: 'css' },
{ label: 'SQL', value: 'sql' },
{ label: 'Shell/Bash', value: 'shell' },
{ label: 'JSON', value: 'json' },
{ label: 'YAML', value: 'yaml' },
{ label: 'Markdown', value: 'markdown' },
{ label: 'Docker', value: 'dockerfile' },
{ label: 'Diff', value: 'diff' },
{ label: 'XML', value: 'xml' },
],
onChange: function (v) { props.setAttributes({ language: v }); }
}),
h(ToggleControl, {
label: '显示行号',
checked: props.attributes.linenumbers,
onChange: function (v) { props.setAttributes({ linenumbers: v }); }
})
),
h('div', { className: 'aksrt-block-enlighter' },
h('div', { className: 'aksrt-block-enlighter__header' },
h('span', { className: 'aksrt-block-enlighter__lang' }, props.attributes.language)
),
h('textarea', {
className: 'aksrt-block-enlighter__code',
value: props.attributes.code,
onChange: function (e) { props.setAttributes({ code: e.target.value }); },
placeholder: '在此输入代码...',
rows: 10,
spellCheck: false,
})
)
);
},
save: function (props) {
var attrs = {
className: 'gl',
'data-enlighter-language': props.attributes.language,
};
if (props.attributes.theme) attrs['data-enlighter-theme'] = props.attributes.theme;
if (!props.attributes.linenumbers) attrs['data-enlighter-linenumbers'] = 'false';
return h('pre', { className: 'enlighter-pre' },
h('code', attrs, props.attributes.code)
);
},
});
// ================================================================
// 3. Quote Block
// ================================================================
registerBlockType('aksrt/quote-styled', {
title: '样式引用',
icon: 'editor-quote',
category: CATEGORY,
description: '带颜色样式的引用块',
attributes: {
content: { type: 'string', default: '' },
style: { type: 'string', default: 'gray' },
cite: { type: 'string', default: '' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('引用设置',
h(SelectControl, {
label: '样式',
value: props.attributes.style,
options: [
{ label: '灰色', value: 'gray' },
{ label: '蓝色', value: 'blue' },
{ label: '绿色', value: 'green' },
{ label: '红色', value: 'red' },
{ label: '黄色', value: 'yellow' },
],
onChange: function (v) { props.setAttributes({ style: v }); }
}),
h(TextControl, {
label: '来源',
value: props.attributes.cite,
onChange: function (v) { props.setAttributes({ cite: v }); }
})
),
h('blockquote', { className: 'aksrt-block-quote aksrt-block-quote--' + props.attributes.style },
h(RichText, {
tagName: 'p',
value: props.attributes.content,
onChange: function (v) { props.setAttributes({ content: v }); },
placeholder: '输入引用内容...',
}),
props.attributes.cite ? h('cite', null, props.attributes.cite) : null
)
);
},
save: function (props) {
return h('blockquote', { className: 'aksrt-block-quote aksrt-block-quote--' + props.attributes.style },
h(RichText.Content, { tagName: 'p', value: props.attributes.content }),
props.attributes.cite ? h('cite', null, props.attributes.cite) : null
);
},
});
// ================================================================
// 4. Alert Block
// ================================================================
registerBlockType('aksrt/alert', {
title: '提示框',
icon: 'warning',
category: CATEGORY,
description: '通知/警告/成功/信息提示框',
attributes: {
content: { type: 'string', default: '' },
type: { type: 'string', default: 'info' },
dismissible: { type: 'boolean', default: false },
},
edit: function (props) {
return h(Fragment, null,
withInspector('提示框设置',
h(SelectControl, {
label: '类型',
value: props.attributes.type,
options: [
{ label: '信息', value: 'info' },
{ label: '成功', value: 'success' },
{ label: '警告', value: 'warning' },
{ label: '错误', value: 'error' },
],
onChange: function (v) { props.setAttributes({ type: v }); }
}),
h(ToggleControl, {
label: '可关闭',
checked: props.attributes.dismissible,
onChange: function (v) { props.setAttributes({ dismissible: v }); }
})
),
h('div', {
className: 'aksrt-block-alert aksrt-block-alert--' + props.attributes.type +
(props.attributes.dismissible ? ' aksrt-block-alert--dismissible' : '')
},
h(RichText, {
tagName: 'p',
value: props.attributes.content,
onChange: function (v) { props.setAttributes({ content: v }); },
placeholder: '输入提示内容...',
})
)
);
},
save: function (props) {
var cls = 'aksrt-block-alert aksrt-block-alert--' + props.attributes.type;
if (props.attributes.dismissible) cls += ' aksrt-block-alert--dismissible';
return h('div', { className: cls, role: 'alert' },
h(RichText.Content, { tagName: 'p', value: props.attributes.content }),
props.attributes.dismissible ? h('button', { type: 'button', className: 'aksrt-block-alert__close', 'aria-label': '关闭' }, '×') : null
);
},
});
// ================================================================
// 5. Buttons Block
// ================================================================
registerBlockType('aksrt/buttons', {
title: '按钮组',
icon: 'button',
category: CATEGORY,
description: '多个按钮组合',
attributes: {
align: { type: 'string', default: 'left' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('按钮组设置',
h(SelectControl, {
label: '对齐',
value: props.attributes.align,
options: [
{ label: '左对齐', value: 'left' },
{ label: '居中', value: 'center' },
{ label: '右对齐', value: 'right' },
],
onChange: function (v) { props.setAttributes({ align: v }); }
})
),
h('div', { className: 'aksrt-block-buttons aksrt-block-buttons--' + props.attributes.align },
h(InnerBlocks, {
allowedBlocks: ['aksrt/button'],
template: [['aksrt/button', { text: '按钮', style: 'primary' }]],
})
)
);
},
save: function (props) {
return h('div', { className: 'aksrt-block-buttons aksrt-block-buttons--' + props.attributes.align },
h(InnerBlocks.Content, null)
);
},
});
registerBlockType('aksrt/button', {
title: '按钮',
icon: 'button',
category: CATEGORY,
parent: ['aksrt/buttons'],
attributes: {
text: { type: 'string', default: '按钮' },
url: { type: 'string', default: '' },
style: { type: 'string', default: 'primary' },
size: { type: 'string', default: 'md' },
newTab: { type: 'boolean', default: false },
},
edit: function (props) {
return h(Fragment, null,
withInspector('按钮设置',
h(TextControl, {
label: '链接',
value: props.attributes.url,
onChange: function (v) { props.setAttributes({ url: v }); }
}),
h(SelectControl, {
label: '样式',
value: props.attributes.style,
options: [
{ label: '主要', value: 'primary' },
{ label: '次要', value: 'secondary' },
{ label: '轮廓', value: 'outline' },
{ label: '幽灵', value: 'ghost' },
],
onChange: function (v) { props.setAttributes({ style: v }); }
}),
h(SelectControl, {
label: '大小',
value: props.attributes.size,
options: [
{ label: '小', value: 'sm' },
{ label: '中', value: 'md' },
{ label: '大', value: 'lg' },
],
onChange: function (v) { props.setAttributes({ size: v }); }
}),
h(ToggleControl, {
label: '新窗口打开',
checked: props.attributes.newTab,
onChange: function (v) { props.setAttributes({ newTab: v }); }
})
),
h(RichText, {
tagName: 'span',
className: 'aksrt-block-btn aksrt-block-btn--' + props.attributes.style + ' aksrt-block-btn--' + props.attributes.size,
value: props.attributes.text,
onChange: function (v) { props.setAttributes({ text: v }); },
placeholder: '按钮文字...',
withoutInteractiveFormatting: true,
})
);
},
save: function (props) {
var linkProps = {
className: 'aksrt-block-btn aksrt-block-btn--' + props.attributes.style + ' aksrt-block-btn--' + props.attributes.size,
};
if (props.attributes.url) {
linkProps.href = props.attributes.url;
if (props.attributes.newTab) {
linkProps.target = '_blank';
linkProps.rel = 'noopener noreferrer';
}
return h('a', linkProps, props.attributes.text);
}
return h('span', linkProps, props.attributes.text);
},
});
// ================================================================
// 6. Collapse Block
// ================================================================
registerBlockType('aksrt/collapse', {
title: '折叠面板',
icon: 'arrow-down',
category: CATEGORY,
description: '可展开/收起的内容面板',
attributes: {
title: { type: 'string', default: '点击展开' },
open: { type: 'boolean', default: false },
},
edit: function (props) {
return h(Fragment, null,
withInspector('折叠面板设置',
h(ToggleControl, {
label: '默认展开',
checked: props.attributes.open,
onChange: function (v) { props.setAttributes({ open: v }); }
})
),
h('div', { className: 'aksrt-block-collapse' },
h('div', { className: 'aksrt-block-collapse__header' },
h(RichText, {
tagName: 'span',
className: 'aksrt-block-collapse__title',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); },
placeholder: '面板标题...',
}),
h('span', { className: 'aksrt-block-collapse__arrow' }, '▼')
),
h('div', { className: 'aksrt-block-collapse__body' },
h(InnerBlocks, null)
)
)
);
},
save: function (props) {
return h('details', {
className: 'aksrt-block-collapse',
open: props.attributes.open ? true : undefined,
},
h('summary', { className: 'aksrt-block-collapse__header' },
h('span', { className: 'aksrt-block-collapse__title' }, props.attributes.title)
),
h('div', { className: 'aksrt-block-collapse__body' },
h(InnerBlocks.Content, null)
)
);
},
});
// ================================================================
// 7. Feature Grid Block
// ================================================================
registerBlockType('aksrt/feature', {
title: '特性网格',
icon: 'grid-view',
category: CATEGORY,
description: '图标+标题+描述的特性展示网格',
attributes: {
columns: { type: 'number', default: 3 },
},
edit: function (props) {
return h(Fragment, null,
withInspector('特性网格设置',
h(RangeControl, {
label: '列数',
value: props.attributes.columns,
min: 2,
max: 4,
onChange: function (v) { props.setAttributes({ columns: v }); }
})
),
h('div', { className: 'aksrt-block-feature aksrt-block-feature--cols-' + props.attributes.columns },
h(InnerBlocks, {
allowedBlocks: ['aksrt/feature-item'],
template: [
['aksrt/feature-item', { icon: 'fa fas fa-star', title: '特性一', desc: '特性描述' }],
['aksrt/feature-item', { icon: 'fa fas fa-heart', title: '特性二', desc: '特性描述' }],
['aksrt/feature-item', { icon: 'fa fas fa-bolt', title: '特性三', desc: '特性描述' }],
],
})
)
);
},
save: function (props) {
return h('div', { className: 'aksrt-block-feature aksrt-block-feature--cols-' + props.attributes.columns },
h(InnerBlocks.Content, null)
);
},
});
registerBlockType('aksrt/feature-item', {
title: '特性项',
icon: 'star-filled',
category: CATEGORY,
parent: ['aksrt/feature'],
attributes: {
icon: { type: 'string', default: 'fa fas fa-star' },
title: { type: 'string', default: '' },
desc: { type: 'string', default: '' },
},
edit: function (props) {
return h('div', { className: 'aksrt-block-feature__item' },
h(TextControl, {
label: '图标类名',
value: props.attributes.icon,
onChange: function (v) { props.setAttributes({ icon: v }); }
}),
h('i', { className: props.attributes.icon + ' aksrt-block-feature__icon' }),
h(RichText, {
tagName: 'h3',
className: 'aksrt-block-feature__title',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); },
placeholder: '标题...',
}),
h(RichText, {
tagName: 'p',
className: 'aksrt-block-feature__desc',
value: props.attributes.desc,
onChange: function (v) { props.setAttributes({ desc: v }); },
placeholder: '描述...',
})
);
},
save: function (props) {
return h('div', { className: 'aksrt-block-feature__item' },
h('i', { className: props.attributes.icon + ' aksrt-block-feature__icon' }),
h('h3', { className: 'aksrt-block-feature__title' }, props.attributes.title),
h('p', { className: 'aksrt-block-feature__desc' }, props.attributes.desc)
);
},
});
// ================================================================
// 8. Responsive Iframe Block
// ================================================================
registerBlockType('aksrt/iframe', {
title: '响应式嵌入',
icon: 'video-alt3',
category: CATEGORY,
description: '响应式 iframe 嵌入(视频、地图等)',
attributes: {
src: { type: 'string', default: '' },
ratio: { type: 'string', default: '16:9' },
title: { type: 'string', default: '' },
},
edit: function (props) {
return h(Fragment, null,
withInspector('嵌入设置',
h(TextControl, {
label: 'URL',
value: props.attributes.src,
onChange: function (v) { props.setAttributes({ src: v }); }
}),
h(SelectControl, {
label: '宽高比',
value: props.attributes.ratio,
options: [
{ label: '16:9', value: '16:9' },
{ label: '4:3', value: '4:3' },
{ label: '1:1', value: '1:1' },
{ label: '自适应', value: 'auto' },
],
onChange: function (v) { props.setAttributes({ ratio: v }); }
}),
h(TextControl, {
label: '标题',
value: props.attributes.title,
onChange: function (v) { props.setAttributes({ title: v }); }
})
),
h('div', { className: 'aksrt-block-iframe aksrt-block-iframe--' + props.attributes.ratio.replace(':', '-') },
props.attributes.src
? h('iframe', { src: props.attributes.src, title: props.attributes.title || '嵌入内容', allowfullscreen: true })
: h('div', { className: 'aksrt-block-iframe__placeholder' }, '请输入嵌入 URL')
)
);
},
save: function (props) {
return h('div', { className: 'aksrt-block-iframe aksrt-block-iframe--' + props.attributes.ratio.replace(':', '-') },
h('iframe', {
src: props.attributes.src,
title: props.attributes.title || '嵌入内容',
allowfullscreen: true,
loading: 'lazy',
})
);
},
});
// ── Carousel Block (Gallery → Swiper) ──
// MediaUpload lives on wp.blockEditor; skip registration if unavailable.
if (MediaUpload) {
registerBlockType('aksrt/carousel', {
title: '轮播图',
icon: 'images-alt2',
category: CATEGORY,
description: '图片轮播/幻灯片(基于 Swiper)',
attributes: {
images: { type: 'array', default: [] },
autoplay: { type: 'boolean', default: true },
delay: { type: 'number', default: 3000 },
effect: { type: 'string', default: 'slide' },
},
edit: function (props) {
var attrs = props.attributes;
var setAttributes = props.setAttributes;
var onSelectImages = function (media) {
setAttributes({
images: media.map(function (m) {
return { url: m.url, alt: m.alt || '', id: m.id };
}),
});
};
var inspector = h(InspectorControls, { key: 'insp' },
h(PanelBody, { title: '轮播设置' },
h(ToggleControl, {
label: '自动播放',
checked: attrs.autoplay,
onChange: function (v) { setAttributes({ autoplay: v }); },
}),
h(RangeControl, {
label: '切换间隔(毫秒)',
value: attrs.delay,
min: 1000,
max: 10000,
step: 500,
onChange: function (v) { setAttributes({ delay: v }); },
}),
h(SelectControl, {
label: '切换效果',
value: attrs.effect,
options: [
{ label: '滑动', value: 'slide' },
{ label: '淡入淡出', value: 'fade' },
{ label: '立方体', value: 'cube' },
],
onChange: function (v) { setAttributes({ effect: v }); },
})
)
);
var preview = attrs.images.length > 0
? h('div', { className: 'aksrt-carousel-preview', style: { display: 'flex', gap: '8px', flexWrap: 'wrap' } },
attrs.images.map(function (img, i) {
return h('img', {
key: i,
src: img.url,
alt: img.alt,
style: { width: '120px', height: '80px', objectFit: 'cover', borderRadius: '6px' },
});
})
)
: h('p', { style: { color: '#999', textAlign: 'center', padding: '20px' } }, '请选择图片');
return h(Fragment, null,
inspector,
h('div', { className: 'aksrt-carousel-block' },
preview,
h(MediaUpload, {
onSelect: onSelectImages,
allowedTypes: ['image'],
multiple: true,
value: attrs.images.map(function (img) { return img.id; }),
render: function (obj) {
return h(wp.components.Button, {
onClick: obj.open,
variant: 'secondary',
style: { marginTop: '8px' },
}, attrs.images.length ? '重新选择图片' : '选择图片');
},
})
)
);
},
save: function () {
// Dynamic block — rendered via PHP
return null;
},
});
}
// ================================================================
// 9. Paid Fragment Block
// ================================================================
function usePaidReadingConfigured() {
if (!useSelect) return true;
return useSelect(function (select) {
var editor = select('core/editor');
if (!editor || !editor.getEditedPostAttribute) return true;
var meta = editor.getEditedPostAttribute('meta') || {};
var pay = meta._aksrt_pay || {};
if (pay.pay_type !== 'reading') return false;
return pay.pay_modo === 'points'
? Number(pay.points_price || 0) > 0
: Number(pay.price || 0) > 0;
}, []);
}
registerBlockType('aksrt/paid-fragment', {
title: '付费可见',
icon: 'lock',
category: CATEGORY,
description: '仅购买文章付费阅读后可见的片段。',
attributes: {
content: { type: 'string', default: '' },
},
edit: function (props) {
var configured = usePaidReadingConfigured();
return h('div', { className: 'aksrt-paid-fragment-block' },
!configured && Notice ? h(Notice, { status: 'warning', isDismissible: false },
'请在“付费内容设置”中选择“付费阅读”并设置有效价格;未配置时此片段会公开显示。'
) : null,
h('div', { className: 'aksrt-paid-fragment-block__label' },
h('span', { className: 'dashicons dashicons-lock', 'aria-hidden': true }),
'付费可见片段'
),
h(RichText, {
tagName: 'div',
className: 'aksrt-paid-fragment-block__content',
value: props.attributes.content,
onChange: function (value) { props.setAttributes({ content: value }); },
placeholder: '输入购买后可见的内容…',
})
);
},
save: function (props) {
// Save a single canonical shortcode so hand-written and block-authored
// content use the identical server-side rendering path.
var shortcode = '[hidecontent type="payshow"]' + props.attributes.content + '[/hidecontent]';
return RawHTML ? h(RawHTML, null, shortcode) : shortcode;
},
});
})();