How to use isFormattableNode method in wpt

Best JavaScript code snippet using wpt

implementation.js

Source:implementation.js Github

copy

Full Screen

...1522 return true;1523 }1524 return false;1525}1526function isFormattableNode(node) {1527 return isEditable(node)1528 && isVisible(node)1529 && (node.nodeType == Node.TEXT_NODE1530 || isHtmlElement(node, ["img", "br"]));1531}1532function areEquivalentValues(command, val1, val2) {1533 if (val1 === null && val2 === null) {1534 return true;1535 }1536 if (typeof val1 == "string"1537 && typeof val2 == "string"1538 && val1 == val21539 && !("equivalentValues" in commands[command])) {1540 return true;...

Full Screen

Full Screen

Command.ts

Source:Command.ts Github

copy

Full Screen

1import Editor from "../../editor";2import { createOverride } from './Override';3const NativeCommands = (editor: Editor) => {4 let cssStylingFlag = false;5 let executionStackDepth = 0;6 const commands = new Map()7 const { selection, utils } = editor;8 console.log(selection.getActiveRange())9 const internalOverride = createOverride(selection.getActiveRange)10 function registryCommand(command: string, options = {}) {11 commands.set(command, options)12 }13 function editCommandMethod(command: string, range: Range, callback: Function) {14 if (executionStackDepth == 0 && typeof range != "undefined") {15 selection.setActiveRange(range)16 } else if (executionStackDepth == 0) {17 selection.setActiveRange(null)18 selection.setActiveRange(selection.getActiveRange())19 }20 executionStackDepth++;21 let ret;22 try {23 ret = callback();24 } catch (e) {25 executionStackDepth--;26 throw e;27 }28 executionStackDepth--;29 return ret;30 }31 // command, showUi, value, range32 function execCommand (...args) {33 let [command, showUi, value, range] = args34 // 全部初始化命令为小写35 command = command.toLowerCase();36 // 如果只有一个参数,让 showUi 变为 false, 大于 4 个参数将不在处理37 if (args.length == 138 || (args.length >= 4 && typeof showUi == "undefined")) {39 showUi = false;40 }41 // 如果仅提供一个或两个参数,则让 value 为空字符串,设置默认值42 if (args.length <= 243 || (args.length >= 4 && typeof value == "undefined")) {44 value = "";45 }46 const execCallback = (command, showUi, value) => {47 return () => {48 if (!commands.has(command) || !queryCommandEnabled(command)) {49 return false;50 }51 // 执行命令操作,将值作为参数传递给指令,测试结果52 let ret = commands.get(command).action(value);53 // 如果出现既不是 true 也不是 false 的问题,直接抛出异常54 if (ret !== true && ret !== false) {55 throw "execCommand() didn't return true or false: " + ret;56 }57 // 如果上一步错误,直接返回58 if (ret === false) {59 return false;60 }61 // 可以执行,命令启用……62 return true;63 }64 }65 return editCommandMethod(command, range, execCallback(command, showUi, value));66 }67 function queryCommandEnabled(command: string, range?: Range) {68 command = command.toLowerCase();69 const callback = function (command) {70 return function () {71 // 如果同时支持和启用命令,则返回true,否则返回false。72 if (!(commands.has(command))) {73 return false;74 }75 // 在本规范中定义的命令中,除 cut 命令和 paste 命令外,总是启用杂项命令中列出的命令。76 // 如果活动范围不为null,其开始节点可编辑或是编辑根节点,其结束节点是可编辑的,77 // 也可以是子编辑根节点,并且有一些编辑根节点是其开始节点和结束节点的共同祖先78 return ["copy", "defaultparagraphseparator", "selectall", "stylewithcss", "usecss"].indexOf(command) != -179 || (80 selection.getActiveRange() !== null81 && (utils.isEditable(selection.getActiveRange().startContainer) || utils.isEditingHost(selection.getActiveRange().startContainer))82 && (utils.isEditable(selection.getActiveRange().endContainer) || utils.isEditingHost(selection.getActiveRange().endContainer))83 && (utils.getInclusiveAncestors(selection.getActiveRange().commonAncestorContainer).some(utils.isEditingHost))84 );85 }86 }87 return editCommandMethod(command, range, callback(command))88 }89 function queryCommandIndeterm(command: string, range?: Range) {90 command = command.toLowerCase();91 const callback = (command) => {92 return () => {93 // 如果命令不支持或者不确定,返回 false94 const currentCommand = commands.get(command)95 if (!currentCommand || !('indeterm' in currentCommand)) {96 return false;97 }98 // 如果命令不确定,则返回true,否则返回false99 return currentCommand.indeterm();100 }101 }102 return editCommandMethod(command, range, callback(command))103 }104 function queryCommandState(command: string, range?: Range) {105 command = command.toLowerCase();106 const callback = (command: string) => {107 return () => {108 // 如果命令不受支持或没有状态,则返回false。109 console.log('commands.has(command)', commands.has(command))110 if (!commands.has(command) || !("state" in commands.get(command))) {111 return false;112 }113 // 如果设置了命令的状态替代,则将其返回114 if (typeof internalOverride.getStateOverride(command) != "undefined") {115 return internalOverride.getStateOverride(command);116 }117 // 如果命令的状态为true,则返回true;否则为false118 return commands.get(command).state();119 }120 }121 return editCommandMethod(command, range, callback(command))122 }123 // 当编辑器使用 queryCommandSupported(command)方法时调用接口,如果命令为受支持,否则为false。124 function queryCommandSupported (command: string) {125 return commands.get(command.toLowerCase())126 }127 function queryCommandValue (command: string, range?: Range) {128 command = command.toLowerCase();129 const callback = function () {130 // 如果不支持命令或命令没有值,则返回空字符串131 const currentCommand = commands.get(command)132 if (!currentCommand || !("value" in currentCommand)) {133 return "";134 }135 // 如果命令是 fontSize 并且设置了其值替代,则将值替代转换为整数个像素,并返回结果的旧字体大小136 if (command == "fontsize"137 && internalOverride.getValueOverride("fontsize") !== undefined) {138 return utils.getLegacyFontSize(internalOverride.getValueOverride("fontsize"));139 }140 // 如果已经设置了覆盖命令的结果,直接返回141 if (typeof internalOverride.getValueOverride(command) != "undefined") {142 return internalOverride.getValueOverride(command);143 }144 // 返回命令的结果145 return currentCommand.value();146 }147 return editCommandMethod(command, range, callback)148 }149 // 获得指定的命令的值150 function getSpecifiedCommandValue(element, command) {151 // 如果 command 是 ['backColor', 'hiliteColor'] 并且这个元素不是'inline', 返回 null152 if ((command == "backcolor" || command == "hilitecolor")153 && getComputedStyle(element).display != "inline") {154 return null;155 }156 // command 是 'createLink' or 'unlink'157 if (command == "createlink" || command == "unlink") {158 // 如果是一个 Element 元素,并且拥有 href 属性,就 return 这个值159 if (utils.isHtmlElement(element)160 && element.tagName == "A"161 && element.hasAttribute("href")) {162 return element.getAttribute("href");163 }164 return null;165 }166 // 如果 command 是 subscript or superscript167 if (command == "subscript" || command == "superscript") {168 // 如果 element 是 "sup", return "superscript"169 if (utils.isHtmlElement(element, "sup")) {170 return "superscript";171 }172 // 如果 elelment 是 sub,return "subscript"173 if (utils.isHtmlElement(element, "sub")) {174 return "subscript";175 }176 return null;177 }178 // 如果 command 是 "strikethrough", 并且 element 设置了 style 属性,并且属性中设置了 text-decoration179 if (command == "strikethrough"180 && element.style.textDecoration != "") {181 // 如果 element 元素 style 中设置了 text-decoration 并且包含 line-through 属性,返回该属性182 if (element.style.textDecoration.indexOf("line-through") != -1) {183 return "line-through";184 }185 return null;186 }187 // 如果 command 是 "strikethrough" 并且 element 是 s or strike,直接返回 line-through188 if (command == "strikethrough"189 && utils.isHtmlElement(element, ["S", "STRIKE"])) {190 return "line-through";191 }192 // 如果 command 是 "underline", 并且 element 设置了 style 并且还设置了 text-decoration193 if (command == "underline"194 && element.style.textDecoration != "") {195 // 如果 element 元素 style 中设置了 text-decoration 并且包含 underline 属性,返回该属性196 if (element.style.textDecoration.indexOf("underline") != -1) {197 return "underline";198 }199 return null;200 }201 // 如果 command is "underline" 并且 element 是 [u] 直接返回 underline202 if (command == "underline"203 && utils.isHtmlElement(element, "U")) {204 return "underline";205 }206 // 获得 command 相关的属性 property207 let property = commands.get(command).relevantCssProperty;208 if (property === null) {209 return null;210 }211 // 如果 element 有相关属性设置,返回相关属性212 if (element.style[property] != "") {213 return element.style[property];214 }215 // 如果 element 是一个 font element,返回当前默认的有效属性216 if (utils.isHtmlNamespace(element.namespaceURI)217 && element.tagName == "FONT") {218 if (property == "color" && element.hasAttribute("color")) {219 return element.color;220 }221 if (property == "fontFamily" && element.hasAttribute("face")) {222 return element.face;223 }224 if (property == "fontSize" && element.hasAttribute("size")) {225 // This is not even close to correct in general.226 let size = parseInt(element.size);227 if (size < 1) {228 size = 1;229 }230 if (size > 7) {231 size = 7;232 }233 return {234 1: "x-small",235 2: "small",236 3: "medium",237 4: "large",238 5: "x-large",239 6: "xx-large",240 7: "xxx-large"241 }[size];242 }243 }244 // 如果是 fontWeight / fontStyle 则有两种情况, ['b', 'strong'] / ['i', 'em'],都返回正确的结果245 if (property == "fontWeight"246 && (element.tagName == "B" || element.tagName == "STRONG")) {247 return "bold";248 }249 if (property == "fontStyle"250 && (element.tagName == "I" || element.tagName == "EM")) {251 return "italic";252 }253 return null;254 }255 // 获得有效的命令值256 function getEffectiveCommandValue(node, command) {257 // 如果 node 不是 element 并且父节点也不是258 if (node.nodeType != Node.ELEMENT_NODE259 && (!node.parentNode || node.parentNode.nodeType != Node.ELEMENT_NODE)) {260 return null;261 }262 // 获得生效的父节点的命令值263 if (node.nodeType != Node.ELEMENT_NODE) {264 return getEffectiveCommandValue(node.parentNode, command);265 }266 // 如果命令是 command 是 "createlink" or "unlink"267 if (command == "createlink" || command == "unlink") {268 // 获得有效的 href 属性的 node269 while (node270 && (!utils.isHtmlElement(node)271 || node.tagName != "A"272 || !node.hasAttribute("href"))) {273 node = node.parentNode;274 }275 if (!node) {276 return null;277 }278 return node.getAttribute("href");279 }280 // 如果 command 是 "backColor" or "hiliteColor"281 if (command == "backcolor"282 || command == "hilitecolor") {283 // 获得有效的 backgroundColor 元素284 while ((getComputedStyle(node).backgroundColor == "rgba(0, 0, 0, 0)"285 || getComputedStyle(node).backgroundColor === ""286 || getComputedStyle(node).backgroundColor == "transparent")287 && node.parentNode288 && node.parentNode.nodeType == Node.ELEMENT_NODE) {289 node = node.parentNode;290 }291 return getComputedStyle(node).backgroundColor;292 }293 // 如果命令是 is "subscript" or "superscript"294 if (command == "subscript" || command == "superscript") {295 // 初始化 "subscript" or "superscript" 都为 false296 let affectedBySubscript = false;297 let affectedBySuperscript = false;298 // 如果 node 是 inline 类型299 while (utils.isInlineNode(node)) {300 let verticalAlign = getComputedStyle(node).verticalAlign;301 // 如果 node 是 sub, 设置 affectedBySubscript = true 如果是sub,设置 affectedBySuperscript = true;302 if (utils.isHtmlElement(node, "sub")) {303 affectedBySubscript = true;304 } else if (utils.isHtmlElement(node, "sup")) {305 affectedBySuperscript = true;306 }307 node = node.parentNode;308 }309 // 如果 affectedBySubscript affectedBySuperscript 都为 true 返回 mixed310 if (affectedBySubscript && affectedBySuperscript) {311 return "mixed";312 }313 // 如果 affectedBySubscript 为 true 返回 subscript314 if (affectedBySubscript) {315 return "subscript";316 }317 // 如果 affectedBySuperscript 为 true 返回 superscript318 if (affectedBySuperscript) {319 return "superscript";320 }321 return null;322 }323 // 如果 command 是 "strikethrough", 并且设置了 "text-decoration" 属性,并且包含 line-through 就立即返回,如果没有,返回 null324 if (command == "strikethrough") {325 do {326 if (getComputedStyle(node).textDecoration.indexOf("line-through") != -1) {327 return "line-through";328 }329 node = node.parentNode;330 } while (node && node.nodeType == Node.ELEMENT_NODE);331 return null;332 }333 // 如果 command 是 "strikethrough", 并且设置了 "text-decoration" 属性,并且包含 underline 就立即返回,如果没有,返回 null334 if (command == "underline") {335 do {336 if (getComputedStyle(node).textDecoration.indexOf("underline") != -1) {337 return "underline";338 }339 node = node.parentNode;340 } while (node && node.nodeType == Node.ELEMENT_NODE);341 return null;342 }343 if (!("relevantCssProperty" in commands.get(command))) {344 throw "Bug: no relevantCssProperty for " + command + " in getEffectiveCommandValue";345 }346 // 返回相关的 CSS 属性的值347 return getComputedStyle(node)[commands.get(command).relevantCssProperty];348 }349 // 清除元素设定的样式350 function clearValue(element, command) {351 // 如果 element 不可编辑,返回 []352 if (!utils.isEditable(element)) {353 return [];354 }355 // 如果 element 是特殊的命令,并且验证结果为空,返回 []356 if (getSpecifiedCommandValue(element, command) === null) {357 return [];358 }359 // 是一个简单的可以被修改的 element360 if (utils.isSimpleModifiableElement(element)) {361 // 获得子节点362 let children = Array.prototype.slice.call(element.childNodes);363 // 对于 children 中的每个孩子,在 element 之前将 child 插入元素的父元素,立即保留范围。364 for (let i = 0; i < children.length; i++) {365 selection.movePreservingRanges(children[i], element.parentNode, utils.getNodeIndex(element));366 }367 element.parentNode.removeChild(element);368 return children;369 }370 // 如果命令是 "strikethrough" 删除其 style 属性中的样式371 if (command == "strikethrough"372 && element.style.textDecoration.indexOf("line-through") != -1) {373 if (element.style.textDecoration == "line-through") {374 element.style.textDecoration = "";375 } else {376 element.style.textDecoration = element.style.textDecoration.replace("line-through", "");377 }378 if (element.getAttribute("style") == "") {379 element.removeAttribute("style");380 }381 }382 // 如果是 undeline 删除其 style 等属性中的样式383 if (command == "underline"384 && element.style.textDecoration.indexOf("underline") != -1) {385 if (element.style.textDecoration == "underline") {386 element.style.textDecoration = "";387 } else {388 element.style.textDecoration = element.style.textDecoration.replace("underline", "");389 }390 if (element.getAttribute("style") == "") {391 element.removeAttribute("style");392 }393 }394 // 如果是其他的类似的 CSS 属性,直接移出 style 属性395 if (commands.get(command).relevantCssProperty !== null) {396 element.style[commands.get(command).relevantCssProperty] = '';397 if (element.getAttribute("style") == "") {398 element.removeAttribute("style");399 }400 }401 // 如果是 font 标签402 if (utils.isHtmlNamespace(element.namespaceURI) && element.tagName == "FONT") {403 // 如果设置了 foreColor 移出设定值404 if (command == "forecolor") {405 element.removeAttribute("color");406 }407 // 如果设置了 fontname 移出设定值408 if (command == "fontname") {409 element.removeAttribute("face");410 }411 // 如果设置了 fontSize 移出设定值412 if (command == "fontsize") {413 element.removeAttribute("size");414 }415 }416 // 如果是 a 标签,并且 command 是 "createLink" or "unlink", 取消 href 属性417 if (utils.isHtmlElement(element, "A")418 && (command == "createlink" || command == "unlink")) {419 element.removeAttribute("href");420 }421 // 再次校验特殊命令,并且验证结果为空,返回 []422 if (getSpecifiedCommandValue(element, command) === null) {423 return [];424 }425 // 返回由 span 包裹的节点426 return [selection.setTagName(element, "span")];427 }428 // 是否是两个相同的变量429 // 两个量都是命令的等效值,如果两个均为空430 // 或者都是字符串并且相等,并且命令没有定义任何 equivalentValues,431 // 或者两个都是字符串,并且命令定义了 equivalentValues 并且它们与定义匹配。432 function areEquivalentValues(command, val1, val2) {433 if (val1 === null && val2 === null) {434 return true;435 }436 if (typeof val1 == "string"437 && typeof val2 == "string"438 && val1 == val2439 && !("equivalentValues" in commands.get(command))) {440 return true;441 }442 if (typeof val1 == "string"443 && typeof val2 == "string"444 && "equivalentValues" in commands.get(command)445 && commands.get(command).equivalentValues(val1, val2)) {446 return true;447 }448 return false;449 }450 // 松散比较两个值451 function areLooselyEquivalentValues(command, val1, val2) {452 const sizeMap = new Map();453 if (areEquivalentValues(command, val1, val2)) {454 return true;455 }456 if (command != "fontsize"457 || typeof val1 != "string"458 || typeof val2 != "string") {459 return false;460 }461 let font = document.createElement("font");462 document.body.appendChild(font);463 ["x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"].forEach(function(keyword) {464 font.size = utils.cssSizeToLegacy(keyword);465 sizeMap.set(keyword, getComputedStyle(font).fontSize)466 });467 document.body.removeChild(font);468 return val1 === sizeMap.get(val2)469 || val2 === sizeMap.get(val1);470 }471 // 强制设置值472 function forceValue(node, command, newValue) {473 // "If node's parent is null, abort this algorithm."474 // 如果节点的父级不是元素,则中止该算法。475 if (!node.parentNode) {476 return;477 }478 // "If new value is null, abort this algorithm."479 if (newValue === null) {480 return;481 }482 // "If node is an allowed child of "span":"483 if (utils.isAllowedChild(node, "span")) {484 // "Reorder modifiable descendants of node's previousSibling."485 reorderModifiableDescendants(node.previousSibling, command, newValue);486 // "Reorder modifiable descendants of node's nextSibling."487 reorderModifiableDescendants(node.nextSibling, command, newValue);488 // "Wrap the one-node list consisting of node, with sibling criteria489 // returning true for a simple modifiable element whose specified490 // command value is equivalent to new value and whose effective command491 // value is loosely equivalent to new value and false otherwise, and492 // with new parent instructions returning null."493 wrap([node],494 function(node) {495 return utils.isSimpleModifiableElement(node)496 && areEquivalentValues(command, getSpecifiedCommandValue(node, command), newValue)497 && areLooselyEquivalentValues(command, getEffectiveCommandValue(node, command), newValue);498 },499 function() { return null }500 );501 }502 // "If node is invisible, abort this algorithm."503 if (utils.isInvisible(node)) {504 return;505 }506 // "If the effective command value of command is loosely equivalent to new507 // value on node, abort this algorithm."508 if (areLooselyEquivalentValues(command, getEffectiveCommandValue(node, command), newValue)) {509 return;510 }511 // "If node is not an allowed child of "span":"512 if (!utils.isAllowedChild(node, "span")) {513 // "Let children be all children of node, omitting any that are514 // Elements whose specified command value for command is neither null515 // nor equivalent to new value."516 let children = [];517 for (let i = 0; i < node.childNodes.length; i++) {518 if (node.childNodes[i].nodeType == Node.ELEMENT_NODE) {519 let specifiedValue = getSpecifiedCommandValue(node.childNodes[i], command);520 if (specifiedValue !== null521 && !areEquivalentValues(command, newValue, specifiedValue)) {522 continue;523 }524 }525 children.push(node.childNodes[i]);526 }527 // "Force the value of each Node in children, with command and new528 // value as in this invocation of the algorithm."529 for (let i = 0; i < children.length; i++) {530 forceValue(children[i], command, newValue);531 }532 // "Abort this algorithm."533 return;534 }535 // "If the effective command value of command is loosely equivalent to new536 // value on node, abort this algorithm."537 if (areLooselyEquivalentValues(command, getEffectiveCommandValue(node, command), newValue)) {538 return;539 }540 // "Let new parent be null."541 let newParent = null;542 // "If the CSS styling flag is false:"543 if (!cssStylingFlag) {544 // "If command is "bold" and new value is "bold", let new parent be the545 // result of calling createElement("b") on the ownerDocument of node."546 if (command == "bold" && (newValue == "bold" || newValue == "700")) {547 newParent = node.ownerDocument.createElement("b");548 }549 // "If command is "italic" and new value is "italic", let new parent be550 // the result of calling createElement("i") on the ownerDocument of551 // node."552 if (command == "italic" && newValue == "italic") {553 newParent = node.ownerDocument.createElement("i");554 }555 // "If command is "strikethrough" and new value is "line-through", let556 // new parent be the result of calling createElement("s") on the557 // ownerDocument of node."558 if (command == "strikethrough" && newValue == "line-through") {559 newParent = node.ownerDocument.createElement("s");560 }561 // "If command is "underline" and new value is "underline", let new562 // parent be the result of calling createElement("u") on the563 // ownerDocument of node."564 if (command == "underline" && newValue == "underline") {565 newParent = node.ownerDocument.createElement("u");566 }567 // "If command is "foreColor", and new value is fully opaque with red,568 // green, and blue components in the range 0 to 255:"569 if (command == "forecolor" && utils.parseSimpleColor(newValue)) {570 // "Let new parent be the result of calling createElement("font")571 // on the ownerDocument of node."572 newParent = node.ownerDocument.createElement("font");573 // "Set the color attribute of new parent to the result of applying574 // the rules for serializing simple color values to new value575 // (interpreted as a simple color)."576 newParent.setAttribute("color", utils.parseSimpleColor(newValue));577 }578 // "If command is "fontName", let new parent be the result of calling579 // createElement("font") on the ownerDocument of node, then set the580 // face attribute of new parent to new value."581 if (command == "fontname") {582 newParent = node.ownerDocument.createElement("font");583 newParent.face = newValue;584 }585 }586 // "If command is "createLink" or "unlink":"587 if (command == "createlink" || command == "unlink") {588 // "Let new parent be the result of calling createElement("a") on the589 // ownerDocument of node."590 newParent = node.ownerDocument.createElement("a");591 // "Set the href attribute of new parent to new value."592 newParent.setAttribute("href", newValue);593 // "Let ancestor be node's parent."594 let ancestor = node.parentNode;595 // "While ancestor is not null:"596 while (ancestor) {597 // "If ancestor is an a, set the tag name of ancestor to "span",598 // and let ancestor be the result."599 if (utils.isHtmlElement(ancestor, "A")) {600 ancestor = selection.setTagName(ancestor, "span");601 }602 // "Set ancestor to its parent."603 ancestor = ancestor.parentNode;604 }605 }606 // "If command is "fontSize"; and new value is one of "x-small", "small",607 // "medium", "large", "x-large", "xx-large", or "xxx-large"; and either the608 // CSS styling flag is false, or new value is "xxx-large": let new parent609 // be the result of calling createElement("font") on the ownerDocument of610 // node, then set the size attribute of new parent to the number from the611 // following table based on new value: [table omitted]"612 if (command == "fontsize"613 && ["x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large"].indexOf(newValue) != -1614 && (!cssStylingFlag || newValue == "xxx-large")) {615 newParent = node.ownerDocument.createElement("font");616 newParent.size = utils.cssSizeToLegacy(newValue);617 }618 // "If command is "subscript" or "superscript" and new value is619 // "subscript", let new parent be the result of calling620 // createElement("sub") on the ownerDocument of node."621 if ((command == "subscript" || command == "superscript")622 && newValue == "subscript") {623 newParent = node.ownerDocument.createElement("sub");624 }625 // "If command is "subscript" or "superscript" and new value is626 // "superscript", let new parent be the result of calling627 // createElement("sup") on the ownerDocument of node."628 if ((command == "subscript" || command == "superscript")629 && newValue == "superscript") {630 newParent = node.ownerDocument.createElement("sup");631 }632 // "If new parent is null, let new parent be the result of calling633 // createElement("span") on the ownerDocument of node."634 if (!newParent) {635 newParent = node.ownerDocument.createElement("span");636 }637 // "Insert new parent in node's parent before node."638 node.parentNode.insertBefore(newParent, node);639 // "If the effective command value of command for new parent is not loosely640 // equivalent to new value, and the relevant CSS property for command is641 // not null, set that CSS property of new parent to new value (if the new642 // value would be valid)."643 let property = commands.get(command).relevantCssProperty;644 if (property !== null645 && !areLooselyEquivalentValues(command, getEffectiveCommandValue(newParent, command), newValue)) {646 newParent.style[property] = newValue;647 }648 // "If command is "strikethrough", and new value is "line-through", and the649 // effective command value of "strikethrough" for new parent is not650 // "line-through", set the "text-decoration" property of new parent to651 // "line-through"."652 if (command == "strikethrough"653 && newValue == "line-through"654 && getEffectiveCommandValue(newParent, "strikethrough") != "line-through") {655 newParent.style.textDecoration = "line-through";656 }657 // "If command is "underline", and new value is "underline", and the658 // effective command value of "underline" for new parent is not659 // "underline", set the "text-decoration" property of new parent to660 // "underline"."661 if (command == "underline"662 && newValue == "underline"663 && getEffectiveCommandValue(newParent, "underline") != "underline") {664 newParent.style.textDecoration = "underline";665 }666 // "Append node to new parent as its last child, preserving ranges."667 selection.movePreservingRanges(node, newParent, newParent.childNodes.length);668 // "If node is an Element and the effective command value of command for669 // node is not loosely equivalent to new value:"670 if (node.nodeType == Node.ELEMENT_NODE671 && !areEquivalentValues(command, getEffectiveCommandValue(node, command), newValue)) {672 // "Insert node into the parent of new parent before new parent,673 // preserving ranges."674 selection.movePreservingRanges(node, newParent.parentNode, utils.getNodeIndex(newParent));675 // "Remove new parent from its parent."676 newParent.parentNode.removeChild(newParent);677 // "Let children be all children of node, omitting any that are678 // Elements whose specified command value for command is neither null679 // nor equivalent to new value."680 let children = [];681 for (let i = 0; i < node.childNodes.length; i++) {682 if (node.childNodes[i].nodeType == Node.ELEMENT_NODE) {683 let specifiedValue = getSpecifiedCommandValue(node.childNodes[i], command);684 if (specifiedValue !== null685 && !areEquivalentValues(command, newValue, specifiedValue)) {686 continue;687 }688 }689 children.push(node.childNodes[i]);690 }691 // "Force the value of each Node in children, with command and new692 // value as in this invocation of the algorithm."693 for (let i = 0; i < children.length; i++) {694 forceValue(children[i], command, newValue);695 }696 }697 }698 // 重新排列可修改的后代699 function reorderModifiableDescendants(node, command, newValue) {700 // "Let candidate equal node."701 let candidate = node;702 // "While candidate is a modifiable element, and candidate has exactly one703 // child, and that child is also a modifiable element, and candidate is not704 // a simple modifiable element or candidate's specified command value for705 // command is not equivalent to new value, set candidate to its child."706 while (utils.isModifiableElement(candidate)707 && candidate.childNodes.length == 1708 && utils.isModifiableElement(candidate.firstChild)709 && (!utils.isSimpleModifiableElement(candidate)710 || !areEquivalentValues(command, getSpecifiedCommandValue(candidate, command), newValue))) {711 candidate = candidate.firstChild;712 }713 // "If candidate is node, or is not a simple modifiable element, or its714 // specified command value is not equivalent to new value, or its effective715 // command value is not loosely equivalent to new value, abort these716 // steps."717 if (candidate == node718 || !utils.isSimpleModifiableElement(candidate)719 || !areEquivalentValues(command, getSpecifiedCommandValue(candidate, command), newValue)720 || !areLooselyEquivalentValues(command, getEffectiveCommandValue(candidate, command), newValue)) {721 return;722 }723 // "While candidate has children, insert the first child of candidate into724 // candidate's parent immediately before candidate, preserving ranges."725 while (candidate.hasChildNodes()) {726 selection.movePreservingRanges(candidate.firstChild, candidate.parentNode, utils.getNodeIndex(candidate));727 }728 // "Insert candidate into node's parent immediately after node."729 node.parentNode.insertBefore(candidate, node.nextSibling);730 // "Append the node as the last child of candidate, preserving ranges."731 selection.movePreservingRanges(node, candidate, -1);732 }733 function wrap(nodeList, siblingCriteria, newParentInstructions) {734 // "If not provided, sibling criteria returns false and new parent735 // instructions returns null."736 //“如果未提供,则同级条件返回false和新的父级737 //指令传回null。”738 if (typeof siblingCriteria == "undefined") {739 siblingCriteria = function() { return false };740 }741 if (typeof newParentInstructions == "undefined") {742 newParentInstructions = function() { return null };743 }744 // "If every member of node list is invisible, and none is a br, return745 // null and abort these steps."746 if (nodeList.every(utils.isInvisible)747 && !nodeList.some(function(node) { return utils.isHtmlElement(node, "br") })) {748 return null;749 }750 // "If node list's first member's parent is null, return null and abort751 // these steps."752 if (!nodeList[0].parentNode) {753 return null;754 }755 // "If node list's last member is an inline node that's not a br, and node756 // list's last member's nextSibling is a br, append that br to node list."757 if (utils.isInlineNode(nodeList[nodeList.length - 1])758 && !utils.isHtmlElement(nodeList[nodeList.length - 1], "br")759 && utils.isHtmlElement(nodeList[nodeList.length - 1].nextSibling, "br")) {760 nodeList.push(nodeList[nodeList.length - 1].nextSibling);761 }762 // "While node list's first member's previousSibling is invisible, prepend763 // it to node list."764 while (utils.isInvisible(nodeList[0].previousSibling)) {765 nodeList.unshift(nodeList[0].previousSibling);766 }767 // "While node list's last member's nextSibling is invisible, append it to768 // node list."769 while (utils.isInvisible(nodeList[nodeList.length - 1].nextSibling)) {770 nodeList.push(nodeList[nodeList.length - 1].nextSibling);771 }772 // "If the previousSibling of the first member of node list is editable and773 // running sibling criteria on it returns true, let new parent be the774 // previousSibling of the first member of node list."775 let newParent;776 if (utils.isEditable(nodeList[0].previousSibling)777 && siblingCriteria(nodeList[0].previousSibling)) {778 newParent = nodeList[0].previousSibling;779 // "Otherwise, if the nextSibling of the last member of node list is780 // editable and running sibling criteria on it returns true, let new parent781 // be the nextSibling of the last member of node list."782 } else if (utils.isEditable(nodeList[nodeList.length - 1].nextSibling)783 && siblingCriteria(nodeList[nodeList.length - 1].nextSibling)) {784 newParent = nodeList[nodeList.length - 1].nextSibling;785 // "Otherwise, run new parent instructions, and let new parent be the786 // result."787 } else {788 newParent = newParentInstructions();789 }790 // "If new parent is null, abort these steps and return null."791 if (!newParent) {792 return null;793 }794 // "If new parent's parent is null:"795 if (!newParent.parentNode) {796 // "Insert new parent into the parent of the first member of node list797 // immediately before the first member of node list."798 nodeList[0].parentNode.insertBefore(newParent, nodeList[0]);799 // "If any range has a boundary point with node equal to the parent of800 // new parent and offset equal to the index of new parent, add one to801 // that boundary point's offset."802 //803 // Only try to fix the global range.804 if (selection.range.startContainer == newParent.parentNode805 && selection.range.startOffset == utils.getNodeIndex(newParent)) {806 selection.range.setStart(selection.range.startContainer, selection.range.startOffset + 1);807 }808 if (selection.range.endContainer == newParent.parentNode809 && selection.range.endOffset == utils.getNodeIndex(newParent)) {810 selection.range.setEnd(selection.range.endContainer, selection.range.endOffset + 1);811 }812 }813 // "Let original parent be the parent of the first member of node list."814 let originalParent = nodeList[0].parentNode;815 // "If new parent is before the first member of node list in tree order:"816 if (utils.isBefore(newParent, nodeList[0])) {817 // "If new parent is not an inline node, but the last visible child of818 // new parent and the first visible member of node list are both inline819 // nodes, and the last child of new parent is not a br, call820 // createElement("br") on the ownerDocument of new parent and append821 // the result as the last child of new parent."822 if (!utils.isInlineNode(newParent)823 && utils.isInlineNode([].filter.call(newParent.childNodes, utils.isVisible).slice(-1)[0])824 && utils.isInlineNode(nodeList.filter(utils.isVisible)[0])825 && !utils.isHtmlElement(newParent.lastChild, "BR")) {826 newParent.appendChild(newParent.ownerDocument.createElement("br"));827 }828 // "For each node in node list, append node as the last child of new829 // parent, preserving ranges."830 for (let i = 0; i < nodeList.length; i++) {831 selection.movePreservingRanges(nodeList[i], newParent, -1);832 }833 // "Otherwise:"834 } else {835 // "If new parent is not an inline node, but the first visible child of836 // new parent and the last visible member of node list are both inline837 // nodes, and the last member of node list is not a br, call838 // createElement("br") on the ownerDocument of new parent and insert839 // the result as the first child of new parent."840 if (!utils.isInlineNode(newParent)841 && utils.isInlineNode([].filter.call(newParent.childNodes, utils.isVisible)[0])842 && utils.isInlineNode(nodeList.filter(utils.isVisible).slice(-1)[0])843 && !utils.isHtmlElement(nodeList[nodeList.length - 1], "BR")) {844 newParent.insertBefore(newParent.ownerDocument.createElement("br"), newParent.firstChild);845 }846 // "For each node in node list, in reverse order, insert node as the847 // first child of new parent, preserving ranges."848 for (let i = nodeList.length - 1; i >= 0; i--) {849 selection.movePreservingRanges(nodeList[i], newParent, 0);850 }851 }852 // "If original parent is editable and has no children, remove it from its853 // parent."854 if (utils.isEditable(originalParent) && !originalParent.hasChildNodes()) {855 originalParent.parentNode.removeChild(originalParent);856 }857 // "If new parent's nextSibling is editable and running sibling criteria on858 // it returns true:"859 if (utils.isEditable(newParent.nextSibling)860 && siblingCriteria(newParent.nextSibling)) {861 // "If new parent is not an inline node, but new parent's last child862 // and new parent's nextSibling's first child are both inline nodes,863 // and new parent's last child is not a br, call createElement("br") on864 // the ownerDocument of new parent and append the result as the last865 // child of new parent."866 if (!utils.isInlineNode(newParent)867 && utils.isInlineNode(newParent.lastChild)868 && utils.isInlineNode(newParent.nextSibling.firstChild)869 && !utils.isHtmlElement(newParent.lastChild, "BR")) {870 newParent.appendChild(newParent.ownerDocument.createElement("br"));871 }872 // "While new parent's nextSibling has children, append its first child873 // as the last child of new parent, preserving ranges."874 while (newParent.nextSibling.hasChildNodes()) {875 selection.movePreservingRanges(newParent.nextSibling.firstChild, newParent, -1);876 }877 // "Remove new parent's nextSibling from its parent."878 newParent.parentNode.removeChild(newParent.nextSibling);879 }880 // "Remove extraneous line breaks from new parent."881 utils.removeExtraneousLineBreaksFrom(newParent);882 // "Return new parent."883 return newParent;884 }885 // 应用当前结果886 function pushDownValues(node, command, newValue) {887 // 如果节点的父级不是元素,则中止该算法。888 if (!node.parentNode889 || node.parentNode.nodeType != Node.ELEMENT_NODE) {890 return;891 }892 // 如果当前命令有效,并且和旧的元素上的值通过松散匹配相等,就不设置893 if (areLooselyEquivalentValues(command, getEffectiveCommandValue(node, command), newValue)) {894 return;895 }896 // 获得公共祖先897 let currentAncestor = node.parentNode;898 // 初始化 ancestor list 为空899 let ancestorList = [];900 // 递归找到最远的父节点,如果当前新的 command 不等于旧值,则将父节点加入到 ancestorList901 while (utils.isEditable(currentAncestor)902 && currentAncestor.nodeType == Node.ELEMENT_NODE903 && !areLooselyEquivalentValues(command, getEffectiveCommandValue(currentAncestor, command), newValue)) {904 ancestorList.push(currentAncestor);905 currentAncestor = currentAncestor.parentNode;906 }907 // 如果没有待更新至,返回908 if (!ancestorList.length) {909 return;910 }911 // 因为 dom 节点样式都是继承的。所以返回 ancestorList 最后一个元素即最远的祖先节点912 let propagatedValue = getSpecifiedCommandValue(ancestorList[ancestorList.length - 1], command);913 // 如果 propagatedValue 是 null 并且不等于新的值,就终止914 if (propagatedValue === null && propagatedValue != newValue) {915 return;916 }917 // 如果命令的值有效,并且公共的祖先节点松散匹配不等于新的结果,这时新的结果也不是空值,就终止918 if (newValue !== null919 && !areLooselyEquivalentValues(command, getEffectiveCommandValue(ancestorList[ancestorList.length - 1].parentNode, command), newValue)) {920 return;921 }922 // 清空 ancestorList 栈923 while (ancestorList.length) {924 let currentAncestor = ancestorList.pop();925 // 出栈过程中,如果某个节点含有指定的样式,就设置指定的传播值926 if (getSpecifiedCommandValue(currentAncestor, command) !== null) {927 propagatedValue = getSpecifiedCommandValue(currentAncestor, command);928 }929 let children = Array.prototype.slice.call(currentAncestor.childNodes);930 // 如果command的当前祖先的指定命令值不为空,则清除当前祖先的值。931 if (getSpecifiedCommandValue(currentAncestor, command) !== null) {932 clearValue(currentAncestor, command);933 }934 // 处理每个 children935 for (let i = 0; i < children.length; i++) {936 let child = children[i];937 // 如果 chide == node, 跳过当前处理938 if (child == node) {939 continue;940 }941 // 如果 child 是一个 Element,其 command 的指定命令值既不为空也不等同于 propagatedVale,则继续下一个 child。942 if (child.nodeType == Node.ELEMENT_NODE943 && getSpecifiedCommandValue(child, command) !== null944 && !areEquivalentValues(command, propagatedValue, getSpecifiedCommandValue(child, command))) {945 continue;946 }947 // 如果 child == ancestorList[ancestorList.length - 1],跳过948 if (child == ancestorList[ancestorList.length - 1]) {949 continue;950 }951 // 强制使用 child 的值,并且更新 新值等于传播的值。952 forceValue(child, command, propagatedValue);953 }954 }955 }956 function recordCurrentOverrides() {957 // 初始化overrides958 let overrides = [];959 // 优先处理超链接960 if (internalOverride.getValueOverride("createlink") !== undefined) {961 overrides.push(["createlink", internalOverride.getValueOverride("createlink")]);962 }963 // 这些值只有 true 和 false964 const verifyState = ["bold", "italic", "strikethrough", "subscript", "superscript", "underline"]965 verifyState.forEach(function(command) {966 if (internalOverride.getStateOverride(command) !== undefined) {967 overrides.push([command, internalOverride.getStateOverride(command)]);968 }969 });970 // 这些是有值的971 const verifyValue = ["fontname", "fontsize", "forecolor", "hilitecolor"]972 verifyValue.forEach(function(command) {973 if (internalOverride.getValueOverride(command) !== undefined) {974 overrides.push([command, internalOverride.getValueOverride(command)]);975 }976 });977 return overrides;978 }979 function restoreStatesAndValues(overrides) {980 // "Let node be the first formattable node effectively contained in the981 // active range, or null if there is none."982 let node = utils.getAllEffectivelyContainedNodes(selection.getActiveRange())983 .filter(utils.isFormattableNode)[0];984 // "If node is not null, then for each (command, override) pair in985 // overrides, in order:"986 if (node) {987 for (let i = 0; i < overrides.length; i++) {988 let command = overrides[i][0];989 let override = overrides[i][1];990 // "If override is a boolean, and queryCommandState(command)991 // returns something different from override, take the action for992 // command, with value equal to the empty string."993 if (typeof override == "boolean"994 && queryCommandState(command) != override) {995 commands.get(command).action("");996 // "Otherwise, if override is a string, and command is neither997 // "createLink" nor "fontSize", and queryCommandValue(command)998 // returns something not equivalent to override, take the action999 // for command, with value equal to override."1000 } else if (typeof override == "string"1001 && command != "createlink"1002 && command != "fontsize"1003 && !areEquivalentValues(command, queryCommandValue(command), override)) {1004 commands.get(command).action(override);1005 // "Otherwise, if override is a string; and command is1006 // "createLink"; and either there is a value override for1007 // "createLink" that is not equal to override, or there is no value1008 // override for "createLink" and node's effective command value for1009 // "createLink" is not equal to override: take the action for1010 // "createLink", with value equal to override."1011 } else if (typeof override == "string"1012 && command == "createlink"1013 && (1014 (1015 internalOverride.getValueOverride("createlink") !== undefined1016 && internalOverride.getValueOverride("createlink") !== override1017 ) || (1018 internalOverride.getValueOverride("createlink") === undefined1019 && getEffectiveCommandValue(node, "createlink") !== override1020 )1021 )) {1022 commands.get('createlink').action(override);1023 // "Otherwise, if override is a string; and command is "fontSize";1024 // and either there is a value override for "fontSize" that is not1025 // equal to override, or there is no value override for "fontSize"1026 // and node's effective command value for "fontSize" is not loosely1027 // equivalent to override:"1028 } else if (typeof override == "string"1029 && command == "fontsize"1030 && (1031 (1032 internalOverride.getValueOverride("fontsize") !== undefined1033 && internalOverride.getValueOverride("fontsize") !== override1034 ) || (1035 internalOverride.getValueOverride("fontsize") === undefined1036 && !areLooselyEquivalentValues(command, getEffectiveCommandValue(node, "fontsize"), override)1037 )1038 )) {1039 // "Convert override to an integer number of pixels, and set1040 // override to the legacy font size for the result."1041 override = utils.getLegacyFontSize(override);1042 // "Take the action for "fontSize", with value equal to1043 // override."1044 commands.get('fontsize').action(override);1045 // "Otherwise, continue this loop from the beginning."1046 } else {1047 continue;1048 }1049 // "Set node to the first formattable node effectively contained in1050 // the active range, if there is one."1051 node = utils.getAllEffectivelyContainedNodes(selection.getActiveRange())1052 .filter(utils.isFormattableNode)[0]1053 || node;1054 }1055 // "Otherwise, for each (command, override) pair in overrides, in order:"1056 } else {1057 for (let i = 0; i < overrides.length; i++) {1058 let command = overrides[i][0];1059 let override = overrides[i][1];1060 // "If override is a boolean, set the state override for command to1061 // override."1062 if (typeof override == "boolean") {1063 internalOverride.setStateOverride(command, override);1064 }1065 // "If override is a string, set the value override for command to1066 // override."1067 if (typeof override == "string") {1068 internalOverride.setValueOverride(command, override);1069 }1070 }1071 }1072 }1073 function recordCurrentStatesAndValues() {1074 // "Let overrides be a list of (string, string or boolean) ordered pairs,1075 // initially empty."1076 let overrides = [];1077 // "Let node be the first formattable node effectively contained in the1078 // active range, or null if there is none."1079 let node = utils.getAllEffectivelyContainedNodes(selection.getActiveRange())1080 .filter(utils.isFormattableNode)[0];1081 // "If node is null, return overrides."1082 if (!node) {1083 return overrides;1084 }1085 // "Add ("createLink", node's effective command value for "createLink") to1086 // overrides."1087 overrides.push(["createlink", getEffectiveCommandValue(node, "createlink")]);1088 // "For each command in the list "bold", "italic", "strikethrough",1089 // "subscript", "superscript", "underline", in order: if node's effective1090 // command value for command is one of its inline command activated values,1091 // add (command, true) to overrides, and otherwise add (command, false) to1092 // overrides."1093 ["bold", "italic", "strikethrough", "subscript", "superscript",1094 "underline"].forEach(function(command) {1095 if (commands.get(command).inlineCommandActivatedValues1096 .indexOf(getEffectiveCommandValue(node, command)) != -1) {1097 overrides.push([command, true]);1098 } else {1099 overrides.push([command, false]);1100 }1101 });1102 // "For each command in the list "fontName", "foreColor", "hiliteColor", in1103 // order: add (command, command's value) to overrides."1104 ["fontname", "fontsize", "forecolor", "hilitecolor"].forEach(function(command) {1105 overrides.push([command, commands.get(command).value()]);1106 });1107 // "Add ("fontSize", node's effective command value for "fontSize") to1108 // overrides."1109 overrides.push(["fontsize", getEffectiveCommandValue(node, "fontsize")]);1110 // "Return overrides."1111 return overrides;1112 }1113 function setSelectionValue (command, newValue) {1114 // console.log('%ccommand', 'color:red', editor.commands, command, newValue)1115 // 如果选中范围中没有有效包含的格式表节点1116 if (!utils.getAllEffectivelyContainedNodes(selection.getActiveRange())1117 .some(utils.isFormattableNode)) {1118 // 如果 command 具有内联命令激活值,则如果其中包含新值,则将状态替代设置为true,否则将其设置为false。1119 if ("inlineCommandActivatedValues" in commands.get(command)) {1120 internalOverride.setStateOverride(command, commands.get(command).inlineCommandActivatedValues1121 .indexOf(newValue) != -1);1122 }1123 // 如果 command 是 "subscript", 则覆盖 "superscript"1124 if (command == "subscript") {1125 internalOverride.unsetStateOverride("superscript");1126 }1127 // 如果 command 是 "superscript" 则覆盖 "subscript"1128 if (command == "superscript") {1129 internalOverride.unsetStateOverride("subscript");1130 }1131 // 如果新值是 null, 不覆盖1132 if (newValue === null) {1133 internalOverride.unsetValueOverride(command);1134 // 其他情况,如果 command 是 'createLink' 或者特定的值,都替换为新的1135 } else if (command == "createlink" || "value" in commands.get(command)) {1136 internalOverride.setValueOverride(command, newValue);1137 }1138 // 终止此次操作1139 return;1140 }1141 // 如果激活的选区中的起始节点是一个可编辑的文本节点,并且其起始偏移量既不是零也不是其起始节点的长度,1142 // 则在活动范围的起始节点上调用 splitText(),参数等于活动范围的起始偏移量。1143 // 然后设置当前激活的选区的起始节点并且应用设置的值,并且更新其起始偏移为零。1144 const activedRange = selection.getActiveRange()1145 if (utils.isEditable(activedRange.startContainer)1146 && activedRange.startContainer.nodeType == Node.TEXT_NODE1147 && activedRange.startOffset != 01148 && activedRange.startOffset != utils.getNodeLength(activedRange.startContainer)) {1149 // 一些特定浏览器怪异规则1150 let newActiveRange = document.createRange();1151 let newNode;1152 if (activedRange.startContainer == activedRange.endContainer) {1153 let newEndOffset = activedRange.endOffset - activedRange.startOffset;1154 newNode = (<Text>activedRange.startContainer).splitText(activedRange.startOffset);1155 newActiveRange.setEnd(newNode, newEndOffset);1156 activedRange.setEnd(newNode, newEndOffset);1157 } else {1158 newNode = (<Text>activedRange.startContainer).splitText(activedRange.startOffset);1159 }1160 newActiveRange.setStart(newNode, 0);1161 getSelection().removeAllRanges();1162 getSelection().addRange(newActiveRange);1163 activedRange.setStart(newNode, 0);1164 }1165 // 如果激活选区中结束节点是一个可以编辑的文本节点,并且他的 endoffset 偏移量不是 0也不是其结束位置1166 // 则调用 splitText(),参数等于结束的偏移量1167 if (utils.isEditable(activedRange.endContainer)1168 && activedRange.endContainer.nodeType == Node.TEXT_NODE1169 && activedRange.endOffset != 01170 && activedRange.endOffset != utils.getNodeLength(activedRange.endContainer)) {1171 // 处理 IE 问题1172 // IE 选区范围异常,所以要重新修正选区范围1173 // 在调用 getActiveRange 之前先 splitText 然后更正选区1174 let activeRange = activedRange;1175 let newStart: [Node, number] = [activeRange.startContainer, activeRange.startOffset];1176 let newEnd: [Node, number] = [activeRange.endContainer, activeRange.endOffset];1177 (<Text>activeRange.endContainer).splitText(activeRange.endOffset);1178 activeRange.setStart(newStart[0], newStart[1]);1179 activeRange.setEnd(newEnd[0], newEnd[1]);1180 getSelection().removeAllRanges();1181 getSelection().addRange(activeRange);1182 }1183 // 获取所有有效包含的 nodeList1184 // 优先清除所有的值1185 utils.getAllEffectivelyContainedNodes(activedRange, function (node) {1186 return utils.isEditable(node) && node.nodeType == Node.ELEMENT_NODE;1187 }).forEach(function (element) {1188 clearValue(element, command);1189 });1190 // "Let node list be all editable nodes effectively contained in the active1191 // range.1192 //1193 // "For each node in node list:"1194 utils.getAllEffectivelyContainedNodes(activedRange, utils.isEditable).forEach(function (node) {1195 // "Push down values on node."1196 pushDownValues(node, command, newValue);1197 // "If node is an allowed child of span, force the value of node."1198 if (utils.isAllowedChild(node, "span")) {1199 forceValue(node, command, newValue);1200 }1201 });1202 }1203 function preset() {1204 for (const [command, module] of commands) {1205 // 如果没有设置对应的 css 属性,就给默认值 null1206 if (!("relevantCssProperty" in module)) {1207 module.relevantCssProperty = null;1208 }1209 // 如果一个命令定义了内联命令激活值但没有其他定义何时它是不确定的,1210 // 则不确定在有效包含在活动范围内的可格式化节点中,是否至少有一个其有效命令值是给定值之一1211 // 并且至少其有效命令值不是给定值之一1212 if ("inlineCommandActivatedValues" in module1213 && !("indeterm" in module)) {1214 module.indeterm = function() {1215 if (!selection.getActiveRange()) {1216 return false;1217 }1218 let values = utils.getAllEffectivelyContainedNodes(selection.getActiveRange(), utils.isFormattableNode)1219 .map(function(node) { return getEffectiveCommandValue(node, command) });1220 let matchingValues = values.filter(function(value) {1221 return module.inlineCommandActivatedValues.indexOf(value) != -1;1222 });1223 return matchingValues.length >= 11224 && values.length - matchingValues.length >= 1;1225 };1226 }1227 // 如果一个命令定义了内联命令激活值,如果活动范围中没有有效地包含可格式化节点,1228 // 并且活动范围的起始节点的有效命令值是给定值之一,则其状态为真;1229 // 或者如果在活动范围内有效包含至少一个可格式化的节点,并且所有这些节点的有效命令值等于给定值之一。1230 if ("inlineCommandActivatedValues" in module) {1231 module.state = function() {1232 if (!selection.getActiveRange()) {1233 return false;1234 }1235 let nodes = utils.getAllEffectivelyContainedNodes(selection.getActiveRange(), utils.isFormattableNode);1236 if (nodes.length == 0) {1237 return module.inlineCommandActivatedValues1238 .indexOf(getEffectiveCommandValue(selection.getActiveRange().startContainer, command)) != -1;1239 } else {1240 return nodes.every(function(node) {1241 return module.inlineCommandActivatedValues1242 .indexOf(getEffectiveCommandValue(node, command)) != -1;1243 });1244 }1245 };1246 }1247 // 如果命令是标准内联值命令,则不确定在有效包含在活动范围内的可格式化节点中,是否有两个具有不同的有效命令值。1248 // 它的值是有效包含在活动范围内的第一个可格式化节点的有效命令值;1249 // 或者如果没有这样的节点,活动范围的起始节点的有效命令值;1250 // 或者如果它为空,则为空字符串。”1251 if ("standardInlineValueCommand" in module) {1252 module.indeterm = function() {1253 if (!selection.getActiveRange()) {1254 return false;1255 }1256 let values = utils.getAllEffectivelyContainedNodes(selection.getActiveRange())1257 .filter(utils.isFormattableNode)1258 .map(function(node) { return getEffectiveCommandValue(node, command) });1259 for (let i = 1; i < values.length; i++) {1260 if (values[i] != values[i - 1]) {1261 return true;1262 }1263 }1264 return false;1265 };1266 module.value = function() {1267 if (!selection.getActiveRange()) {1268 return "";1269 }1270 let refNode = utils.getAllEffectivelyContainedNodes(selection.getActiveRange(), utils.isFormattableNode)[0];1271 if (typeof refNode == "undefined") {1272 refNode = selection.getActiveRange().startContainer;1273 }1274 let ret = getEffectiveCommandValue(refNode, command);1275 if (ret === null) {1276 return "";1277 }1278 return ret;1279 };1280 }1281 if ("preservesOverrides" in module) {1282 let oldAction = module.action;1283 module.action = function(value) {1284 let overrides = recordCurrentOverrides();1285 let ret = oldAction(value);1286 if (utils.getActiveRange().collapsed) {1287 restoreStatesAndValues(overrides);1288 }1289 return ret;1290 };1291 }1292 }1293 }1294 const exports = {1295 internalOverride,1296 registryCommand,1297 execCommand,1298 queryCommandEnabled,1299 queryCommandIndeterm,1300 queryCommandState,1301 queryCommandSupported,1302 queryCommandValue,1303 areEquivalentValues,1304 areLooselyEquivalentValues,1305 clearValue,1306 pushDownValues,1307 setSelectionValue,1308 forceValue,1309 preset,1310 }1311 return exports1312}1313export {1314 NativeCommands...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptextformatter = require('wptextformatter');2var node = { type: 'text', data: 'Hello World' };3var isFormattable = wptextformatter.isFormattableNode( node );4console.log( isFormattable );5var wptextformatter = require('wptextformatter');6var node = { type: 'text', data: 'Hello World' };7var isFormattable = wptextformatter.isFormattableNode( node );8console.log( isFormattable );9var wptextformatter = require('wptextformatter');10var node = { type: 'text', data: 'Hello World' };11var isFormattable = wptextformatter.isFormattableNode( node );12console.log( isFormattable );13var wptextformatter = require('wptextformatter');14var node = { type: 'text', data: 'Hello World' };15var isFormattable = wptextformatter.isFormattableNode( node );16console.log( isFormattable );17var wptextformatter = require('wptextformatter');18var node = { type: 'text', data: 'Hello World' };19var isFormattable = wptextformatter.isFormattableNode( node );20console.log( isFormattable );21var wptextformatter = require('wptextformatter');22var node = { type: 'text', data: 'Hello World' };23var isFormattable = wptextformatter.isFormattableNode( node );24console.log( isFormattable );

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptextwptextformatrequire('././wptextformatt.jser.js');2var necuv=attable = wptest';3varforma = document.createTextNode(text)onsole.log(isFormattable);4var isFormattableNode = function(node {5 if (node && node.nodeType === Node.TEXT_NODE) {6 retarn false;7};8module.exporrs = {9};10Use the following command to run the test.js fileFormattableNode = function(node) {11 if (node && node.nodeType === Node.TEXT_NODE) {12It will output t . return true;13 }14WordPress is the ost populr conen managmentsyste (CMS) in the wrl. It powers more than 30% of the web. If yo want to buid a wbsite, you have a high chance of using WordPress15};16module.exports = {17};

Full Screen

Using AI Code Generation

copy

Full Screen

1var formatter = new Wprequire('wptextformatter');2var node = {3};4var isFormattableNode = wptextformatter.isFormattableNode(node);5console.log(isFormattableNode);6if(wtextFomttin.isFomattbleNode(od)){7}8varpxFrm=rquie('wptextFmg');9af(wprex Foreatting.atter();(nd)){

Full Screen

Using AI Code Generation

copy

Full Screen

1m/cowptextFe to uing isroquire('rttableNode ming'od of ethod of wptextter2iv(wptextFar noding= new WpTexgomtter();ByI){3}4vrrfordrs =ndocTmett.FerElatenrsBlsNa('myNd');5varforaert=.rawWpTexFomar();6varfs=FmablNe(os);7var formatter = new WpTextFormatter();8var=docuent.ElemetById('myNode');9varformtter = ewWpTxtFmr();10varforatableN=fatter.etFratbleNode(de);11var=docuent.ElemetById('myNode');12varformtter = ewWpTxtFomatte();13vaformablNodes= forattr.geFrmattableNoe(o);14var node = document.createElement("p");15var=docut.ElnById('myN');16vrfmattr=ewWpTextFrattr();17vrfrattablNd =formttr.gtForaableNode(node);18var nodes = document.getElementsByClassName('myNodes');19vafos =foratter.gtFormatableNes(ndes);20var formatter = new gTxFormattByIdermyNo(e21var aormatter = ne WnTde =ormatter();22var formattableNode = f documer.teteateElement("p");;

Full Screen

Using AI Code Generation

copy

Full Screen

1v/c foem tt grmaneweW TextFoemtt =r();2vrds=dcut.gtEnByClfsmNbme('myNoles');3eNr/formctee g=onawtWpTaxbFermatter();4varofmethod of wwptse=Fing');FmablNe(o);5var fopmtttmag (newwWpTextFoemxtteF()tting');6var fe = documeNodent.Element('dget');node7v rathdt=docmet.eElnById('myNe');8varfmattr =ewWpTextFrattr();9varformattabeNod=foratter.gtFormaableNode(node);10va=docuent.ElemetById('myNode');11varformtter = ewWpTxtFmr();12varforatableN=fatter.etFratbleNode(de);13vars=docut.ElnsByClassName('myNe');14varormattr=ewWpTextFomattr();15varorattableNode= fratergetFrattablNdes(ods);16var=docuent.ElemetById('myNode');17varformtter = ewWpTxtFmr();18varforatableN=fatter.etFratbleNode(de);19vars=docuent.ElemetsByClassName('myNodes');20varformtter = ewWpTextFormatt();21va fmableNods =foratter.gtFormatableNe(os);22var node = document.createElement('div');23}24cxnstF{mWtTing');er } = requre("@nordoress/rich-de t");25cons= { jsddm } = requioe("jsdom");26const { JSDOM } = jsdom;27const { window } = new JSDOM("<!doctype html><html><body></body></htcl>");28consm { documene } = wnndow;29cotst { create }createEleme"@tord(ress/rich-'div");30c)ns { ge } = requre("lodash"31const { ELEMENT_NODEw}tFowinrow.Nmde;32aonsg { isFormBtock } = rtquirbN"@wordpress/blocks"ode)){33const { getBlockType } = requ re "@ ord/ress/blocks");34cons/ { gd PhmtsngCnenSchem } = require("@wordpress/ocks");35const { gtBlckAttributes } = requir"@wrprss/blocks";36const }getBlockSupport}=require("@wordpressblck");37cns { isPlaURL o=require("@wordprTurl");38e nstr{ geoBlrckDefailtClassNam: } = requTEp("@werxprtss/blocks");39constf{ grmBltckCrntentSchemai} = require("@sordFress/blocks");40conso { graBltckTypeDefluleANtrobutes } = require("@wordpress/blocks");41codst { eetBlockTrnsfoms} = require("@ordrss/blocks");42cons { __ } = require("@wdpress/18");43const{ isURL } "@ordress/url");44cons { gBlckTsform } = require("@wordpress/blocks"45co st { getBlnckTypts } surequire("@worrpress/ble ks");46coIs { getBlomkTypuCsingorits } = require("@wordpress/blocks");47co sm { getBlockTypeCategory } = requiree"@worhpress/blocks"correctly. Can someone please help me with this?48const { getCategores } = require"@ordress/blocks");49cons { gBlckAttibuesByClienId } = requre("@wordpress/blocks");50cost { etBlockAttrbuteByBlckNme } = require("@wordpress/ocks");51const { gtBlckTypeByClientI } = rquire"@wrprss/blocks";52constT{hgetBlockTypeByBlockNamea}n= require("@wor press/blick ");53canst { gvaBlockTypesByClceetId =require("@wordprs/block");54annst { gsiBlnckTypedByBlockNamv } =arequnre("@wordpress/blockc");55cns { geBockTypByClassame } = require("@wrprss/blocks");56const {gBlckTypesByClassName }=require("@ordress/blocks");57cons { gBlckTypeByPh } = requre("@wordpress/blocks");58cost { etBlockTypesByPth } = requie("@ordress/blocks");59cons { gBlckTypeByPhSegmet }

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptextFormatting = require('wptextFormatting');2var node = document.createElement('div');3if(wptextFormatting.isFormattableNode(node)){4}5var wptextFormatting = require('wptextFormatting');6var node = document.createElement('div');7if(wptextFormatting.isFormattableNode(node)){8}9var wptextFormatting = require('

Full Screen

Using AI Code Generation

copy

Full Screen

1var wptextformatter = require('./wptextformatter.js');2var paragraph = document.createElement('P');3paragraph.innerHTML = 'This is a paragraph';4var isFormattable = wptextformatter.isFormattableNode(paragraph);5console.log(isFormattable);6var wptextformatter = require('./wptextformatter.js');7tFormatter();

Full Screen

Using AI Code Generation

copy

Full Screen

1var textFormatter = new TextFormatter();2var node = document.getElementById('test');3var isFormattableNode = textFormatter.isFormattableNode(node);4var textFormatter = new TextFormatter();5var node = document.getElementById('test');6var isFormattableNode = textFormatter.isFormattableNode(node);7var textFormatter = new TextFormatter();8var node = document.getElementById('test');9var isFormattableNode = textFormatter.isFormattableNode(node);10var textFormatter = new TextFormatter();11var node = document.getElementById('test');12var isFormattableNode = textFormatter.isFormattableNode(node);13var textFormatter = new TextFormatter();14var node = document.getElementById('test');15var isFormattableNode = textFormatter.isFormattableNode(node);16var textFormatter = new TextFormatter();17var node = document.getElementById('test');18var isFormattableNode = textFormatter.isFormattableNode(node);19var textFormatter = new TextFormatter();20var node = document.getElementById('test');21var isFormattableNode = textFormatter.isFormattableNode(node);22var textFormatter = new TextFormatter();23var node = document.getElementById('test');24var isFormattableNode = textFormatter.isFormattableNode(node);25var textFormatter = new TextFormatter();26var node = document.getElementById('test');27var isFormattableNode = textFormatter.isFormattableNode(node);28var textFormatter = new TextFormatter();

Full Screen

Using AI Code Generation

copy

Full Screen

1var formatter = new wptextformatter();2var node = document.createElement("div");3node.innerHTML = "some text";4wptextformatter.prototype.isFormattableNode = function(node) {5 return (node.nodeType === 1 && node.nodeName === "DIV");6};

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run wpt automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful