进行了一些小修复

This commit is contained in:
2026-08-26 16:59:42 +08:00
parent b80ac46147
commit 5121b33ad5
8 changed files with 663 additions and 86 deletions
@@ -0,0 +1,44 @@
/* Content shown inside the front-submit TinyMCE iframe. */
.tinymce-hide {
position: relative;
margin: 18px 0;
padding: 38px 14px 14px;
border: 1px dashed rgba(240, 68, 148, 0.35);
border-radius: 6px;
background: rgba(240, 68, 148, 0.04);
}
.tinymce-hide > .hide-before,
.tinymce-hide > .hide-after {
margin: 0;
color: #f04494;
font-family: Consolas, Monaco, monospace;
font-size: 12px;
line-height: 1.5;
}
.tinymce-hide > .hide-before {
position: absolute;
top: 10px;
left: 14px;
}
.tinymce-hide > .hide-after {
margin-top: 8px;
}
.tinymce-hide > [contenteditable="true"] {
min-height: 38px;
padding: 10px;
border-radius: 4px;
background: rgba(255, 255, 255, 0.75);
outline: 0;
}
.tinymce-hide > [contenteditable="true"] > :first-child {
margin-top: 0;
}
.tinymce-hide > [contenteditable="true"] > :last-child {
margin-bottom: 0;
}
+175 -6
View File
@@ -117,16 +117,170 @@
opacity: 1; opacity: 1;
} }
.newposts-editor-tools { .aksrt-editor-media {
position: fixed;
z-index: 100080;
inset: 0;
display: flex; display: flex;
flex-wrap: wrap; align-items: center;
gap: 6px; justify-content: center;
padding: 8px 0 0; padding: 10px;
} }
.newposts-editor-tools .but { .aksrt-editor-media__backdrop {
padding: 4px 9px; position: absolute;
inset: 0;
width: 100%;
height: 100%;
padding: 0;
border: 0;
background: rgba(0, 0, 0, 0.45);
cursor: default;
}
.aksrt-editor-media__dialog {
position: relative;
z-index: 1;
width: min(620px, calc(100vw - 20px));
max-height: calc(100vh - 20px);
overflow: hidden auto;
border-radius: var(--main-radius, 8px);
background: var(--main-bg-color, #fff);
box-shadow: 0 18px 60px rgba(0, 0, 0, 0.2);
}
.aksrt-editor-media__close {
position: absolute;
z-index: 2;
top: 8px;
right: 10px;
width: 34px;
height: 34px;
padding: 0;
border: 0;
background: transparent;
color: var(--muted-color, #777);
font-size: 26px;
line-height: 34px;
cursor: pointer;
}
.aksrt-editor-media__title {
margin: 0;
padding: 18px 54px 14px 20px;
font-size: 17px;
line-height: 1.4;
}
.aksrt-editor-media__tabs {
display: flex;
gap: 24px;
padding: 0 20px;
border-bottom: 1px solid var(--main-border-color, rgba(50, 50, 50, 0.08));
}
.aksrt-editor-media__tabs button {
position: relative;
padding: 10px 2px 12px;
border: 0;
background: transparent;
color: var(--muted-color, #777);
font-size: 14px;
cursor: pointer;
}
.aksrt-editor-media__tabs button.is-active {
color: var(--focus-color, #f04494);
}
.aksrt-editor-media__tabs button.is-active::after {
position: absolute;
right: 0;
bottom: -1px;
left: 0;
height: 2px;
border-radius: 2px;
background: currentColor;
content: '';
}
.aksrt-editor-media__panel {
display: none;
padding: 20px;
}
.aksrt-editor-media__panel.is-active {
display: block;
}
.aksrt-editor-media__panel > p {
margin: 0 0 10px;
color: var(--muted-color, #777);
font-size: 13px;
}
.aksrt-editor-media__panel textarea {
width: 100%;
min-height: 120px;
resize: vertical;
}
.aksrt-editor-media__drop {
display: flex;
min-height: 180px;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 8px;
padding: 20px;
border: 2px dashed var(--main-border-color, rgba(50, 50, 50, 0.12));
border-radius: var(--main-radius, 8px);
background: var(--muted-border-color, rgba(50, 50, 50, 0.03));
color: var(--muted-color, #777);
text-align: center;
cursor: pointer;
transition: 0.2s;
}
.aksrt-editor-media__drop:hover,
.aksrt-editor-media__drop.is-dragging {
border-color: var(--focus-color, #f04494);
background: rgba(240, 68, 148, 0.06);
color: var(--focus-color, #f04494);
}
.aksrt-editor-media__drop input {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
}
.aksrt-editor-media__drop i {
font-size: 34px;
}
.aksrt-editor-media__drop span {
font-size: 12px; font-size: 12px;
opacity: 0.75;
}
.aksrt-editor-media__selection {
min-height: 20px;
margin-top: 10px;
color: var(--muted-color, #777);
font-size: 13px;
}
.aksrt-editor-media__submit {
display: block;
min-width: 110px;
margin: 14px 0 0 auto;
}
body.aksrt-editor-media-open {
overflow: hidden;
} }
.featured-edit { .featured-edit {
@@ -402,6 +556,21 @@
margin: 2px; margin: 2px;
} }
.aksrt-editor-media {
align-items: flex-end;
padding: 0;
}
.aksrt-editor-media__dialog {
width: 100%;
max-height: 88vh;
border-radius: 12px 12px 0 0;
}
.aksrt-editor-media__drop {
min-height: 150px;
}
.pay-dawnload-edit .lists-item { .pay-dawnload-edit .lists-item {
align-items: stretch; align-items: stretch;
flex-direction: column; flex-direction: column;
+362
View File
@@ -0,0 +1,362 @@
/**
* Front-submit TinyMCE tools matching the reference article editor.
*
* @package AKSRT
*/
(function (window, document) {
'use strict';
if (!window.tinymce || !window.tinymce.PluginManager) {
return;
}
var cfg = window.aksrtSubmitData || {};
var editorCfg = cfg.editor || {};
var i18n = cfg.i18n || {};
var activeModal = null;
function notify(message, type, duration, id) {
if (typeof window.notyf === 'function') {
window.notyf(
message,
type,
duration === undefined ? 5 : duration,
id || 'aksrt-front-submit-editor-image-toast'
);
}
}
function escapeAttr(value) {
return String(value)
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
function validImageUrl(value) {
var raw = String(value).trim();
if (!/^https?:\/\//i.test(raw)) {
return '';
}
try {
var url = new URL(raw);
return url.protocol === 'http:' || url.protocol === 'https:' ? url.href : '';
} catch (error) {
return '';
}
}
function imageMarkup(url, attachmentId, alt) {
var safeUrl = validImageUrl(url);
if (!safeUrl) {
return '';
}
var idAttr = attachmentId ? ' data-edit-file-id="' + Number(attachmentId) + '"' : '';
var altAttr = alt ? ' alt="' + escapeAttr(alt) + '"' : ' alt=""';
return '<p><img src="' + escapeAttr(safeUrl) + '"' + idAttr + altAttr + '></p>';
}
function closeImageModal() {
if (!activeModal) {
return;
}
document.removeEventListener('keydown', activeModal.onKeydown);
activeModal.root.remove();
activeModal = null;
document.body.classList.remove('aksrt-editor-media-open');
}
function uploadImage(file) {
var upload = (cfg.uploads || {}).image || null;
if (!upload || !upload.url) {
return Promise.reject(new Error(i18n.uploadUnavailable || '当前账号不能上传图片'));
}
if (!file || !/^image\//.test(file.type || '')) {
return Promise.reject(new Error(i18n.invalidImage || '请选择有效的图片文件'));
}
if (upload.maxSize && file.size > upload.maxSize) {
return Promise.reject(new Error(i18n.fileTooLarge || '文件大小超过限制'));
}
var body = new FormData();
body.append('file', file);
return fetch(upload.url, {
method: 'POST',
credentials: 'same-origin',
headers: { 'X-WP-Nonce': cfg.restNonce || '' },
body: body,
}).then(function (response) {
return response.json().catch(function () {
return {};
}).then(function (payload) {
if (!response.ok || !payload || !payload.success || !payload.url) {
throw new Error((payload && payload.message) || i18n.error || '图片上传失败');
}
return payload;
});
});
}
function createImageModal(editor) {
closeImageModal();
var canUpload = !!editorCfg.canUploadImage && !!((cfg.uploads || {}).image);
var root = document.createElement('div');
root.className = 'aksrt-editor-media';
root.setAttribute('role', 'dialog');
root.setAttribute('aria-modal', 'true');
root.setAttribute('aria-labelledby', 'aksrt-editor-media-title');
root.innerHTML =
'<button type="button" class="aksrt-editor-media__backdrop" data-editor-media-close tabindex="-1" aria-label="' +
escapeAttr(i18n.close || '关闭') + '"></button>' +
'<div class="aksrt-editor-media__dialog">' +
'<button type="button" class="aksrt-editor-media__close" data-editor-media-close aria-label="' +
escapeAttr(i18n.close || '关闭') + '">&times;</button>' +
'<h3 id="aksrt-editor-media-title" class="aksrt-editor-media__title">' +
escapeAttr(i18n.insertImage || '插入图片') + '</h3>' +
'<div class="aksrt-editor-media__tabs" role="tablist">' +
(canUpload
? '<button type="button" class="is-active" role="tab" aria-selected="true" data-editor-media-tab="upload">' +
escapeAttr(i18n.uploadImage || '上传图片') + '</button>'
: '') +
'<button type="button" class="' + (canUpload ? '' : 'is-active') + '" role="tab" aria-selected="' +
(canUpload ? 'false' : 'true') + '" data-editor-media-tab="external">' +
escapeAttr(i18n.externalImage || '外链图片') + '</button>' +
'</div>' +
'<div class="aksrt-editor-media__panels">' +
(canUpload
? '<section class="aksrt-editor-media__panel is-active" data-editor-media-panel="upload">' +
'<label class="aksrt-editor-media__drop">' +
'<input type="file" accept="image/gif,image/jpeg,image/png,image/webp" multiple data-editor-media-files>' +
'<i class="fa fas fa-cloud-upload-alt" aria-hidden="true"></i>' +
'<strong>' + escapeAttr(i18n.selectImages || '选择或拖入图片') + '</strong>' +
'<span>' + escapeAttr(i18n.imageUploadHint || '可批量选择,上传完成后自动插入正文') + '</span>' +
'</label>' +
'<div class="aksrt-editor-media__selection" data-editor-media-selection></div>' +
'<button type="button" class="but c-blue aksrt-editor-media__submit" data-editor-media-upload disabled>' +
escapeAttr(i18n.confirmUpload || '确认上传') + '</button>' +
'</section>'
: '') +
'<section class="aksrt-editor-media__panel ' + (canUpload ? '' : 'is-active') + '" data-editor-media-panel="external">' +
'<p>' + escapeAttr(i18n.externalImageHint || '每行填写一个图片地址:') + '</p>' +
'<textarea class="form-control" rows="5" placeholder="https://..." data-editor-media-urls></textarea>' +
'<button type="button" class="but c-blue aksrt-editor-media__submit" data-editor-media-external>' +
escapeAttr(i18n.confirmInsert || '确认插入') + '</button>' +
'</section>' +
'</div>' +
'</div>';
document.body.appendChild(root);
document.body.classList.add('aksrt-editor-media-open');
var fileInput = root.querySelector('[data-editor-media-files]');
var uploadButton = root.querySelector('[data-editor-media-upload]');
var selection = root.querySelector('[data-editor-media-selection]');
var drop = root.querySelector('.aksrt-editor-media__drop');
var files = [];
function showSelection() {
if (!selection || !uploadButton) {
return;
}
selection.textContent = files.length
? (i18n.selectedImages || '已选择 %d 张图片').replace('%d', String(files.length))
: '';
uploadButton.disabled = files.length === 0;
}
function setFiles(nextFiles) {
files = Array.prototype.filter.call(nextFiles || [], function (file) {
return /^image\//.test(file.type || '');
});
showSelection();
}
root.addEventListener('click', function (event) {
var close = event.target.closest('[data-editor-media-close]');
if (close) {
event.preventDefault();
closeImageModal();
return;
}
var tab = event.target.closest('[data-editor-media-tab]');
if (tab) {
var name = tab.getAttribute('data-editor-media-tab');
root.querySelectorAll('[data-editor-media-tab]').forEach(function (item) {
var active = item === tab;
item.classList.toggle('is-active', active);
item.setAttribute('aria-selected', active ? 'true' : 'false');
});
root.querySelectorAll('[data-editor-media-panel]').forEach(function (panel) {
panel.classList.toggle('is-active', panel.getAttribute('data-editor-media-panel') === name);
});
return;
}
if (event.target.closest('[data-editor-media-external]')) {
var textarea = root.querySelector('[data-editor-media-urls]');
var urls = String(textarea ? textarea.value : '').split(/\r?\n/);
var html = urls.map(function (url) {
return imageMarkup(url, 0, '');
}).join('');
if (!html) {
notify(i18n.invalidImageUrl || '请填写有效的图片地址', 'warning');
return;
}
editor.insertContent(html + '<p></p>');
editor.nodeChanged();
closeImageModal();
return;
}
if (event.target.closest('[data-editor-media-upload]')) {
if (!files.length || !uploadButton) {
return;
}
uploadButton.disabled = true;
uploadButton.textContent = i18n.uploading || '正在上传…';
notify(i18n.uploading || '正在上传正文图片…', 'load', '');
Promise.all(files.map(uploadImage)).then(function (items) {
var html = items.map(function (item) {
return imageMarkup(item.url, item.attachment_id, item.name || '');
}).join('');
if (!html) {
throw new Error(i18n.error || '图片上传失败');
}
editor.insertContent(html + '<p></p>');
editor.nodeChanged();
notify(i18n.uploaded || '正文图片上传成功', 'success');
closeImageModal();
}).catch(function (error) {
notify(error.message || i18n.error || '正文图片上传失败', 'danger');
uploadButton.disabled = false;
uploadButton.textContent = i18n.confirmUpload || '确认上传';
});
}
});
if (fileInput) {
fileInput.addEventListener('change', function () {
setFiles(fileInput.files);
});
}
if (drop) {
['dragenter', 'dragover'].forEach(function (name) {
drop.addEventListener(name, function (event) {
event.preventDefault();
drop.classList.add('is-dragging');
});
});
['dragleave', 'drop'].forEach(function (name) {
drop.addEventListener(name, function (event) {
event.preventDefault();
drop.classList.remove('is-dragging');
});
});
drop.addEventListener('drop', function (event) {
setFiles(event.dataTransfer && event.dataTransfer.files);
});
}
var onKeydown = function (event) {
if (event.key === 'Escape') {
closeImageModal();
}
};
activeModal = { root: root, onKeydown: onKeydown };
document.addEventListener('keydown', onKeydown);
var focusTarget = root.querySelector('[data-editor-media-tab].is-active');
if (focusTarget) {
focusTarget.focus();
}
}
function selectedContent(editor) {
var content = String(editor.selection.getContent() || '').trim();
return content ? '<p>' + content + '</p>' : '<p>' + escapeAttr(i18n.hiddenPlaceholder || '隐藏内容') + '</p>';
}
function insertHiddenContent(editor, item) {
var node = editor.selection.getNode();
var content = selectedContent(editor);
var suffix = '<p></p>';
if (node && editor.dom.hasClass(node, 'tinymce-hide')) {
var editable = node.querySelector('[contenteditable="true"]');
content = editable ? editable.innerHTML : content;
editor.dom.remove(node);
suffix = '';
}
editor.insertContent(
'<div class="tinymce-hide" data-aksrt-hide-type="' + escapeAttr(item.type) + '" contenteditable="false">' +
'<p class="hide-before">' + escapeAttr(item.open) + '</p>' +
'<div contenteditable="true">' + content + '</div>' +
'<p class="hide-after">' + escapeAttr(item.close) + '</p>' +
'</div>' + suffix
);
editor.nodeChanged();
}
window.tinymce.PluginManager.add('aksrt_editor_tools', function (editor) {
if (editorCfg.canUploadImage) {
editor.addButton('aksrt_image', {
text: '',
icon: 'image',
tooltip: i18n.insertImage || '插入图片',
onclick: function () {
createImageModal(editor);
},
});
}
if (editorCfg.canHide) {
var menu = [
{
text: i18n.replyVisible || '回复可见',
type: 'reply',
open: '[reply]',
close: '[/reply]',
},
{
text: i18n.loginVisible || '登录可见',
type: 'login',
open: '[aksrt_hide mode="login"]',
close: '[/aksrt_hide]',
},
{
text: i18n.vipVisible || 'VIP 可见',
type: 'vip',
open: '[vip]',
close: '[/vip]',
},
];
if (editorCfg.canPay) {
menu.push({
text: i18n.payVisible || '付费可见',
type: 'payshow',
open: '[payshow]',
close: '[/payshow]',
});
}
menu = menu.map(function (item) {
return {
text: item.text,
onclick: function () {
insertHiddenContent(editor, item);
},
};
});
editor.addButton('aksrt_hide', {
text: '',
icon: 'preview',
tooltip: i18n.hiddenContent || '隐藏内容',
type: 'menubutton',
stateSelector: '.tinymce-hide',
menu: menu,
});
}
});
})(window, document);
-51
View File
@@ -32,21 +32,6 @@
return ta ? ta.value : ''; return ta ? ta.value : '';
} }
function insertEditorContent(html) {
if (window.tinymce) {
var ed = window.tinymce.get('post_content');
if (ed) {
ed.focus();
ed.insertContent(html);
return;
}
}
var ta = qs('#post_content') || qs('[name="post_content"]');
if (ta) {
ta.value += html;
}
}
function serializeForm(form) { function serializeForm(form) {
var data = {}; var data = {};
var fd = new FormData(form); var fd = new FormData(form);
@@ -106,7 +91,6 @@
this.bindDraftDelete(); this.bindDraftDelete();
this.bindFeatured(); this.bindFeatured();
this.bindPay(); this.bindPay();
this.bindShortcodes();
this.bindLeaveWarning(); this.bindLeaveWarning();
this.bindAi(); this.bindAi();
this.bindTagActive(); this.bindTagActive();
@@ -659,41 +643,6 @@
} }
}, },
bindShortcodes: function () {
document.addEventListener('click', function (e) {
var btn = e.target.closest('[data-insert-shortcode]');
if (!btn) {
return;
}
e.preventDefault();
if (btn.hasAttribute('data-insert-upload-image')) {
var toastId = 'aksrt-front-submit-editor-image-toast';
App.pickUpload('image', 'image/*').then(function (file) {
if (!file) return null;
notyf(i18n.uploading || '正在上传正文图片…', 'load', '', toastId);
return App.uploadFile('image', file);
}).then(function (file) {
if (!file || !file.url) return;
insertEditorContent('<img src="' + file.url.replace(/"/g, '&quot;') + '" alt="">');
notyf(i18n.uploaded || '正文图片上传成功', 'success', 5, toastId);
}).catch(function (error) {
notyf(error.message || i18n.error || '正文图片上传失败', 'danger', 5, toastId);
});
return;
}
var type = btn.getAttribute('data-insert-shortcode');
if (type === 'hide') {
insertEditorContent('[hidecontent type="login"]' + (i18n.hidePlaceholder || '隐藏内容') + '[/hidecontent]');
} else if (type === 'payshow') {
insertEditorContent('[hidecontent type="payshow"]' + (i18n.payPlaceholder || '付费可见内容') + '[/hidecontent]');
} else if (type === 'reply') {
insertEditorContent('[hidecontent type="reply"]' + (i18n.replyPlaceholder || '回复后可见') + '[/hidecontent]');
} else if (type === 'vip') {
insertEditorContent('[vip]' + (i18n.vipPlaceholder || 'VIP 可见内容') + '[/vip]');
}
});
},
bindAi: function () { bindAi: function () {
var ai = cfg.ai || {}; var ai = cfg.ai || {};
if (!ai.available) { if (!ai.available) {
+24
View File
@@ -86,6 +86,11 @@ if (file_exists($js)) {
'summary' => !empty($ctx['ai_available']), 'summary' => !empty($ctx['ai_available']),
'tags' => !empty($ctx['ai_available']), 'tags' => !empty($ctx['ai_available']),
], ],
'editor' => [
'canUploadImage' => !empty($ctx['can_upload_img']),
'canHide' => !empty($ctx['can_hide']),
'canPay' => !empty($ctx['can_pay']),
],
'uploads' => [ 'uploads' => [
'image' => !empty($ctx['can_upload_img']) ? [ 'image' => !empty($ctx['can_upload_img']) ? [
'url' => esc_url_raw(rest_url('aksrt/v1/front-submit/upload/image')), 'url' => esc_url_raw(rest_url('aksrt/v1/front-submit/upload/image')),
@@ -118,6 +123,25 @@ if (file_exists($js)) {
'pickImage' => __('选择图片', 'aksrt'), 'pickImage' => __('选择图片', 'aksrt'),
'pickVideo' => __('选择视频封面图', 'aksrt'), 'pickVideo' => __('选择视频封面图', 'aksrt'),
'videoUrl' => __('请输入视频地址', 'aksrt'), 'videoUrl' => __('请输入视频地址', 'aksrt'),
'close' => __('关闭', 'aksrt'),
'insertImage' => __('插入图片', 'aksrt'),
'uploadImage' => __('上传图片', 'aksrt'),
'externalImage' => __('外链图片', 'aksrt'),
'selectImages' => __('选择或拖入图片', 'aksrt'),
'imageUploadHint' => __('可批量选择,上传完成后自动插入正文', 'aksrt'),
'selectedImages' => __('已选择 %d 张图片', 'aksrt'),
'confirmUpload' => __('确认上传', 'aksrt'),
'externalImageHint' => __('每行填写一个图片地址:', 'aksrt'),
'confirmInsert' => __('确认插入', 'aksrt'),
'invalidImage' => __('请选择有效的图片文件', 'aksrt'),
'invalidImageUrl' => __('请填写有效的图片地址', 'aksrt'),
'uploadUnavailable' => __('当前账号不能上传图片', 'aksrt'),
'hiddenContent' => __('隐藏内容', 'aksrt'),
'hiddenPlaceholder' => __('隐藏内容', 'aksrt'),
'replyVisible' => __('回复可见', 'aksrt'),
'loginVisible' => __('登录可见', 'aksrt'),
'vipVisible' => __('VIP 可见', 'aksrt'),
'payVisible' => __('付费可见', 'aksrt'),
], ],
]); ]);
} }
+31 -27
View File
@@ -43,8 +43,36 @@ $is_can_new = !empty($ctx['is_can_new']);
<?php else : ?> <?php else : ?>
<div class="newposts-editor"> <div class="newposts-editor">
<?php <?php
$toolbar1 = 'formatselect,bold,italic,bullist,numlist,alignleft,aligncenter,alignright,link,blockquote,code,fullscreen'; $toolbar1 = ['formatselect', 'bold', 'italic', 'bullist', 'numlist', 'alignleft', 'aligncenter', 'alignright', 'link'];
if (!empty($ctx['can_upload_img'])) {
$toolbar1[] = 'aksrt_image';
}
if (!empty($ctx['can_hide'])) {
$toolbar1[] = 'aksrt_hide';
}
$toolbar1 = implode(',', array_merge($toolbar1, ['blockquote', 'code', 'fullscreen']));
$plugins = 'paste,link,lists,fullscreen,wordpress,wplink,charmap'; $plugins = 'paste,link,lists,fullscreen,wordpress,wplink,charmap';
$editor_plugin_path = get_template_directory() . '/assets/js/front-submit-editor.js';
$editor_plugin_url = get_template_directory_uri() . '/assets/js/front-submit-editor.js';
if (file_exists($editor_plugin_path)) {
$editor_plugin_url = add_query_arg('ver', (string) filemtime($editor_plugin_path), $editor_plugin_url);
}
$editor_css_path = get_template_directory() . '/assets/css/frontend/pages/submit-editor.css';
$editor_css_url = get_template_directory_uri() . '/assets/css/frontend/pages/submit-editor.css';
if (file_exists($editor_css_path)) {
$editor_css_url = add_query_arg('ver', (string) filemtime($editor_css_path), $editor_css_url);
}
$external_plugins = static function (array $external, string $editor_id) use ($editor_plugin_url): array {
if ($editor_id === 'post_content') {
$external['aksrt_editor_tools'] = $editor_plugin_url;
}
return $external;
};
$editor_content_css = static function (string $styles) use ($editor_css_url): string {
return $styles . ($styles !== '' ? ',' : '') . $editor_css_url;
};
add_filter('mce_external_plugins', $external_plugins, 10, 2);
add_filter('mce_css', $editor_content_css);
$editor_settings = [ $editor_settings = [
'textarea_name' => 'post_content', 'textarea_name' => 'post_content',
'textarea_rows' => 20, 'textarea_rows' => 20,
@@ -61,34 +89,10 @@ $is_can_new = !empty($ctx['is_can_new']);
], ],
]; ];
wp_editor((string) $ctx['current_content'], 'post_content', $editor_settings); wp_editor((string) $ctx['current_content'], 'post_content', $editor_settings);
remove_filter('mce_external_plugins', $external_plugins, 10);
remove_filter('mce_css', $editor_content_css, 10);
?> ?>
</div> </div>
<?php if (!empty($ctx['can_hide']) || !empty($ctx['can_pay']) || !empty($ctx['can_upload_img'])) : ?>
<div class="newposts-editor-tools">
<?php if (!empty($ctx['can_upload_img'])) : ?>
<button type="button" class="but" data-insert-upload-image>
<i class="fa fas fa-image"></i> <?php esc_html_e('上传图片', 'aksrt'); ?>
</button>
<?php endif; ?>
<?php if (!empty($ctx['can_hide'])) : ?>
<button type="button" class="but" data-insert-shortcode="hide" title="<?php esc_attr_e('插入登录后可见', 'aksrt'); ?>">
<i class="fa fas fa-eye-slash"></i> <?php esc_html_e('登录可见', 'aksrt'); ?>
</button>
<button type="button" class="but" data-insert-shortcode="reply" title="<?php esc_attr_e('插入回复后可见', 'aksrt'); ?>">
<i class="fa fas fa-comment-dots"></i> <?php esc_html_e('回复可见', 'aksrt'); ?>
</button>
<button type="button" class="but" data-insert-shortcode="vip" title="<?php esc_attr_e('插入 VIP 可见', 'aksrt'); ?>">
<i class="fa fas fa-certificate"></i> <?php esc_html_e('VIP 可见', 'aksrt'); ?>
</button>
<?php endif; ?>
<?php if (!empty($ctx['can_pay'])) : ?>
<button type="button" class="but" data-insert-shortcode="payshow" title="<?php esc_attr_e('插入付费可见内容', 'aksrt'); ?>">
<i class="fa fas fa-lock"></i> <?php esc_html_e('付费可见', 'aksrt'); ?>
</button>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?> <?php endif; ?>
<div class="flex ac jsb mt10"> <div class="flex ac jsb mt10">
@@ -49,6 +49,29 @@ test('front submit follows the reference newposts shell and cards', () => {
assert.match(submit, /new-posts-submit/); assert.match(submit, /new-posts-submit/);
}); });
test('front submit image and visibility actions live in the TinyMCE toolbar', () => {
const main = read('templates/parts/submit/editor-main.php');
const page = read('templates/pages/page-submit.php');
const submit = read('assets/js/front-submit.js');
const editor = read('assets/js/front-submit-editor.js');
assert.match(main, /\$toolbar1\[\]\s*=\s*'aksrt_image'/);
assert.match(main, /\$toolbar1\[\]\s*=\s*'aksrt_hide'/);
assert.match(main, /mce_external_plugins/);
assert.match(main, /aksrt_editor_tools/);
assert.match(editor, /PluginManager\.add\('aksrt_editor_tools'/);
assert.match(editor, /addButton\('aksrt_image'/);
assert.match(editor, /addButton\('aksrt_hide'/);
assert.match(editor, /type:\s*'menubutton'/);
assert.match(editor, /data-editor-media-tab="upload"/);
assert.match(editor, /data-editor-media-tab="external"/);
assert.match(editor, /\(cfg\.uploads \|\| \{\}\)\.image/);
assert.match(page, /'canUploadImage'\s*=>\s*!empty\(\$ctx\['can_upload_img'\]\)/);
assert.doesNotMatch(main, /newposts-editor-tools|data-insert-shortcode|data-insert-upload-image/);
assert.doesNotMatch(submit, /bindShortcodes|data-insert-shortcode|data-insert-upload-image/);
assert.doesNotMatch(editor, /hidecontent|shop|forum|bbs_/i);
});
test('article paid-content metabox follows the reference field set without shop enhancements', () => { test('article paid-content metabox follows the reference field set without shop enhancements', () => {
const meta = read('src/Core/ResourceMetaBox.php'); const meta = read('src/Core/ResourceMetaBox.php');
const fields = [ const fields = [
+4 -2
View File
@@ -369,6 +369,8 @@ test('settings actions use rehydrated fixed-id notyf flows', () => {
test('front submit actions use direct fixed-id notyf flows', () => { test('front submit actions use direct fixed-id notyf flows', () => {
const submit = read('assets/js/front-submit.js'); const submit = read('assets/js/front-submit.js');
const editor = read('assets/js/front-submit-editor.js');
const source = submit + '\n' + editor;
const page = read('templates/pages/page-submit.php'); const page = read('templates/pages/page-submit.php');
[ [
@@ -382,7 +384,7 @@ test('front submit actions use direct fixed-id notyf flows', () => {
'aksrt-front-submit-editor-image-toast', 'aksrt-front-submit-editor-image-toast',
'aksrt-front-submit-ai-tags-toast', 'aksrt-front-submit-ai-tags-toast',
'aksrt-front-submit-ai-summary-toast', 'aksrt-front-submit-ai-summary-toast',
].forEach((id) => assert.match(submit, new RegExp("['\"]" + id + "['\"]"))); ].forEach((id) => assert.match(source, new RegExp("['\"]" + id + "['\"]")));
assert.match(submit, /submit: function[\s\S]*?notyf\([^;]+?'load'[^;]+?toastId[\s\S]*?notyf\([^;]+?'success'[^;]+?toastId[\s\S]*?notyf\([^;]+?'danger'[^;]+?toastId/); assert.match(submit, /submit: function[\s\S]*?notyf\([^;]+?'load'[^;]+?toastId[\s\S]*?notyf\([^;]+?'success'[^;]+?toastId[\s\S]*?notyf\([^;]+?'danger'[^;]+?toastId/);
assert.match(submit, /bindDraftDelete: function[\s\S]*?'aksrt-front-submit-delete-draft-toast'[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(submit, /bindDraftDelete: function[\s\S]*?'aksrt-front-submit-delete-draft-toast'[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/);
@@ -398,7 +400,7 @@ test('front submit actions use direct fixed-id notyf flows', () => {
}); });
assert.match(submit, /aksrt-front-submit-resource-upload-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(submit, /aksrt-front-submit-resource-upload-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/);
assert.match(submit, /aksrt-front-submit-editor-image-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(editor, /aksrt-front-submit-editor-image-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/);
assert.match(submit, /aksrt-front-submit-ai-tags-toast[\s\S]*?aksrt-front-submit-ai-summary-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/); assert.match(submit, /aksrt-front-submit-ai-tags-toast[\s\S]*?aksrt-front-submit-ai-summary-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/);
assert.match(submit, /needContent[^;]+?'warning'/); assert.match(submit, /needContent[^;]+?'warning'/);
assert.doesNotMatch(submit, /\b(?:window\.)?alert\s*\(/); assert.doesNotMatch(submit, /\b(?:window\.)?alert\s*\(/);