From e28666e7fa02b1664de336bb2ff3ed105bc8db7f Mon Sep 17 00:00:00 2001 From: Theo-Hafsaoui Date: Fri, 30 Aug 2024 12:20:40 +0200 Subject: [PATCH] Add applyToSection for Latex --- go.mod | 2 + go.sum | 2 + internal/parser/latex.go | 55 ++++++++++++++-- internal/parser/latex_test.go | 97 ++++++++++++++++++++++++++-- internal/parser/markdown.go | 12 ++-- internal/parser/markdown_test.go | 12 ++-- internal/parser/template_sections.go | 34 ++++++++++ 7 files changed, 191 insertions(+), 23 deletions(-) create mode 100644 go.sum create mode 100644 internal/parser/template_sections.go diff --git a/go.mod b/go.mod index fd1e805..f9b9f73 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module anemon go 1.22.0 + +require github.com/google/go-cmp v0.6.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..5a8d551 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/internal/parser/latex.go b/internal/parser/latex.go index 483cbd3..9824750 100644 --- a/internal/parser/latex.go +++ b/internal/parser/latex.go @@ -1,13 +1,13 @@ package parser -import "os" +import ( + "fmt" + "os" + "strings" +) -//Apply a section to a section type on a latex template -//func (section section, type section_type, template string) +type SectionName string -//to write this template -//func write(template string, name string) -//Todo //Read the template file in the assets directory func read_template()(string,error) { @@ -24,3 +24,46 @@ func writeTemplate(template string, name string)error{ []byte(template), 0644) return err } + +//Apply a section to a section type on a latex template +func applyToSection(section Section, section_type string)(string,error){ + replacements := []string{section.first, section.second, section.third, section.fourth} + template := "" + switch{ + + case section_type == "Professional": + template = replace_param(prof_template,NB_P_PROF,replacements) + template = replace_items(template, section.description) + + case section_type == "Project": + template = replace_param(proj_template,NB_P_PROJ,replacements) + template = replace_items(template, section.description) + + case section_type == "Education": + template = replace_param(edu_template,NB_P_EDU,replacements) + + case section_type == "Skill"://TODO https://github.com/Theo-Hafsaoui/Anemon/issues/1 + template = replace_param(sk_template,NB_P_SK,replacements) + } + return template,nil +} + +//Search and replace the number in range of `nb_params` by their replacement +func replace_param(template string, nb_params int, replacements []string)string{ + for i := 0; i < nb_params; i++ { + position := fmt.Sprintf("%d", i+1) + template = strings.Replace(template, + position, replacements[i], 1) + } + return template +} + +func replace_items(template string, section_items []string)string{ + items := "" + for _,item := range section_items{ + items += strings.Replace(pro_item,"%ITEM%",item,1) + } + template = strings.Replace(template, + "%ITEMS%", items, 1) + return template +} diff --git a/internal/parser/latex_test.go b/internal/parser/latex_test.go index d98b549..48ef74f 100644 --- a/internal/parser/latex_test.go +++ b/internal/parser/latex_test.go @@ -4,6 +4,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/google/go-cmp/cmp" ) func TestReadLatex(t *testing.T) { @@ -20,21 +22,17 @@ func TestReadLatex(t *testing.T) { if err != nil { t.Fatalf("Failed to write file: %v", err) } - content, err := read_template() if err != nil { t.Fatalf("Failed to read file: %v", err) } - if content != "Hello World" { t.Fatalf("Expected 'Hello World', got '%s'", content) } - err = os.Remove(templateFile) if err != nil { t.Fatalf("Failed to remove file: %v", err) } - if _, err := os.Stat(backupFile); err == nil { err = os.Rename(backupFile, templateFile) if err != nil { @@ -42,15 +40,104 @@ func TestReadLatex(t *testing.T) { } } } + func TestWriteLatex(t *testing.T) { err := writeTemplate("Hello, world", "hello") if err != nil { t.Fatalf("Failed to write file: %v", err) } - err = os.Remove("../../assets/latex/output/hello.tex") if err != nil { t.Fatalf("Failed to remove file: %v", err) } } +func TestApplySection(t *testing.T) { + tests := []struct { + name string + section Section + sectionType string + want string + }{ + { + name: "Professional Section", + section: Section{ + first: "first", + second: "second", + third: "third", + fourth: "fourth", + description: []string{"item1", "item2"}, + }, + sectionType: "Professional", + want: ` + \resumeSubheading + {first}{second} + {\href{third}{fourth}}{ } + \resumeItemListStart + \resumeItem{item1} + \resumeItem{item2} + + \resumeItemListEnd + `, + }, + { + name: "Project Section", + section: Section{ + first: "first", + second: "second", + third: "third", + description: []string{"item1", "item2"}, + }, + sectionType: "Project", + want: ` + \resumeProjectHeading + {\textbf{first} $|$ \emph{second \href{third}{\faIcon{github}}}}{} + \resumeItemListStart + \resumeItem{item1} + \resumeItem{item2} + + \resumeItemListEnd + `, + }, + { + name: "Education Section", + section: Section{ + first: "first", + second: "second", + third: "third", + fourth: "fourth", + }, + sectionType: "Education", + want: ` + \resumeSubheading + {\href{first}{second}}{} + {third}{fourth} + `, + }, + { + name: "Skill Section", + section: Section{ + first: "first", + second: "second", + third: "third", + fourth: "fourth", + }, + sectionType: "Skill", + want: ` + \textbf{first}{: second} \\ + `, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := applyToSection(tt.section, tt.sectionType) + if err != nil { + t.Fatalf("error when applying template: %v", err) + } + if diff := cmp.Diff(tt.want, got); diff != "" { + t.Errorf("TestApplySection mismatch (-want +got):\n%s", diff) + } + }) + } +} diff --git a/internal/parser/markdown.go b/internal/parser/markdown.go index d1848d6..ea1f29a 100644 --- a/internal/parser/markdown.go +++ b/internal/parser/markdown.go @@ -8,27 +8,23 @@ import ( /* Section represents a parsed Markdown section with up to four heading levels and a description. -with params_nb the max `depth` of the heading */ type Section struct { first string second string third string fourth string - description string - params_nb int + description []string } /* Parse parses a Markdown-like `paragraph` into a `Section`, extracting headings and description based on the number of leading hashtags. Returns an error if the format is invalid. */ func Parse(paragraph string) (Section,error){ - p_counter := map[int]bool{} r, _ := regexp.Compile("^#+") section := Section{} for _, line := range strings.Split(strings.TrimRight(paragraph, "\n"), "\n") { nb_hashtag := len(r.FindString(line)) - p_counter[nb_hashtag] = true switch{ case nb_hashtag>0 && line[nb_hashtag] != ' ': return section, errors.New("Err: cannot parse this md line{"+line+"} # should be followed by space") @@ -40,12 +36,12 @@ func Parse(paragraph string) (Section,error){ section.third=line[nb_hashtag+1:] case nb_hashtag == 4: section.fourth=line[nb_hashtag+1:] - case nb_hashtag == 0: - section.description += line + case nb_hashtag == 0 && len(line)>1: + items := strings.Split(line, "\n") + section.description = append(section.description, items...) case nb_hashtag > 4: return section, errors.New("Err: cannot parse this md line{"+line+"}") } } - section.params_nb = len(p_counter) return section, nil } diff --git a/internal/parser/markdown_test.go b/internal/parser/markdown_test.go index ad5b3fd..3596c64 100644 --- a/internal/parser/markdown_test.go +++ b/internal/parser/markdown_test.go @@ -1,7 +1,9 @@ package parser import ( - "testing" + "fmt" + "reflect" + "testing" ) func TestParseHappyPath(t *testing.T) { @@ -10,7 +12,8 @@ func TestParseHappyPath(t *testing.T) { ## Skill ### Date #### Url -Description` +Item +Item2` result, err := Parse(input) if err != nil { t.Fatalf("Unexecpted eroor :%s", err.Error()) @@ -38,8 +41,9 @@ Description` } - description := "Description" - if result.description != description { + description := []string{"Item","Item2"} + if !reflect.DeepEqual(result.description, description){ + fmt.Printf("want: %q, got: %q\n", description, result.description) t.Fatalf("want %s got %s", description, result.description) } } diff --git a/internal/parser/template_sections.go b/internal/parser/template_sections.go new file mode 100644 index 0000000..ae2698b --- /dev/null +++ b/internal/parser/template_sections.go @@ -0,0 +1,34 @@ +package parser + +const pro_item = "\\resumeItem{%ITEM%}\n" + +const prof_template = ` +\resumeSubheading + {1}{2} + {\href{3}{4}}{ } +\resumeItemListStart + %ITEMS% +\resumeItemListEnd +` +const NB_P_PROF = 4 + +const proj_template = ` +\resumeProjectHeading +{\textbf{1} $|$ \emph{2 \href{3}{\faIcon{github}}}}{} +\resumeItemListStart + %ITEMS% +\resumeItemListEnd +` +const NB_P_PROJ = 3 + +const edu_template = ` +\resumeSubheading +{\href{1}{2}}{} +{3}{4} +` +const NB_P_EDU = 4 + +const sk_template = ` +\textbf{1}{: 2} \\ +` +const NB_P_SK = 2