Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix EOL handling in web editor #27141

Merged
merged 16 commits into from
Sep 24, 2023
2 changes: 1 addition & 1 deletion routers/web/repo/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
Operation: operation,
FromTreePath: ctx.Repo.TreePath,
TreePath: form.TreePath,
ContentReader: strings.NewReader(strings.ReplaceAll(form.Content, "\r", "")),
ContentReader: strings.NewReader(form.Content),
},
},
Signoff: form.Signoff,
Expand Down
7 changes: 4 additions & 3 deletions templates/repo/editor/edit.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
{{end}}
</div>
<div class="ui bottom attached active tab segment" data-tab="write">
<textarea id="edit_area" name="content" class="gt-hidden" data-id="repo-{{.Repository.Name}}-{{.TreePath}}"
<textarea id="edit_area" name="content" class="gt-hidden"
data-id="repo-{{.Repository.Name}}-{{.TreePath}}"
data-url="{{.Repository.Link}}/markup"
data-context="{{.RepoLink}}"
data-previewable-extensions="{{.PreviewableExtensions}}"
data-line-wrap-extensions="{{.LineWrapExtensions}}">
{{.FileContent}}</textarea>
data-line-wrap-extensions="{{.LineWrapExtensions}}"
data-initial-value="{{JsonUtils.EncodeToString .FileContent}}"></textarea>
<div class="editor-loading is-loading"></div>
</div>
<div class="ui bottom attached tab segment markup" data-tab="preview">
Expand Down
19 changes: 17 additions & 2 deletions web_src/js/features/codeeditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export async function createMonaco(textarea, filename, editorOpts) {
const monaco = await import(/* webpackChunkName: "monaco" */'monaco-editor');

initLanguages(monaco);
let {language, ...other} = editorOpts;
let {language, eol, ...other} = editorOpts;
if (!language) language = getLanguage(filename);

const container = document.createElement('div');
Expand Down Expand Up @@ -105,14 +105,28 @@ export async function createMonaco(textarea, filename, editorOpts) {
monaco.languages.register({id: 'vs.editor.nullLanguage'});
monaco.languages.setLanguageConfiguration('vs.editor.nullLanguage', {});

// We encode the initial value in JSON on the backend to prevent browsers from
// discarding the \r during HTML parsing:
// https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream
const value = JSON.parse(textarea.getAttribute('data-initial-value') || '""');
textarea.value = value;
textarea.removeAttribute('data-initial-value');

const editor = monaco.editor.create(container, {
value: textarea.value,
value,
theme: 'gitea',
language,
...other,
});

const model = editor.getModel();

// Monaco performs auto-detection of dominant EOL in the file, biased towards LF for
// empty files. If there is an editorconfig value, override this detected value.
if (eol in monaco.editor.EndOfLineSequence) {
model.setEOL(monaco.editor.EndOfLineSequence[eol]);
}

model.onDidChangeContent(() => {
textarea.value = editor.getValue();
textarea.dispatchEvent(new Event('change')); // seems to be needed for jquery-are-you-sure
Expand Down Expand Up @@ -187,5 +201,6 @@ function getEditorConfigOptions(ec) {
opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true;
opts.insertSpaces = ec.indent_style === 'space';
opts.useTabStops = ec.indent_style === 'tab';
opts.eol = ec.end_of_line?.toUpperCase();
return opts;
}