import { flow, identity } from "fp-ts-esm/function";
import { not } from "fp-ts-esm/Predicate";
import * as S from "fp-ts-esm/string";
import { serialize } from "parse5";
import { and, or } from "../../../../fp-utils.js";
import { partitionBy } from "../../../node-utils.js";
import { traverse, traverseRoot } from "../core/ast-traversal.js";
import {
  appendChild,
  hasChild,
  hasClass,
  hasDescendant,
  hasParent,
  hasStyleFor,
  hasTag,
  isText,
  isWhitespace,
  oneOf,
  toAst
} from "../core/parse5-utils.js";
import { addParagraph, rootTextToP } from "../core/preprocess.js";
const containerPToDiv = [
  // @ts-ignore $TSFixMe
  and([hasTag("p"), hasDescendant(oneOf(["img", "iframe", "ol", "ul"]))]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    tagName: "div",
    nodeName: "div",
    childNodes: partitionBy(
      // @ts-ignore $TSFixMe
      hasDescendant(oneOf(["img", "iframe", "ol", "ul"])),
      hasTag("p"),
      identity,
      addParagraph(node),
      // @ts-ignore $TSFixMe
      appendChild
    )(node.childNodes)
  })
];
const collapseWhitespaces = [
  and([
    // @ts-ignore $TSFixMe
    isText,
    // @ts-ignore $TSFixMe
    isWhitespace,
    // @ts-ignore $TSFixMe
    hasParent(not(oneOf(["p", "span", "h1", "h2", "h3", "h4", "h5", "h6"])))
  ]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    value: ""
  })
];
const wrapPWithLiInList = [
  // @ts-ignore $TSFixMe
  and([hasTag("p"), hasParent(oneOf(["ul", "ol"]))]),
  // @ts-ignore $TSFixMe
  (node) => {
    const listItem = {
      nodeName: "li",
      tagName: "li",
      childNodes: [],
      attrs: [],
      parentNode: node.parentNode,
      namespaceURI: node.namespaceURI
    };
    const childNode = { ...node, parentNode: listItem };
    listItem.childNodes.push(childNode);
    return listItem;
  }
];
const cleanListPadding = [
  oneOf(["ol", "ul"]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    childNodes: node.childNodes.filter(not(isText))
  })
];
const cleanListItemPadding = [
  hasTag("li"),
  // @ts-ignore $TSFixMe
  (el) => ({
    ...el,
    // @ts-ignore $TSFixMe
    childNodes: el.childNodes.filter(and([not(hasTag("br")), not(isWhitespace)]))
  })
];
const cleanInvalidVideos = [
  and([
    // @ts-ignore $TSFixMe
    hasTag("div"),
    // @ts-ignore $TSFixMe
    hasClass((c) => c === "container-video"),
    // @ts-ignore $TSFixMe
    not(hasDescendant(hasTag("iframe")))
  ]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    childNodes: []
  })
];
const wrapTextUnderLi = [
  and([
    // @ts-ignore $TSFixMe
    hasTag("li"),
    // @ts-ignore $TSFixMe
    or([hasChild(isText), hasChild(oneOf(["a", "u", "em", "strong", "s", "strike", "del"]))])
  ]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    childNodes: partitionBy(
      or([
        // @ts-ignore $TSFixMe
        hasTag("p"),
        // @ts-ignore $TSFixMe
        hasDescendant(oneOf(["h1", "h2", "h3", "h4", "h5", "h6", "img", "iframe", "ol", "ul"]))
      ]),
      hasTag("p"),
      identity,
      addParagraph(node),
      // @ts-ignore $TSFixMe
      appendChild
    )(node.childNodes)
  })
];
const ignoreNakedSpanParents = [
  "strong",
  "b",
  "u",
  "i",
  "em",
  "s",
  "strike",
  "del",
  "sup",
  "sub",
  "a",
  "p",
  "span",
  "h1",
  "h2",
  "h3",
  "h4",
  "h5",
  "h6"
];
const wrapNakedStyledSpanWithP = [
  and([
    // @ts-ignore $TSFixMe
    hasTag("span"),
    // @ts-ignore $TSFixMe
    or([hasStyleFor("text-decoration"), hasStyleFor("font-weight"), hasStyleFor("font-style")]),
    // @ts-ignore $TSFixMe
    hasParent(not(oneOf(ignoreNakedSpanParents)))
  ]),
  // @ts-ignore $TSFixMe
  (node) => {
    const paragraph = {
      nodeName: "p",
      tagName: "p",
      childNodes: [],
      attrs: [],
      parentNode: node.parentNode,
      namespaceURI: node.namespaceURI
    };
    const childNode = { ...node, parentNode: paragraph };
    paragraph.childNodes.push(childNode);
    return paragraph;
  }
];
const nakedSpanToP = [
  and([
    // @ts-ignore $TSFixMe
    hasTag("span"),
    // @ts-ignore $TSFixMe
    not(hasStyleFor("text-decoration")),
    // @ts-ignore $TSFixMe
    not(hasStyleFor("font-weight")),
    // @ts-ignore $TSFixMe
    not(hasStyleFor("font-style")),
    // @ts-ignore $TSFixMe
    hasParent(not(oneOf(ignoreNakedSpanParents)))
  ]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    nodeName: "p",
    tagName: "p"
  })
];
const isTextLink = and([hasTag("a"), hasChild(isText)]);
const isInlineTag = oneOf(["span", "u", "em", "i", "b", "strong", "strike", "del", "s"]);
const textInDivToP = [
  // @ts-ignore $TSFixMe
  and([hasTag("div"), or([hasChild(isText), hasChild(isTextLink), hasChild(isInlineTag)])]),
  // @ts-ignore $TSFixMe
  (node) => ({
    ...node,
    childNodes: partitionBy(
      // @ts-ignore $TSFixMe
      and([not(isText), not(hasTag("p")), not(isTextLink), not(isInlineTag)]),
      hasTag("p"),
      identity,
      addParagraph(node),
      // @ts-ignore $TSFixMe
      appendChild
    )(node.childNodes)
  })
];
const brToNewLineInRoot = [
  // @ts-ignore $TSFixMe
  and([hasTag("br"), not(hasParent(hasTag("p")))]),
  // @ts-ignore $TSFixMe
  (node) => ({
    parentNode: node.parentNode,
    nodeName: "#text",
    value: "_ROOT_NEW_LINE_MARKER_"
  })
];
const brToNewLineInP = [
  // @ts-ignore $TSFixMe
  and([hasTag("br"), hasParent(hasTag("p"))]),
  // @ts-ignore $TSFixMe
  (node) => ({
    parentNode: node.parentNode,
    nodeName: "#text",
    value: "_P_NEW_LINE_MARKER_"
  })
];
const collapseBreaks = flow(
  S.replace(/(_ROOT_NEW_LINE_MARKER_\s*){3}/gim, " "),
  S.replace(/(_ROOT_NEW_LINE_MARKER_\s*){1,2}/gim, ""),
  S.replace(/(_P_NEW_LINE_MARKER_\s*){3}/gim, "\n\n\n"),
  S.replace(/(_P_NEW_LINE_MARKER_\s*){2}/gim, "\n\n"),
  S.replace(/(_P_NEW_LINE_MARKER_\s*){1}/gim, "\n")
);
const preprocess = flow(
  toAst,
  traverseRoot(rootTextToP),
  flow(traverse(brToNewLineInP), traverse(brToNewLineInRoot)),
  flow(
    traverse(cleanListPadding),
    traverse(cleanListItemPadding),
    traverse(wrapPWithLiInList),
    traverse(cleanInvalidVideos),
    traverse(containerPToDiv)
  ),
  flow(traverse(wrapTextUnderLi), traverse(collapseWhitespaces)),
  // hack to make nakedSpanToP work -- otherwise does not work correctly
  flow(serialize, toAst, traverse(nakedSpanToP), traverse(wrapNakedStyledSpanWithP)),
  traverse(textInDivToP),
  serialize,
  collapseBreaks
);
export {
  preprocess
};
//# sourceMappingURL=preprocess.js.map
