jack 1 dzień temu
rodzic
commit
7baeffb000

+ 23 - 6
src/assets/styles/prosemirror.scss

@@ -15,6 +15,11 @@
   p {
   p {
     margin: 0;
     margin: 0;
   }
   }
+  .empty {
+    margin: 0;
+    font-size: 0;
+    padding: 0;
+  }
   p:first-child {
   p:first-child {
     margin-top: 0;
     margin-top: 0;
     // font-size: 0;
     // font-size: 0;
@@ -25,14 +30,21 @@
   }
   }
   ul {
   ul {
     
     
-    list-style-type: disc;
-    padding-inline-start: 0;
+    list-style-type: none;
+    padding-left: 1.5em;       /* 为伪元素留出空间 */
 
 
-    li {
-      list-style-type: inherit;
-      padding: 0;
+    li::before {
+      content: "•";
+      list-style-type: none;
+      padding: 0.125em 0;
+      float: left;
+      margin-right: 0.4em;
+    }
+
+    li.empty-li::before {
+      font-size: 0;
+      content: none !important;
     }
     }
-    
   }
   }
 
 
   ol {
   ol {
@@ -42,6 +54,11 @@
     li {
     li {
       list-style-type: inherit;
       list-style-type: inherit;
       padding: 0.125em 0;
       padding: 0.125em 0;
+      float: left;
+      margin-right: 0.4em;
+    }
+    li.empty-li::before {
+      content: none !important;
     }
     }
   }
   }
 
 

+ 90 - 8
src/utils/prosemirror/schema/nodes.ts

@@ -24,8 +24,8 @@ const orderedList: NodeSpec = {
   content: 'list_item+',
   content: 'list_item+',
   group: 'block',
   group: 'block',
   parseDOM: [
   parseDOM: [
-    { 
-      tag: 'ol', 
+    {
+      tag: 'ol',
       getAttrs: dom => {
       getAttrs: dom => {
         const order = ((dom as HTMLElement).hasAttribute('start') ? (dom as HTMLElement).getAttribute('start') : 1) || 1
         const order = ((dom as HTMLElement).hasAttribute('start') ? (dom as HTMLElement).getAttribute('start') : 1) || 1
         const attr: Attr = { order: +order }
         const attr: Attr = { order: +order }
@@ -188,9 +188,33 @@ const listItem: NodeSpec = {
     }
     }
     if (marginTop) style += `margin-top: ${marginTop};`;
     if (marginTop) style += `margin-top: ${marginTop};`;
     if (marginBottom) style += `margin-bottom: ${marginBottom};`;
     if (marginBottom) style += `margin-bottom: ${marginBottom};`;
-    if (marginLeft) style += `margin-left: ${marginLeft};`;
+    if (marginLeft) {
+      // 解析数值和单位
+      const str = String(marginLeft).trim();
+      const match = str.match(/^([+-]?\d*\.?\d+)(px|pt|em|rem|%|vw|vh)?$/i);
+      if (match) {
+        let num = parseFloat(match[1]);
+        const unit = match[2] || 'px';
+        const absNum = Math.abs(num); // 负数转正
+        const val = absNum + unit;
+        style += `margin-left: max(min(0px, 100% - ${val}), 0px);`;
+      } else {
+        style += `margin-left: ${marginLeft};`;
+      }
+    }
     if (marginRight) style += `margin-right: ${marginRight};`;
     if (marginRight) style += `margin-right: ${marginRight};`;
-    if (lineHeight) style += `line-height: ${lineHeight * 1.2};`;
+    if (lineHeight) {
+      let finalValue;
+      const str = String(lineHeight).trim();
+      // 匹配纯数字(整数或小数,可带负号)
+      if (/^-?\d+(\.\d+)?$/.test(str)) {
+        finalValue = parseFloat(str) * 1.2;
+      } else {
+        // 带单位或其他非纯数字内容,直接使用原值
+        finalValue = lineHeight;
+      }
+      style += `line-height: ${finalValue};`;
+    }
     if (paddingTop) style += `padding-top: ${paddingTop};`;
     if (paddingTop) style += `padding-top: ${paddingTop};`;
     if (paddingRight) style += `padding-right: ${paddingRight};`;
     if (paddingRight) style += `padding-right: ${paddingRight};`;
     if (paddingBottom) style += `padding-bottom: ${paddingBottom};`;
     if (paddingBottom) style += `padding-bottom: ${paddingBottom};`;
@@ -199,8 +223,23 @@ const listItem: NodeSpec = {
       style += `white-space: ${whiteSpace};`; // 添加 white-space
       style += `white-space: ${whiteSpace};`; // 添加 white-space
     }
     }
 
 
-    const attrs: { style?: string } = {};
+    //const attrs: { style?: string } = {};
+    //if (style) attrs.style = style;
+
+    let isEmpty = false;
+    const firstChild = node.content.firstChild;
+    if (firstChild && firstChild.type.name === 'paragraph') {
+      // 段落无任何子节点(包括 text 和 inline 节点)
+      if (firstChild.content.size === 0) {
+        isEmpty = true;
+      }
+    }
+    // 如果整个 li 的内容长度为 0 也可以作为判断
+    if (node.content.size === 0) isEmpty = true;
+
+    const attrs: { style?: string; class?: string } = {};
     if (style) attrs.style = style;
     if (style) attrs.style = style;
+    if (isEmpty) attrs.class = 'empty-li';
 
 
     return ['li', attrs, 0];
     return ['li', attrs, 0];
   },
   },
@@ -303,9 +342,36 @@ const paragraph: NodeSpec = {
     }
     }
     if (marginTop) style += `margin-top: ${marginTop};`;
     if (marginTop) style += `margin-top: ${marginTop};`;
     if (marginBottom) style += `margin-bottom: ${marginBottom};`;
     if (marginBottom) style += `margin-bottom: ${marginBottom};`;
+    /*
+    if (marginLeft) {
+      // 解析数值和单位
+      const str = String(marginLeft).trim();
+      const match = str.match(/^([+-]?\d*\.?\d+)(px|pt|em|rem|%|vw|vh)?$/i);
+      if (match) {
+        let num = parseFloat(match[1]);
+        const unit = match[2] || 'px';
+        const absNum = Math.abs(num); // 负数转正
+        const val = absNum + unit;
+        style += `margin-left: max(min(0px, 100% - ${val}), 0px);`;
+      } else {
+        style += `margin-left: ${marginLeft};`;
+      }
+    }
+    */
     if (marginLeft) style += `margin-left: ${marginLeft};`;
     if (marginLeft) style += `margin-left: ${marginLeft};`;
     if (marginRight) style += `margin-right: ${marginRight};`;
     if (marginRight) style += `margin-right: ${marginRight};`;
-    if (lineHeight) style += `line-height: ${lineHeight * 1.2};`;
+    if (lineHeight) {
+      let finalValue;
+      const str = String(lineHeight).trim();
+      // 匹配纯数字(整数或小数,可带负号)
+      if (/^-?\d+(\.\d+)?$/.test(str)) {
+        finalValue = parseFloat(str) * 1.2;
+      } else {
+        // 带单位或其他非纯数字内容,直接使用原值
+        finalValue = lineHeight;
+      }
+      style += `line-height: ${finalValue};`;
+    }
     if (paddingTop) style += `padding-top: ${paddingTop};`;
     if (paddingTop) style += `padding-top: ${paddingTop};`;
     if (paddingRight) style += `padding-right: ${paddingRight};`;
     if (paddingRight) style += `padding-right: ${paddingRight};`;
     if (paddingBottom) style += `padding-bottom: ${paddingBottom};`;
     if (paddingBottom) style += `padding-bottom: ${paddingBottom};`;
@@ -314,8 +380,24 @@ const paragraph: NodeSpec = {
       style += `white-space: ${whiteSpace};`; // 添加 white-space
       style += `white-space: ${whiteSpace};`; // 添加 white-space
     }
     }
 
 
-    const attr: Attr = { style };
-    return ['p', attr, 0];
+    const attrs: { style?: string; class?: string } = {};
+/*
+    let isEmpty = false;
+    const firstChild = node.content.firstChild;
+    if (firstChild) {
+      // 段落无任何子节点(包括 text 和 inline 节点)
+      if (firstChild.content.size === 0) {
+        isEmpty = true;
+      }
+    }
+    
+    // 如果整个 li 的内容长度为 0 也可以作为判断
+    if (node.content.size === 0) isEmpty = true;
+    if (style) attrs.style = style;
+    //if (isEmpty) attrs.class = 'empty';
+*/
+    if (style) attrs.style = style;
+    return ['p', attrs, 0];
   },
   },
 };
 };