ASP.NET Core中CKEditor 4 HTML元素默认样式设置及保存时样式随HTML提交的解决方案咨询
你碰到的这个问题很常见——CKEditor的content.css是编辑器自身的显示样式文件,只会作用于编辑器内部的预览,并不会自动嵌入到输出的HTML内容里。所以不管是通过模型绑定拿到的model.Vsebina,还是调用CKEDITOR.instances.Vsebina.getData()获取的内容,都是不带样式的纯结构HTML,这就导致iTextSharp生成PDF时没法应用你想要的段落边距。
下面给你几个可行的解决思路,你可以根据自己的场景选择:
方案1:让CKEditor输出自带inline样式的HTML
直接让编辑器生成的<p>标签自带style属性,这样保存的HTML本身就包含样式信息。
方法A:配置编辑器的默认段落格式
修改你的CKEditor初始化代码,自定义段落格式的样式:
$("#Vsebina.html-text").ckeditor({ // 定义允许的格式标签 format_tags: 'p;h1;h2', // 给p标签设置默认样式 formats: { p: { element: 'p', styles: { 'margin-bottom': '30px' } } }, // 设置默认的段落格式为自定义的p样式 defaultParagraphFormat: 'p' });
这样用户在编辑器里输入的所有段落,都会自动带上style="margin-bottom:30px;"属性,保存后自然就带着样式了。
方法B:通过编辑器事件自动处理内容
如果不想改编辑器的格式配置,也可以在编辑器获取数据的环节,手动给所有<p>标签添加样式:
// 初始化编辑器后绑定getData事件 var editor = CKEDITOR.instances.Vsebina; editor.on('getData', function(e) { // 替换所有<p>标签为带样式的版本(兼容带属性的<p>标签) e.data.dataValue = e.data.dataValue.replace(/<p([^>]*)>/g, '<p$1 style="margin-bottom:30px;">'); });
这样每次调用getData()(包括表单提交时编辑器自动填充到文本框的内容),都会返回带inline样式的HTML,模型绑定自然就能拿到带样式的内容。
方案2:在控制器保存时嵌入全局样式块
如果不想给每个<p>标签加inline样式,可以在控制器里把样式块插到HTML内容的开头,这样iTextSharp解析时会识别并应用这个全局样式:
修改你的Save方法:
public IActionResult Save(VloziscaDetailModel model) { if(ModelState.IsValid) { // 定义需要的CSS样式 var globalStyles = "<style type='text/css'>p { margin-bottom: 30px; }</style>"; // 把样式块加到HTML内容最前面 model.Vsebina = globalStyles + model.Vsebina; item.Vsebina = model.Vsebina; // 后续的业务逻辑... } }
这种方式的好处是不用修改编辑器配置,而且样式是全局的,后续要调整样式只需要改这里的CSS即可,iTextSharp在解析HTML时会读取这个样式块并应用到所有<p>标签上。
方案3:在iTextSharp生成PDF时直接应用样式
如果不想修改保存的原始HTML内容,也可以在PDF生成环节,给iTextSharp指定要应用的样式:
假设你用XMLWorker来解析HTML(iTextSharp推荐用这个替代旧的HtmlWorker),可以这样做:
using iTextSharp.text; using iTextSharp.text.pdf; using iTextSharp.tool.xml; using iTextSharp.tool.xml.css; // 生成PDF的示例代码 var document = new Document(); using (var fs = new FileStream("output.pdf", FileMode.Create)) { PdfWriter.GetInstance(document, fs); document.Open(); // 创建样式表并添加段落的边距样式 var styleSheet = new StyleSheet(); styleSheet.LoadTagStyle("p", "margin-bottom", "30px"); // 解析HTML时应用这个样式表 var workerHelper = XMLWorkerHelper.GetInstance(); using (var sr = new StringReader(model.Vsebina)) { workerHelper.ParseXHtml(document, sr, styleSheet); } document.Close(); }
这种方式的优点是不会改动原始的HTML内容,样式只作用于PDF生成环节,适合不需要在其他地方展示带样式内容的场景。
额外注意点
- 如果你用方案1,要确保CKEditor的内容过滤规则(
allowedContent)允许<p>标签带有style属性。默认情况下CKEditor可能会过滤掉未知属性,所以可以配置:$("#Vsebina.html-text").ckeditor({ allowedContent: 'p[style]; h1 h2;', // 精确允许p标签带style属性,以及h1、h2标签 // 其他配置... }); - iTextSharp对CSS的支持有限,一些复杂的CSS选择器或样式可能无法完全解析,所以优先选择简单的inline样式或者基础的标签样式规则。
内容的提问来源于stack exchange,提问作者TheMixy

