<commit_before>_ = require 'underscore-plus'
{Range} = require 'atom'

TOC_END = '<!-- TOC END -->'
TOC_START_REGEXP = /<!\-\- TOC START (.*)?\-\->/i
TOC_END_REGEXP = ///#{_.escapeRegExp(TOC_END)}///i

# TOC generation
# -------------------------
linkFor = (text) ->
  text
    .toLowerCase()
    .replace(/\s/g, '-')
    .replace(/\<(.*?)>(.+)<\/\1>/g, "$2") # e.g. exract 'a' from <kbd>a<kbd>
    .replace(/[^\w-]/g, '') # Remove non-(alphanumeric or '-') char.

titleFor = (text) ->
  text
    .replace(/!\[.*?\]\(https?:\/\/.*?\)/g, "") # Remove img link
    .replace(/\[(.*?)\]\(https?:\/\/.*?\)/g, "$1") # extract link txt
    .trim()

# Set title and link
setTitleAndLink = (headers) ->
  countByLink = {}

  for header in headers
    title = titleFor(header.subject)
    link = linkFor(title)

    if not (link of countByLink)
      countByLink[link] = 0
      linkSuffix = ''
    else
      countByLink[link] += 1
      linkSuffix = "-" + countByLink[link]

    header.title = title
    header.link = link + linkSuffix

generateToc = (headers, options) ->
  indentBase = "  "
  headers
    .filter (header) ->
      options.min <= header.level <= options.max

    .map ({level, title, link}) ->
      indent = indentBase.repeat(level-1)
      if options.link
        "#{indent}- [#{title}](##{link})"
      else
        "#{indent}- [#{title}]"

    .join("\n")

# Extract markdown headers from editor
# -------------------------
isMarkdownHeader = (editor, bufferPosition) ->
  {scopes} = editor.scopeDescriptorForBufferPosition(bufferPosition)
  scopes[1]?.startsWith('markup.heading') or scopes[1]?.startsWith('heading.markup.md')

MARKDOWN_HEADER_REGEXP = /^(#+)\s*(.*$)$/g
scanHeaders = (editor) ->
  headers = []
  editor.scan MARKDOWN_HEADER_REGEXP, ({match, range}) ->
    return unless isMarkdownHeader(editor, range.start)
    level = match[1].length
    subject = match[2]
    headers.push({level, subject})
  headers

# Misc
# -------------------------
deserializeTocOptions = (text) ->
  options = {}
  for param in text.trim().split(/\s+/)
    [key, value] = param.split(':')
    switch key
      when 'min', 'max' # integer<commit_msg>respect `min` in TOC indentation<commit_after>_ = require 'underscore-plus'
{Range} = require 'atom'

TOC_END = '<!-- TOC END -->'
TOC_START_REGEXP = /<!\-\- TOC START (.*)?\-\->/i
TOC_END_REGEXP = ///#{_.escapeRegExp(TOC_END)}///i

# TOC generation
# -------------------------
linkFor = (text) ->
  text
    .toLowerCase()
    .replace(/\s/g, '-')
    .replace(/\<(.*?)>(.+)<\/\1>/g, "$2") # e.g. exract 'a' from <kbd>a<kbd>
    .replace(/[^\w-]/g, '') # Remove non-(alphanumeric or '-') char.

titleFor = (text) ->
  text
    .replace(/!\[.*?\]\(https?:\/\/.*?\)/g, "") # Remove img link
    .replace(/\[(.*?)\]\(https?:\/\/.*?\)/g, "$1") # extract link txt
    .trim()

# Set title and link
setTitleAndLink = (headers) ->
  countByLink = {}

  for header in headers
    title = titleFor(header.subject)
    link = linkFor(title)

    if not (link of countByLink)
      countByLink[link] = 0
      linkSuffix = ''
    else
      countByLink[link] += 1
      linkSuffix = "-" + countByLink[link]

    header.title = title
    header.link = link + linkSuffix

generateToc = (headers, options) ->
  indentBase = "  "
  headers
    .filter (header) ->
      options.min <= header.level <= options.max

    .map ({level, title, link}) ->
      indent = indentBase.repeat(level-options.min)
      if options.link
        "#{indent}- [#{title}](##{link})"
      else
        "#{indent}- [#{title}]"

    .join("\n")

# Extract markdown headers from editor
# -------------------------
isMarkdownHeader = (editor, bufferPosition) ->
  {scopes} = editor.scopeDescriptorForBufferPosition(bufferPosition)
  scopes[1]?.startsWith('markup.heading') or scopes[1]?.startsWith('heading.markup.md')

MARKDOWN_HEADER_REGEXP = /^(#+)\s*(.*$)$/g
scanHeaders = (editor) ->
  headers = []
  editor.scan MARKDOWN_HEADER_REGEXP, ({match, range}) ->
    return unless isMarkdownHeader(editor, range.start)
    level = match[1].length
    subject = match[2]
    headers.push({level, subject})
  headers

# Misc
# -------------------------
deserializeTocOptions = (text) ->
  options = {}
  for param in text.trim().split(/\s+/)
    [key, value] = param.split(':')
    switch key
      when 'min', 'max' # integer
{'fraction_non_alphanumeric': 0.2326812428078251, 'fraction_numerical': 0.004372842347525892, 'mean_word_length': 2.4879614767255216, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3049441', 'n_tokens_mistral': 1529, 'n_tokens_neox': 1512, 'n_words': 311}