mdast#Text TypeScript Examples

The following examples show how to use mdast#Text. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From dendron with GNU Affero General Public License v3.0 7 votes vote down vote up
/** Given a header, finds the text of that header, including any wikilinks or hashtags that are included in the header.
   *
   * For example, for the header `## Foo [[Bar|bar]] and #baz`, the text should be `Foo Bar and #baz`.
   */
  static headerText(header: Heading): string {
    const headerText: string[] = [];
    visit(header, (node) => {
      switch (node.type) {
        case DendronASTTypes.TEXT:
          headerText.push((node as Text).value);
          break;
        case DendronASTTypes.WIKI_LINK:
          headerText.push((node as WikiLinkNoteV4).data.alias);
          break;
        case DendronASTTypes.HASHTAG:
          headerText.push((node as HashTag).value);
          break;
        case DendronASTTypes.USERTAG:
          headerText.push((node as UserTag).value);
          break;
        case DendronASTTypes.INLINE_CODE:
          headerText.push((node as InlineCode).value);
          break;
        default:
        /* nothing */
      }
    });
    return _.trim(headerText.join(""));
  }
Example #2
Source File: dendronPreview.ts    From dendron with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
 * Transforms any UserTag or HashTag nodes into a vscode command URI for gotoNote.
 */
function modifyTagValueToCommandUri({
  proc,
  node,
}: {
  proc: Unified.Processor;
  node: UserTag | HashTag;
}) {
  const { vault } = MDUtilsV5.getProcData(proc);

  const goToNoteCommandOpts = {
    qs: node.fname,
    vault,
  };

  const encodedArgs = encodeURIComponent(JSON.stringify(goToNoteCommandOpts));

  // Convert the node to a 'link' type so that it can behave properly like a
  // link instead of the tag behavior, since we've changed the value to a
  // command URI
  (node as unknown as Link).type = "link";
  (node as unknown as Link).url = `command:dendron.gotoNote?${encodedArgs}`;

  const childTextNode: Text = {
    type: "text",
    value: node.value,
  };

  (node as unknown as Link).children = [childTextNode];
}
Example #3
Source File: utils.ts    From dendron with GNU Affero General Public License v3.0 6 votes vote down vote up
static isText(node: Node): node is Text {
    return node.type === DendronASTTypes.TEXT;
  }
Example #4
Source File: utils.ts    From dendron with GNU Affero General Public License v3.0 6 votes vote down vote up
getLinkCandidates = ({
  ast,
  note,
  engine,
}: {
  ast: DendronASTNode;
  note: NoteProps;
  engine: DEngineClient;
}) => {
  const textNodes: Text[] = [];
  visit(
    ast,
    [DendronASTTypes.TEXT],
    (node: Text, _index: number, parent: Parent | undefined) => {
      if (parent?.type === "paragraph" || parent?.type === "tableCell") {
        textNodes.push(node);
      }
    }
  );

  const linkCandidates: DLink[] = [];
  _.map(textNodes, (textNode: Text) => {
    const value = textNode.value as string;
    value.split(/\s+/).forEach((word) => {
      const possibleCandidates = NoteUtils.getNotesByFnameFromEngine({
        fname: word,
        engine,
        vault: note.vault,
      }).filter((note) => note.stub !== true);
      linkCandidates.push(
        ...possibleCandidates.map((candidate): DLink => {
          const startColumn = value.indexOf(word) + 1;
          const endColumn = startColumn + word.length;

          const position: Position = {
            start: {
              line: textNode.position!.start.line,
              column: startColumn,
              offset: textNode.position!.start.offset
                ? textNode.position!.start.offset + startColumn - 1
                : undefined,
            },
            end: {
              line: textNode.position!.start.line,
              column: endColumn,
              offset: textNode.position!.start.offset
                ? textNode.position!.start.offset + endColumn - 1
                : undefined,
            },
          };
          return {
            type: "linkCandidate",
            from: NoteUtils.toNoteLoc(note),
            value: value.trim(),
            position,
            to: {
              fname: word,
              vaultName: VaultUtils.getName(candidate.vault),
            },
          };
        })
      );
    });
  });
  return linkCandidates;
}
Example #5
Source File: case.ts    From reskript with MIT License 6 votes vote down vote up
parseToCase = async ([heading, meta, ...nodes]: Content[]): Promise<PlayCase | null> => {
    if (heading.type !== 'heading' || heading.depth !== 2) {
        return null;
    }

    const replCodeBlock = findReplCodeBlock(nodes);

    if (!replCodeBlock) {
        return null;
    }

    const description = stringifyNodesToMarkdown(nodes.filter(v => v !== replCodeBlock));
    const metaInfo = await extractMeta(meta);
    return {
        name: (heading.children[0] as Text).value,
        description: description.trim(),
        code: (replCodeBlock as Code).value,
        ...metaInfo,
    };
}
Example #6
Source File: case.ts    From reskript with MIT License 5 votes vote down vote up
isMatchCaseName = (nodes: Content[], name: string): boolean => {
    const [heading] = nodes;
    return heading.type === 'heading' && heading.depth === 2 && (heading.children[0] as Text).value === name;
}
Example #7
Source File: toc.ts    From website-docs with MIT License 5 votes vote down vote up
function getContentFromLink(
  content: Paragraph,
  config: PathConfig
): RepoNavLink {
  if (content.type !== 'paragraph' || content.children.length === 0) {
    throw new Error(`incorrect format in TOC.md`)
  }

  const child = content.children[0] as Link | Text

  if (child.type === 'link') {
    if (child.children.length === 0) {
      throw new Error(`incorrect link in TOC.md`)
    }

    const content = child.children.map(node => {
      switch (node.type) {
        case 'text':
          return node.value
        case 'inlineCode':
          return { code: true, value: node.value }
        default:
          throw new Error(`unsupported tag ${node.type} in TOC link`)
      }
    })

    if (child.url.startsWith('https://')) {
      return {
        link: child.url,
        content,
      }
    }

    const urlSegs = child.url.split('/')
    const filename = urlSegs[urlSegs.length - 1].replace('.md', '')

    return {
      link: generateUrl(filename, config),
      content,
    }
  } else {
    return {
      content: [child.value],
    }
  }
}
Example #8
Source File: descriptionFormatter.ts    From prettier-plugin-jsdoc with MIT License 4 votes vote down vote up
/**
 * Trim, make single line with capitalized text. Insert dot if flag for it is
 * set to true and last character is a word character
 *
 * @private
 */
