Skip to content

Commit

Permalink
Feature yaml editor (#76)
Browse files Browse the repository at this point in the history
* added yaml editor

* name fix

* moved component to one code block

* removed logs

* fix: yaml editor

* fix: reviews

* new line

* fix: merge fix
  • Loading branch information
cr-ruhanmuzaffar authored Aug 16, 2024
1 parent f7722c4 commit fe93192
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 121 deletions.
18 changes: 0 additions & 18 deletions docs/configure-coderabbit.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,6 @@ You can add a `.coderabbit.yaml` configuration file to the root of your
repositories. Below is a sample YAML file that can be used as a starting point
and changed as needed:

```yaml
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
language: "en-US"
early_access: false
reviews:
profile: "chill"
request_changes_workflow: false
high_level_summary: true
poem: true
review_status: true
collapse_walkthrough: false
auto_review:
enabled: true
drafts: false
chat:
auto_reply: true
```
Write your configuration file in the below editor to validate:

```mdx-code-block
Expand Down
103 changes: 0 additions & 103 deletions src/components/YamlEditor/YamlEditor.jsx

This file was deleted.

160 changes: 160 additions & 0 deletions src/components/YamlEditor/YamlEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React, { useState, useEffect } from "react";

import AceEditor from "react-ace";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/ext-language_tools";

import "ace-builds/webpack-resolver";
import "ace-builds/src-noconflict/mode-yaml";

import jsYaml from "js-yaml";

import Ajv from "ajv";
const ajv = new Ajv({ allErrors: true });

import Schema from "../../../static/schema/schema.v2.json";

const validate = ajv.compile(Schema.definitions.schema);
const initialValue = `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
language: "en-US"
early_access: false
reviews:
profile: "chill"
request_changes_workflow: false
high_level_summary: true
poem: true
review_status: true
collapse_walkthrough: false
auto_review:
enabled: true
drafts: false
chat:
auto_reply: true
`;
export default function YamlEditor() {
const [value, setValue] = useState(initialValue);
const [annotations, setAnnotations] = useState([]);

useEffect(() => {
setValue(initialValue);
validateAndSetAnnotations(initialValue);
}, []);

function validateAndSetAnnotations(yaml) {
try {
const doc = jsYaml.load(yaml, { strict: true });
const isValid = validate(doc);

if (!isValid && validate.errors) {
setAnnotations(
validate.errors.map((err) => {
const instancePathArr = err?.instancePath?.split("/");
const key =
instancePathArr && instancePathArr[instancePathArr.length - 1];
return {
row: err.instancePath ? getLineNumber(yaml, err.instancePath) : 0,
column: 0,
text: `${key}: ${err.message} ${
err?.params?.allowedValues
? `Allowed values: ${err.params.allowedValues.join(", ")}`
: ""
}`,
type: "error",
};
})
);
} else {
setAnnotations([]);
}
} catch (err) {
const instancePathArr = err?.instancePath?.split("/");
const key =
instancePathArr && instancePathArr[instancePathArr.length - 1];

setAnnotations([
{
row: err.instancePath ? getLineNumber(yaml, err.instancePath) : 0,
column: 0,
text:
`${key}: ${err.message} ${
err?.params?.allowedValues
? `Allowed values: ${err.params.allowedValues.join(", ")}`
: ""
}` || "YAML parsing error",
type: "error",
},
]);
}
}

function getLineNumber(yaml, instancePath) {
const lines = yaml.split("\n");
const pathParts = instancePath.split("/").filter(Boolean);
let currentObj = jsYaml.load(yaml);
let lineNumber = 0;

const lastPathPart = pathParts[pathParts.length - 1];
const lastPathPartIndex = pathParts.length - 1;

for (let i = 0; i < lines.length; i++) {
if (lines[i].trim().startsWith(pathParts[0] + ":")) {
// Found the top-level field
lineNumber = i;
currentObj = currentObj[pathParts[0]];

for (let j = 1; j < lastPathPartIndex; j++) {
// Go through the nested fields
for (let k = lineNumber + 1; k < lines.length; k++) {
if (lines[k].trim().startsWith(pathParts[j] + ":")) {
lineNumber = k;
currentObj = currentObj[pathParts[j]];
break;
}
}
}

// look for the last path part with array syntax as well as object syntax
for (let l = lineNumber + 1; l < lines.length; l++) {
if (lines[l].trim().startsWith(`- ${lastPathPart}:`)) {
lineNumber = l;
break;
} else if (lines[l].trim().startsWith(lastPathPart + ":")) {
lineNumber = l;
break;
}
}
break;
}
}

return lineNumber;
}

function onChange(newValue) {
setValue(newValue);
validateAndSetAnnotations(newValue);
}

return (
<div className="m4">
<AceEditor
mode="yaml"
theme="github"
onChange={onChange}
value={value}
name="yaml-editor"
editorProps={{ $blockScrolling: true }}
setOptions={{
useWorker: false,
showPrintMargin: false,
showGutter: true,
}}
annotations={annotations}
width="100%"
height="400px"
/>
<br />
</div>
);
}

0 comments on commit fe93192

Please sign in to comment.