feat(tester): add bluemonday

This commit is contained in:
Vyacheslav1557 2025-03-16 21:37:10 +05:00
parent 94fc50e272
commit af6e0b89f6
3 changed files with 117 additions and 84 deletions

View file

@ -7,6 +7,7 @@ import (
"git.sch9.ru/new_gate/ms-tester/internal/models"
"git.sch9.ru/new_gate/ms-tester/internal/tester"
"git.sch9.ru/new_gate/ms-tester/pkg"
"github.com/microcosm-cc/bluemonday"
"strings"
)
@ -41,90 +42,6 @@ func (u *ProblemUseCase) ListProblems(ctx context.Context, page int32, pageSize
return u.problemRepo.ListProblems(ctx, u.problemRepo.DB(), page, pageSize)
}
func isEmpty(p models.ProblemUpdate) bool {
return p.Title == nil &&
p.Legend == nil &&
p.InputFormat == nil &&
p.OutputFormat == nil &&
p.Notes == nil &&
p.Scoring == nil &&
p.MemoryLimit == nil &&
p.TimeLimit == nil
}
const heading = `
\newcommand{\InputFile}{\subsection*{Входные данные}}
\newcommand{\OutputFile}{\subsection*{Выходные данные}}
\newcommand{\Scoring}{\subsection*{Система оценки}}
\newcommand{\Note}{\subsection*{Примечание}}
\newcommand{\Examples}{\subsection*{Примеры}}
`
func wrap(s string) string {
return fmt.Sprintf("%s\n\\begin{document}\n%s\n\\end{document}\n", heading, s)
}
func trimSpaces(statement models.ProblemStatement) models.ProblemStatement {
return models.ProblemStatement{
Legend: strings.TrimSpace(statement.Legend),
InputFormat: strings.TrimSpace(statement.InputFormat),
OutputFormat: strings.TrimSpace(statement.OutputFormat),
Notes: strings.TrimSpace(statement.Notes),
Scoring: strings.TrimSpace(statement.Scoring),
}
}
func build(ctx context.Context, pandocClient pkg.PandocClient, p models.ProblemStatement) (models.Html5ProblemStatement, error) {
p = trimSpaces(p)
latex := models.ProblemStatement{}
if p.Legend != "" {
latex.Legend = wrap(fmt.Sprintf("\\InputFile\n%s\n", p.Legend))
}
if p.InputFormat != "" {
latex.InputFormat = wrap(fmt.Sprintf("\\InputFile\n%s\n", p.InputFormat))
}
if p.OutputFormat != "" {
latex.OutputFormat = wrap(fmt.Sprintf("\\OutputFile\n%s\n", p.OutputFormat))
}
if p.Notes != "" {
latex.Notes = wrap(fmt.Sprintf("\\Note\n%s\n", p.Notes))
}
if p.Scoring != "" {
latex.Scoring = wrap(fmt.Sprintf("\\Scoring\n%s\n", p.Scoring))
}
req := []string{
latex.Legend,
latex.InputFormat,
latex.OutputFormat,
latex.Notes,
latex.Scoring,
}
res, err := pandocClient.BatchConvertLatexToHtml5(ctx, req)
if err != nil {
return models.Html5ProblemStatement{}, err
}
if len(res) != len(req) {
return models.Html5ProblemStatement{}, fmt.Errorf("wrong number of fieilds returned: %d", len(res))
}
return models.Html5ProblemStatement{
LegendHtml: res[0],
InputFormatHtml: res[1],
OutputFormatHtml: res[2],
NotesHtml: res[3],
ScoringHtml: res[4],
}, nil
}
func (u *ProblemUseCase) UpdateProblem(ctx context.Context, id int32, problemUpdate models.ProblemUpdate) error {
if isEmpty(problemUpdate) {
return pkg.Wrap(pkg.ErrBadInput, nil, "UpdateProblem", "empty problem update")
@ -197,3 +114,109 @@ func (u *ProblemUseCase) UpdateProblem(ctx context.Context, id int32, problemUpd
return nil
}
func isEmpty(p models.ProblemUpdate) bool {
return p.Title == nil &&
p.Legend == nil &&
p.InputFormat == nil &&
p.OutputFormat == nil &&
p.Notes == nil &&
p.Scoring == nil &&
p.MemoryLimit == nil &&
p.TimeLimit == nil
}
func wrap(s string) string {
return fmt.Sprintf("\\begin{document}\n%s\n\\end{document}\n", s)
}
func trimSpaces(statement models.ProblemStatement) models.ProblemStatement {
return models.ProblemStatement{
Legend: strings.TrimSpace(statement.Legend),
InputFormat: strings.TrimSpace(statement.InputFormat),
OutputFormat: strings.TrimSpace(statement.OutputFormat),
Notes: strings.TrimSpace(statement.Notes),
Scoring: strings.TrimSpace(statement.Scoring),
}
}
func sanitize(statement models.Html5ProblemStatement) models.Html5ProblemStatement {
p := bluemonday.UGCPolicy()
p.AllowAttrs("class").Globally()
p.AllowAttrs("style").Globally()
p.AllowStyles("text-align").MatchingEnum("center", "left", "right").Globally()
p.AllowStyles("display").MatchingEnum("block", "inline", "inline-block").Globally()
p.AllowStandardURLs()
p.AllowAttrs("cite").OnElements("blockquote", "q")
p.AllowAttrs("href").OnElements("a", "area")
p.AllowAttrs("src").OnElements("img")
if statement.LegendHtml != "" {
statement.LegendHtml = p.Sanitize(statement.LegendHtml)
}
if statement.InputFormatHtml != "" {
statement.InputFormatHtml = p.Sanitize(statement.InputFormatHtml)
}
if statement.OutputFormatHtml != "" {
statement.OutputFormatHtml = p.Sanitize(statement.OutputFormatHtml)
}
if statement.NotesHtml != "" {
statement.NotesHtml = p.Sanitize(statement.NotesHtml)
}
if statement.ScoringHtml != "" {
statement.ScoringHtml = p.Sanitize(statement.ScoringHtml)
}
return statement
}
func build(ctx context.Context, pandocClient pkg.PandocClient, p models.ProblemStatement) (models.Html5ProblemStatement, error) {
p = trimSpaces(p)
latex := models.ProblemStatement{}
if p.Legend != "" {
latex.Legend = wrap(p.Legend)
}
if p.InputFormat != "" {
latex.InputFormat = wrap(p.InputFormat)
}
if p.OutputFormat != "" {
latex.OutputFormat = wrap(p.OutputFormat)
}
if p.Notes != "" {
latex.Notes = wrap(p.Notes)
}
if p.Scoring != "" {
latex.Scoring = wrap(p.Scoring)
}
req := []string{
latex.Legend,
latex.InputFormat,
latex.OutputFormat,
latex.Notes,
latex.Scoring,
}
res, err := pandocClient.BatchConvertLatexToHtml5(ctx, req)
if err != nil {
return models.Html5ProblemStatement{}, err
}
if len(res) != len(req) {
return models.Html5ProblemStatement{}, fmt.Errorf("wrong number of fieilds returned: %d", len(res))
}
sanitizedStatement := sanitize(models.Html5ProblemStatement{
LegendHtml: res[0],
InputFormatHtml: res[1],
OutputFormatHtml: res[2],
NotesHtml: res[3],
ScoringHtml: res[4],
})
return sanitizedStatement, nil
}