#!/usr/bin/env ruby
sub_counter = 0

add_pattern = /\{\+\+(?<value>.*?)\+\+[ \t]*(?:\[(?<meta>.*?)\])?[ \t]*\}/m

del_pattern = /\{--(?<value>.*?)--[ \t]*(?:\[(?<meta>.*?)\])?[ \t]*\}/m

insdel_comm_pattern = /(?<=[-+=~<]\})[ \t]*\{>>(?<value>.*?)?<<\}/

comm_pattern = /\{>>(?<value>.*?)<<\}/m

# gen_comm_pattern = /\{[ \t]*\[(?<meta>.*?)\][ \t]*\}/m

subs_pattern = /\{~~(?<original>(?:[^~>]|(?:~(?!>)))+)~>(?<new>(?:[^~]+|(?:~(?!~\})))+)~~\}/m

mark_pattern = /\{==(?<value>.*?)==\}/m

fix_grafs_pattern = /^(?<value><(?:del|ins|span|mark).*?)$/m

test_pattern = %(
# The CriticMarkup Syntax

The CriticMarkup syntax is fairly straightforward. The key thing to remember is that CriticMarkup is processed _before_ any other MultiMarkdown is handled. It's almost like a separate layer on top of the MultiMarkdown syntax.

When editing in MultiMarkdown Composer, you can have CriticMarkup syntax flagged in the both the editor pane and the preview window. This will allow you to see changes in the HTML preview.

## Deletions from the original text:

This is {--could be--} a test.


## Additions:

This {++is ++}{>>2024-08-12 10:28:29<<}a test.


## Substitutions:

This {~~isn't~>is~~}{>>BT<<} a test.


## Highlighting:

This is a {==test==}.

## Comments:

This is a test{>>What is it a test of?<<}.
)

def deletion_process(group_object)
  replace_string = ''
  if group_object['value'] == '\n\n'
    '<del>&nbsp;</del>'
  else
    %(<del class="crit">#{group_object['value'].gsub("\n\n", "</del>\n\n<del class=\"crit\">")}</del>)
  end
end

def subs_process(group_object)
  @subcounter += 1
  delString = %(<del class="crit" data-subout="sub#{@subcounter}">#{group_object['original']}</del>)
  insString = %(<ins class="crit" id="sub#{@subcounter}">#{group_object['new']}</ins>)
  "#{delString}#{insString}"
end

# Converts Addition markup to HTML
def addition_process(group_object)
  replace_string = ''

  # Is there a new paragraph followed by new text
  if group_object['value'] =~ /^\n\n/ && group_object['value'] != "\n\n"
    replace_string = "\n\n<span style=\"display:none\"></span><ins class=\"crit criticbreak\">&nbsp;</ins>\n\n"
    replace_string = %(#{replace_string}<span style="display:none"></span><ins class="crit">#{group_object['value'].gsub(
      /\n\n/, "</ins>\n\n<ins class=\"crit\">"
    )}#{group_object['value'].gsub(/\n\n/, "</ins>\n\n<ins class=\"crit\">")})
    replace_string = "#{replace_string}</ins>"
  # Is the addition just a single new paragraph
  elsif group_object['value'] == "\n\n"
    replace_string = "\n\n<span style=\"display:none\"></span><ins class=\"crit criticbreak\">&nbsp;</ins>\n\n"
  # Is it added text followed by a new paragraph?
  elsif group_object['value'] =~ /\n\n$/ && group_object['value'] != "\n\n"
    replace_string = %(<span style="display:none"></span><ins class="crit">#{group_object['value'].gsub(/\n\n/,
                                                                                                       "</ins>\n\n<span style=\"display:none\"></span><ins class=\"crit\"><br>")}</ins>)
    replace_string = "#{replace_string}\n\n<span style=\"display:none\"></span><ins class=\"crit criticbreak\">&nbsp;</ins>\n\n"
  else
    replace_string = %(<span style="display:none"></span><ins class="crit">#{group_object['value'].gsub(/\n\n/,
                                                                                                       "</ins>\n\n<span style=\"display:none\"></span><ins class=\"crit\">")}</ins>)
  end

  replace_string
end

def ins_del_highlight_process(group_object)
  content = group_object['value'].gsub(/\n/, ' ')
  %(<span class="critic criticcomment inline" data-comment="#{content}">&dagger;</span>)
end

def highlight_process(group_object)
  content = group_object['value'].gsub(/\n/, ' ')
  %(<span class="critic criticcomment">#{content}</span>)
end

def mark_process(group_object)
  %(<mark class="crit">#{group_object['value']}</mark>)
end

def fix_grafs_process(group_object)
  %(<p>#{group_object['value']}</p>)
end

@subcounter = 0

# Accept input from Marked.app
# h = test_pattern
h = $stdin.read.force_encoding('utf-8')

h.gsub!(insdel_comm_pattern) do
  m = Regexp.last_match
  ins_del_highlight_process(m)
end

h.gsub!(del_pattern) do
  m = Regexp.last_match
  deletion_process(m)
end

h.gsub!(add_pattern) do
  m = Regexp.last_match
  addition_process(m)
end

h.gsub!(comm_pattern) do
  m = Regexp.last_match
  highlight_process(m)
end

h.gsub!(mark_pattern) do
  m = Regexp.last_match
  mark_process(m)
end

h.gsub!(add_pattern) do
  m = Regexp.last_match
  addition_process(m)
end

h.gsub!(subs_pattern) do
  m = Regexp.last_match
  subs_process(m)
end

h.gsub!(fix_grafs_pattern) do
  m = Regexp.last_match
  fix_grafs_process(m)
end

print h
