diff --git a/internal/adapters/output/latex_test.go b/internal/adapters/output/latex_test.go index 0374007..173c4a9 100644 --- a/internal/adapters/output/latex_test.go +++ b/internal/adapters/output/latex_test.go @@ -18,6 +18,7 @@ func TestApplySectionToTemplate(t *testing.T) { template := "Start\n%EXPERIENCE_SECTIONS%\nEnd" headers := []string{"Company Name", "Position", "https://company.com", "Company"} items := []string{"Task 1", "Task 2"} + keyword := []string{"1", "2"} want := strings.TrimSpace(`Start %EXPERIENCE_SECTIONS% @@ -25,13 +26,13 @@ func TestApplySectionToTemplate(t *testing.T) { {Company Name}{Position} {\href{https://company.com}{Company}}{ } \resumeItemListStart - \resumeItem{Task 1} - \resumeItem{Task 2} + \resumeItem{Task \textbf{1}} +\resumeItem{Task \textbf{2}} \resumeItemListEnd End`) processor := LatexProccesor{} - got, err := processor.ApplySectionToTemplate(template, headers, items, "Professional") + got, err := processor.ApplySectionToTemplate(template, headers, items, "Professional",keyword) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -44,19 +45,23 @@ End`) template := "Start\n%PROJECTS_SECTIONS%\nEnd" headers := []string{"Project Name", "Project Description", "https://github.com/project"} items := []string{"Feature 1", "Feature 2"} + keyword := []string{"1", "2"} - want := strings.TrimSpace(`Start + want := `Start %PROJECTS_SECTIONS% \resumeProjectHeading {\textbf{Project Name} | \emph{Project Description \href{https://github.com/project}{\faIcon{github}}}}{} \resumeItemListStart - \resumeItem{Feature 1} - \resumeItem{Feature 2} + \resumeItem{Feature \textbf{1}} +\resumeItem{Feature \textbf{2}} + \resumeItemListEnd -End`) + +End` + processor := LatexProccesor{} - got, err := processor.ApplySectionToTemplate(template, headers, items, "Project") + got, err := processor.ApplySectionToTemplate(template, headers, items, "Project",keyword) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -69,9 +74,10 @@ End`) template := "Start\n%EXPERIENCE_SECTIONS%\nEnd" headers := []string{"Company Name", "Position", "https://company.com", "Company"} items := []string{"Task 1", "Task 2"} + keyword := []string{"1", "2"} processor := LatexProccesor{} - _, err := processor.ApplySectionToTemplate(template, headers, items, "UnsupportedSection") + _, err := processor.ApplySectionToTemplate(template, headers, items, "UnsupportedSection",keyword) if err == nil || err.Error() != "Don't know type UnsupportedSection" { t.Errorf("expected error 'Don't know type UnsupportedSection', got %v", err) } @@ -93,7 +99,7 @@ End`) End`) processor := LatexProccesor{} - got, err := processor.ApplySectionToTemplate(template, headers, items, "Project") + got, err := processor.ApplySectionToTemplate(template, headers, items, "Project",nil) if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -121,7 +127,7 @@ func TestReplaceWithSectionTemplate(t *testing.T) { End`) - got := strings.TrimSpace(replaceWithSectionTemplate(template, ProjectTemplate, headers, items)) + got := strings.TrimSpace(replaceWithSectionTemplate(template, ProjectTemplate, headers, items,nil)) if removeWhitespace(got) != removeWhitespace(want) { t.Errorf("replaceWithSectionTemplate happy path failed;\nwant:\n%s\ngot:\n%s", want, got) } @@ -143,7 +149,7 @@ End`) End`) - got := strings.TrimSpace(replaceWithSectionTemplate(template, ProjectTemplate, headers, items)) + got := strings.TrimSpace(replaceWithSectionTemplate(template, ProjectTemplate, headers, items,nil)) if removeWhitespace(got) != removeWhitespace(want) { t.Errorf("replaceWithSectionTemplate happy path failed;\nwant:\n%s\ngot:\n%s", want, got) } @@ -200,9 +206,15 @@ func TestReplaceItems(t *testing.T) { t.Run("happy path - should replace %ITEMS% with formatted items", func(t *testing.T) { template := "Start\n%ITEMS% End" section_items := []string{"Item 1", "Item 2", "Item 3"} - want := "Start\n\\resumeItem{Item 1}\n\\resumeItem{Item 2}\n\\resumeItem{Item 3}\n End" + keyword := []string{"1", "2"} + want := `Start +\resumeItem{Item \textbf{1}} +\resumeItem{Item \textbf{2}} +\resumeItem{Item 3} + End` + - got := replace_items(template, section_items) + got := replace_items(template, section_items,keyword) if got != want { t.Errorf("replace_items happy path failed;\nwant:\n%s\ngot:\n%s", want, got) } @@ -212,8 +224,9 @@ func TestReplaceItems(t *testing.T) { template := "Start\n%ITEMS%Middle\n%ITEMS%\nEnd" section_items := []string{"Single Item"} want := "Start\n\\resumeItem{Single Item}\nMiddle\n%ITEMS%\nEnd" + keyword := []string{"1", "2"} - got := replace_items(template, section_items) + got := replace_items(template, section_items,keyword) if got != want { t.Errorf("replace_items failure case failed;\nwant:\n%s\ngot:\n%s", want, got) } @@ -222,8 +235,9 @@ func TestReplaceItems(t *testing.T) { t.Run("nothing - should rm %ITEMS% if section_items is empty", func(t *testing.T) { template := "Start\n%ITEMS%\nEnd" section_items := []string{} + keyword := []string{"1", "2"} want := "Start\n\nEnd" - got := replace_items(template, section_items) + got := replace_items(template, section_items,keyword) if got != want { t.Errorf("replace_items 'nothing' case failed;\nwant:\n%s\ngot:\n%s", want, got) } diff --git a/internal/adapters/output/latex_writer.go b/internal/adapters/output/latex_writer.go index eb6f5c1..601dae6 100644 --- a/internal/adapters/output/latex_writer.go +++ b/internal/adapters/output/latex_writer.go @@ -3,6 +3,7 @@ package output import ( "anemon/internal/core" "errors" + "log/slog" "fmt" "os" "reflect" @@ -10,6 +11,8 @@ import ( "strings" ) +const NB_REPEAT = 1 + type LatexReader struct{} type LatexProccesor struct{} @@ -42,7 +45,8 @@ func ApplyInfoToTemplate(template string, params core.Params) string { } // Apply a section to a section type on a latex template -func (*LatexProccesor) ApplySectionToTemplate(template string, headers []string, item []string, section string) (string, error) { +func (*LatexProccesor) ApplySectionToTemplate(template string, headers []string, + item []string, section string, keyword []string) (string, error) { if len(section) < 2 { return "", errors.New("Don't know type " + section) } @@ -50,29 +54,29 @@ func (*LatexProccesor) ApplySectionToTemplate(template string, headers []string, switch { case section == "Professional": template = replaceWithSectionTemplate(template, ProfessionalTemplate, - headers, item) + headers, item,keyword) case section == "Project": template = replaceWithSectionTemplate(template, ProjectTemplate, - headers, item) + headers, item,keyword) case section == "Education": template = replaceWithSectionTemplate(template, EducationTemplate, - headers, nil) + headers, nil,nil) case section == "Skill": template = replaceWithSectionTemplate(template, SkillTemplate, - headers, nil) + headers, nil,keyword) default: - fmt.Println("Don't know type " + section) + slog.Warn("Don't know type " + section) return "", errors.New("Don't know type " + section) } return template, nil } // Replace with the template defined in the template_sections.go const -func replaceWithSectionTemplate(template string, SectionTemplate TemplateStruct, headers []string, items []string) string { +func replaceWithSectionTemplate(template string, SectionTemplate TemplateStruct, headers []string, items []string,keywords []string) string { updated_template := strings.Replace(template, SectionTemplate.hook, SectionTemplate.hook+replace_headers(SectionTemplate.template, headers), 1) if items != nil { - updated_template = replace_items(updated_template, items) + updated_template = replace_items(updated_template, items, keywords) } return updated_template } @@ -93,7 +97,9 @@ func replace_headers(sec_template string, replacements []string) string { return sanitize(sec_template) } -func replace_items(template string, section_items []string) string { +//replace the %item% keyword in the template with the item prepared for the CV +func replace_items(template string, o_section_items []string, keywords []string) string { + section_items := emph_keyword(o_section_items,keywords) items := "" for _, item := range section_items { items += strings.Replace(single_item_template, "%ITEM%", item, 1) @@ -103,6 +109,21 @@ func replace_items(template string, section_items []string) string { return sanitize(template) } +//Take a list of items and return them with emphasis on the keyword +func emph_keyword(items []string, keywords []string) []string{ + if keywords == nil{ return items } + + res := make([]string, len(items)) + for i_i,item := range items{ + new_item := item + for _,keyword := range keywords{ + new_item = strings.Replace(new_item, keyword,`\textbf{`+keyword+`}`,NB_REPEAT) + } + res[i_i]=new_item + } + return res +} + // Sanitize the special charactere func sanitize(template string) string { replacements := []struct { diff --git a/internal/core/generate.go b/internal/core/generate.go index b59a71e..6e68617 100644 --- a/internal/core/generate.go +++ b/internal/core/generate.go @@ -105,7 +105,7 @@ func generateCVFrom(cv CV, params Params, root string, items := paragraph.Items sortByScore(items, keywords) cvTemplate, err = processor.ApplySectionToTemplate( - cvTemplate, headers, items, section.Title) + cvTemplate, headers, items, section.Title, keywords) if err != nil { return err } @@ -175,15 +175,6 @@ func getLowestIndex[T any](items []T, keywords []string, getScore func(T, []stri return min_idx } -// Get items of a section and sum they score to get global score of the items -func getScoreSection(section Section, keywords []string) int { - res := 0 - for _, paragraph := range section.Paragraphes { - res += getScoreParagraphe(paragraph, keywords) - } - return res -} - // Get items of a single paragraph and sum they score to get global score of the items func getScoreParagraphe(paragraph Paragraphe, keywords []string) int { res := 0 diff --git a/internal/core/generate_test.go b/internal/core/generate_test.go index dae0a55..6be00dd 100644 --- a/internal/core/generate_test.go +++ b/internal/core/generate_test.go @@ -60,7 +60,7 @@ func (p *MockTemplateProcessor) MakeNewTemplate(path string, template string, na return nil } -func (p *MockTemplateProcessor) ApplySectionToTemplate(template string, headers []string, items []string, section string) (string, error) { +func (p *MockTemplateProcessor) ApplySectionToTemplate(template string, headers []string, items []string, section string, keywords []string) (string, error) { if p.ApplyErr != nil { return "", p.ApplyErr } diff --git a/internal/core/ports.go b/internal/core/ports.go index a22fc96..1d8187a 100644 --- a/internal/core/ports.go +++ b/internal/core/ports.go @@ -27,7 +27,7 @@ type TemplateReader interface { type TemplateProcessor interface { MakeNewTemplate(path string, template string, name string) error - ApplySectionToTemplate(template string, headers []string, item []string, section string) (string, error) + ApplySectionToTemplate(template string, headers []string, item []string, section string, keyword []string) (string, error) } // CV with Language and Sections