function formatDescription(
  tag: string,
  text: string,
  options: AllOptions,
  formatOptions: FormatOptions,
): string {
  if (!text) return text;

  const { printWidth } = options;
  const { tagStringLength = 0, beginningSpace } = formatOptions;

  /**
   * change list with dash to dot for example:
   * 1- a thing
   *
   * to
   *
   * 1. a thing
   */
  text = text.replace(/^(\d+)[-][\s|]+/g, "$1. "); // Start
  text = text.replace(/\n+(\s*\d+)[-][\s]+/g, "\n$1. ");

  const fencedCodeBlocks = text.matchAll(/```\S*?\n[\s\S]+?```/gm);
  const indentedCodeBlocks = text.matchAll(
    /^\r?\n^(?:(?:(?:[ ]{4}|\t).*(?:\r?\n|$))+)/gm,
  );
  const allCodeBlocks = [...fencedCodeBlocks, ...indentedCodeBlocks];
  const tables: string[] = [];
  text = text.replace(
    /((\n|^)\|[\s\S]*?)((\n[^|])|$)/g,
    (code, _1, _2, _3, _, offs: number) => {
      // If this potential table is inside a code block, don't touch it
      for (const block of allCodeBlocks) {
        if (
          block.index !== undefined &&
          block.index <= offs + 1 &&
          offs + code.length + 1 <= block.index + block[0].length
        ) {
          return code;
        }
      }

      code = _3 ? code.slice(0, -1) : code;

      tables.push(code);
      return `\n\n${TABLE}\n\n${_3 ? _3.slice(1) : ""}`;
    },
  );

  if (
    options.jsdocCapitalizeDescription &&
    !TAGS_PEV_FORMATE_DESCRIPTION.includes(tag)
  ) {
    text = capitalizer(text);
  }

  text = `${tagStringLength ? `${"!".repeat(tagStringLength - 1)}?` : ""}${
    text.startsWith("```") ? "\n" : ""
  }${text}`;

  let tableIndex = 0;

  const rootAst = fromMarkdown(text);

  function stringifyASTWithoutChildren(
    mdAst: Content | Root,
    intention: string,
    parent: Content | Root | null,
  ) {
    if (mdAst.type === "inlineCode") {
      return `\`${mdAst.value}\``;
    }

    if (mdAst.type === "code") {
      let result = mdAst.value || "";
      let _intention = intention;

      if (result) {
        // Remove two space from lines, maybe added previous format
        if (mdAst.lang) {
          const supportParsers = parserSynonyms(mdAst.lang.toLowerCase());
          const parser = supportParsers?.includes(options.parser as any)
            ? options.parser
            : supportParsers?.[0] || mdAst.lang;

          result = formatCode(result, intention, {
            ...options,
            parser,
            jsdocKeepUnParseAbleExampleIndent: true,
          });
        } else if (options.jsdocPreferCodeFences || false) {
          result = formatCode(result, _intention, {
            ...options,
            jsdocKeepUnParseAbleExampleIndent: true,
          });
        } else {
          _intention = intention + " ".repeat(4);

          result = formatCode(result, _intention, {
            ...options,
            jsdocKeepUnParseAbleExampleIndent: true,
          });
        }
      }
      const addFence = options.jsdocPreferCodeFences || !!mdAst.lang;
      result = addFence ? result : result.trimEnd();
      return result
        ? addFence
          ? `\n\n${_intention}\`\`\`${mdAst.lang || ""}${result}\`\`\``
          : `\n${result}`
        : "";
    }

    if ((mdAst as Text).value === TABLE) {
      if (parent) {
        (parent as any).costumeType = TABLE;
      }

      if (tables.length > 0) {
        let result = tables?.[tableIndex] || "";
        tableIndex++;
        if (result) {
          result = format(result, {
            ...options,
            parser: "markdown",
          }).trim();
        }
        return `${
          result
            ? `\n\n${intention}${result.split("\n").join(`\n${intention}`)}`
            : (mdAst as Text).value
        }`;
      }
    }

    if (mdAst.type === "break") {
      return `\\\n`;
    }

    return ((mdAst as Text).value ||
      (mdAst as Link).title ||
      (mdAst as Image).alt ||
      "") as string;
  }

  function stringyfy(
    mdAst: Content | Root,
    intention: string,
    parent: Content | Root | null,
  ): string {
    if (!Array.isArray((mdAst as Root).children)) {
      return stringifyASTWithoutChildren(mdAst, intention, parent);
    }

    return ((mdAst as Root).children as Content[])
      .map((ast, index) => {
        switch (ast.type) {
          case "listItem": {
            let _listCount = `\n${intention}- `;
            // .replace(/((?!(^))\n)/g, "\n" + _intention);
            if (typeof (mdAst as List).start === "number") {
              const count = index + (((mdAst as List).start as number) ?? 1);
              _listCount = `\n${intention}${count}. `;
            }

            const _intention = intention + " ".repeat(_listCount.length - 1);

            const result = stringyfy(ast, _intention, mdAst).trim();

            return `${_listCount}${result}`;
          }

          case "list": {
            let end = "";
            /**
             * Add empty line after list if that is end of description
             * issue: {@link https://github.com/hosseinmd/prettier-plugin-jsdoc/issues/98}
             */
            if (
              tag !== DESCRIPTION &&
              mdAst.type === "root" &&
              index === mdAst.children.length - 1
            ) {
              end = "\n";
            }
            return `\n${stringyfy(ast, intention, mdAst)}${end}`;
          }

          case "paragraph": {
            const paragraph = stringyfy(ast, intention, parent);
            if ((ast as any).costumeType === TABLE) {
              return paragraph;
            }

            return `\n\n${paragraph
              /**
               * Break by backslash\
               * issue: https://github.com/hosseinmd/prettier-plugin-jsdoc/issues/102
               */
              .split("\\\n")
              .map((_paragraph) => {
                const links: string[] = [];
                // Find jsdoc links and remove spaces
                _paragraph = _paragraph.replace(
                  /{@(link|linkcode|linkplain)[\s](([^{}])*)}/g,
                  (_, tag: string, link: string) => {
                    links.push(link);

                    return `{@${tag}${"_".repeat(link.length)}}`;
                  },
                );

                _paragraph = _paragraph.replace(/\s+/g, " "); // Make single line

                if (
                  options.jsdocCapitalizeDescription &&
                  !TAGS_PEV_FORMATE_DESCRIPTION.includes(tag)
                )
                  _paragraph = capitalizer(_paragraph);
                if (options.jsdocDescriptionWithDot)
                  _paragraph = _paragraph.replace(/([\w\p{L}])$/u, "$1."); // Insert dot if needed

                let result = breakDescriptionToLines(
                  _paragraph,
                  printWidth,
                  intention,
                );

                // Replace links
                result = result.replace(
                  /{@(link|linkcode|linkplain)([_]+)}/g,
                  (original: string, tag: string, underline: string) => {
                    const link = links[0];

                    if (link.length === underline.length) {
                      links.shift();
                      return `{@${tag} ${link}}`;
                    }

                    return original;
                  },
                );

                return result;
              })
              .join("\\\n")}`;
          }

          case "strong": {
            return `**${stringyfy(ast, intention, mdAst)}**`;
          }

          case "emphasis": {
            return `_${stringyfy(ast, intention, mdAst)}_`;
          }

          case "heading": {
            return `\n\n${intention}${"#".repeat(ast.depth)} ${stringyfy(
              ast,
              intention,
              mdAst,
            )}`;
          }

          case "link":
          case "image": {
            return `[${stringyfy(ast, intention, mdAst)}](${ast.url})`;
          }

          case "linkReference": {
            return `[${stringyfy(ast, intention, mdAst)}][${ast.label}]`;
          }
          case "definition": {
            return `\n\n[${ast.label}]: ${ast.url}`;
          }

          case "blockquote": {
            const paragraph = stringyfy(ast, "", mdAst);
            return `${intention}> ${paragraph
              .trim()
              .replace(/(\n+)/g, `$1${intention}> `)}`;
          }
        }
        return stringyfy(ast, intention, mdAst);
      })
      .join("");
  }

  let result = stringyfy(rootAst, beginningSpace, null);

  result = result.replace(/^[\s\n]+/g, "");
  result = result.replace(/^([!]+\?)/g, "");

  return result;
}