Skip to content

Commit 74c25d9

Browse files
authored
Merge pull request #12 from opengrep/fix-inconsitent-ouput-due-to-rule-paths
Fix inconsitent ouput due to rule paths
2 parents b5459c4 + 5f785f2 commit 74c25d9

File tree

9 files changed

+116
-95
lines changed

9 files changed

+116
-95
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "opengrep-playground",
33
"productName": "opengrep-playground",
4-
"version": "1.0.1",
4+
"version": "1.0.2",
55
"description": "Opengrep Playgorund Editor",
66
"main": ".vite/build/main.js",
77
"scripts": {

src/App.vue

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import RuleResults from './components/RuleResults.vue';
4343
import DebugSection from './components/DebugSection.vue';
4444
import RuleEditor from './components/RuleEditor.vue';
4545
import { store } from './store';
46+
import { getLanguage } from './language.mapper';
47+
4648
4749
const getRootDir = inject('$getRootDir');
4850
const getSafeDir = inject('$getSafeDir');
@@ -68,11 +70,11 @@ function handleShowDataFlows(dataFlows) {
6870
6971
async function handleCodeEditorUpdate() {
7072
try {
71-
if (store.ruleEditorCode === '') {
73+
if (store.ruleEditorCode.normalizedRule === '') {
7274
return;
7375
}
7476
75-
const codeSampleFilePath = await joinPath(store.safeDir, "tmp", `untitled_code.${store.languageDetails?.extension ?? 'txt'}`);
77+
const codeSampleFilePath = await joinPath(store.safeDir, "tmp", `untitled_code.${store.languageDetails?.extension}`);
7678
await writeFile(codeSampleFilePath, store.codeEditorCode, { flag: 'w' }); // 'w' flag to create or overwrite the file
7779
store.codeSampleFilePath = codeSampleFilePath;
7880
@@ -85,7 +87,7 @@ async function handleCodeEditorUpdate() {
8587
async function handleRuleEditorUpdate() {
8688
try {
8789
const ruleFilePath = await joinPath(store.safeDir, "tmp", 'untitled_rule.yaml');
88-
await writeFile(ruleFilePath, store.ruleEditorCode, { flag: 'w' }); // 'w' flag to create or overwrite the file
90+
await writeFile(ruleFilePath, store.ruleEditorCode.normalizedRule, { flag: 'w' }); // 'w' flag to create or overwrite the file
8991
store.ruleFilePath = ruleFilePath;
9092
await handleCodeEditorUpdate();
9193
} catch (error) {
@@ -94,14 +96,6 @@ async function handleRuleEditorUpdate() {
9496
}
9597
}
9698
97-
function handleHistoryClick(entry) {
98-
if (entry.editorType === 'code-editor') {
99-
store.codeEditorCode = entry.content;
100-
} else if (entry.editorType === 'rule-editor') {
101-
store.ruleEditorCode = entry.content;
102-
}
103-
}
104-
10599
function startResize(event, columnIndex) {
106100
resizingColumn.value = columnIndex;
107101
startX.value = event.clientX;

src/components/CodeEditor.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const emit = defineEmits(['codeEditorUpdated']);
1313
1414
const MONACO_EDITOR_OPTIONS = {
1515
automaticLayout: true,
16-
formatOnType: true,
17-
formatOnPaste: true,
16+
formatOnType: false,
17+
formatOnPaste: false,
1818
wordBasedSuggestionsOnlySameLanguage: true,
1919
semanticHighlighting: { enabled: 'configuredByTheme' },
2020
readOnly: false,

src/components/RuleEditor.vue

Lines changed: 25 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
</template>
55

66
<script setup>
7-
import { shallowRef, watch, inject } from 'vue';
7+
import { shallowRef, watch } from 'vue';
88
import { VueMonacoEditor } from '@guolao/vue-monaco-editor';
99
import yaml from 'js-yaml';
1010
import { store } from '../store';
11+
import { getLanguage } from '../language.mapper';
1112
1213
const emit = defineEmits(['ruleEditorUpdated']);
1314
const language = 'yaml';
@@ -32,100 +33,51 @@ const MONACO_EDITOR_OPTIONS = {
3233
horizontal: 'hidden'
3334
}
3435
};
35-
const languageMappings = {
36-
js: { ext: "js", monaco: "javascript" },
37-
ts: { ext: "ts", monaco: "typescript" },
38-
javascript: { ext: "js", monaco: "javascript" },
39-
typescript: { ext: "ts", monaco: "typescript" },
40-
python: { ext: "py", monaco: "python" },
41-
go: { ext: "go", monaco: "go" },
42-
java: { ext: "java", monaco: "java" },
43-
c: { ext: "c", monaco: "c" },
44-
cpp: { ext: "cpp", monaco: "cpp" },
45-
php: { ext: "php", monaco: "php" },
46-
ruby: { ext: "rb", monaco: "ruby" },
47-
swift: { ext: "swift", monaco: "swift" },
48-
kotlin: { ext: "kt", monaco: "kotlin" },
49-
rust: { ext: "rs", monaco: "rust" },
50-
csharp: { ext: "cs", monaco: "csharp" },
51-
terraform: { ext: "tf", monaco: "terraform" },
52-
yaml: { ext: "yaml", monaco: "yaml" },
53-
yml: { ext: "yml", monaco: "yaml" },
54-
scala: { ext: "scala", monaco: "scala" },
55-
json: { ext: "json", monaco: "json" },
56-
xml: { ext: "xml", monaco: "xml" },
57-
sql: { ext: "sql", monaco: "sql" },
58-
dockerfile: { ext: "dockerfile", monaco: "dockerfile" },
59-
plaintext: { ext: "txt", monaco: "plaintext" },
60-
dart: { ext: "dart", monaco: "dart" },
61-
elixir: { ext: "ex", monaco: "plaintext" },
62-
jsp: { ext: "jsp", monaco: "jsp" },
63-
html: { ext: "html", monaco: "html" },
64-
css: { ext: "css", monaco: "css" },
65-
scss: { ext: "scss", monaco: "scss" },
66-
less: { ext: "less", monaco: "less" },
67-
bash: { ext: "bash", monaco: "shell" },
68-
apex: { ext: "cls", monaco: "apex" },
69-
closure: { ext: "clj", monaco: "clojure" },
70-
libsonnet: { ext: "jsonnet", monaco: "jsonnet" },
71-
ocaml: { ext: "ml", monaco: "ocaml" },
72-
solidity: { ext: "sol", monaco: "solidity" },
73-
generic: { ext: null, monaco: "plaintext" },
74-
vue: { ext: "vue", monaco: "javascript" },
75-
react: { ext: "jsx", monaco: "javascript" },
76-
angular: { ext: "ts", monaco: "typescript" },
77-
svelte: { ext: "svelte", monaco: "javascript" },
78-
android: { ext: "AndroidManifest.xml", monaco: "xml" },
79-
};
8036
8137
const editorRef = shallowRef();
8238
const handleMount = editor => (editorRef.value = editor);
8339
8440
watch(() => store.ruleEditorCode, (newCode) => {
8541
if (editorRef.value) {
8642
const model = editorRef.value.getModel();
87-
if (model && model.getValue() !== newCode) {
88-
model.setValue(newCode);
43+
if (model && model.getValue() !== newCode.originalRule) {
44+
model.setValue(newCode.normalizedRule);
8945
}
9046
}
9147
});
9248
9349
function handleCodeChange(code) {
94-
store.languageDetails = getLanguageDetails(code);
95-
store.ruleEditorCode = code;
50+
const parsedYamlCode = yaml.load(code);
51+
if (!parsedYamlCode || !parsedYamlCode.rules || parsedYamlCode.rules.length === 0) {
52+
return null;
53+
}
54+
const { paths, ...rest } = parsedYamlCode.rules[0];
55+
56+
store.languageDetails = getLanguageDetails(rest);
57+
58+
store.ruleEditorCode = {
59+
originalRule: code,
60+
normalizedRule: yaml.dump({
61+
...parsedYamlCode,
62+
rules: [{ ...rest }]
63+
})
64+
};
9665
store.disableBinaryRun = !store.languageDetails;
9766
emit('ruleEditorUpdated');
9867
};
9968
10069
function getLanguageDetails(yamlContent) {
101-
const parsedYaml = yaml.load(yamlContent);
102-
103-
if (!parsedYaml || !parsedYaml.rules || parsedYaml.rules.length === 0) {
104-
return null;
105-
}
106-
107-
const languages = parsedYaml.rules ? parsedYaml.rules[0]?.languages : []; // Take the first rule
70+
const languages = yamlContent?.languages
10871
if (!languages || languages.length === 0) {
10972
return null
11073
}
11174
112-
// Get the first supported language
113-
let primaryLanguage = languages.find(lang => languageMappings[lang]);
114-
if (!primaryLanguage) {
115-
return null;
116-
}
117-
if (primaryLanguage === 'xml' && parsedYaml.rules[0].paths.include.some(path => path.includes('AndroidManifest.xml'))) {
118-
primaryLanguage = 'android';
75+
if(languages.length > 1){
76+
return getLanguage('generic');
11977
}
12078
121-
let extension = languageMappings[primaryLanguage].ext;
122-
if (primaryLanguage === 'generic') {
123-
extension = parsedYaml.rules[0].paths.include[0].split('.').pop()
124-
}
125-
126-
return {
127-
extension,
128-
monacoLanguage: languageMappings[primaryLanguage].monaco
129-
};
79+
// Get the first supported language
80+
return getLanguage(languages[0]) ?? getLanguage('generic');
13081
}
82+
13183
</script>

src/components/RuleResults.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
</div>
3232
</div>
3333
<div class="result-footer" v-if="result.extra.dataflow_trace">
34-
<button class="small" @click="handleShowDataFlows(result.extra.dataflow_trace)" style="align-self: center;">Show
34+
<button class="small" @click="handleShowDataFlows(result.extra.dataflow_trace)"
35+
style="align-self: center;">Show
3536
dataflows</button>
3637
</div>
3738
</div>
@@ -41,7 +42,8 @@
4142

4243
<!-- TEST RESULTS -->
4344
<h4 @click="toggleSection('testResults')" style="cursor: pointer;">
44-
Test Results ({{ store.jsonResult?.parsedTestResults.filter(test => test.status === 'SUCCESS').length }}/{{ store.jsonResult?.parsedTestResults.length }} Unit Tests Passed)
45+
Test Results ({{ store.jsonResult?.parsedTestResults.filter(test => test.status === 'SUCCESS').length }}/{{
46+
store.jsonResult?.parsedTestResults.length }} Unit Tests Passed)
4547
</h4>
4648
<div style="flex: 1" class="scrollable-section">
4749
<div v-if="isTestLoading" class="loading-container">
@@ -178,7 +180,7 @@ async function runBinaryForScan(binaryPath, runScanWithoutMatchingExplanations)
178180
179181
function extractScanErrors(jsonOutput) {
180182
return jsonOutput.errrors.forEach(error => {
181-
showErrorDialog(`${error.level}: ${error.type}`, error.message);
183+
showErrorDialog(`${error.level}: ${error.type}`, error.message);
182184
});
183185
}
184186

src/language.mapper.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const languageMappings = {
2+
js: { ext: "js", monaco: "javascript" },
3+
ts: { ext: "ts", monaco: "typescript" },
4+
javascript: { ext: "js", monaco: "javascript" },
5+
typescript: { ext: "ts", monaco: "typescript" },
6+
python: { ext: "py", monaco: "python" },
7+
py: { ext: "py", monaco: "python" },
8+
go: { ext: "go", monaco: "go" },
9+
java: { ext: "java", monaco: "java" },
10+
c: { ext: "c", monaco: "c" },
11+
cpp: { ext: "cpp", monaco: "cpp" },
12+
php: { ext: "php", monaco: "php" },
13+
ruby: { ext: "rb", monaco: "ruby" },
14+
rb: { ext: "rb", monaco: "ruby" },
15+
swift: { ext: "swift", monaco: "swift" },
16+
kotlin: { ext: "kt", monaco: "kotlin" },
17+
kt: { ext: "kt", monaco: "kotlin" },
18+
rust: { ext: "rs", monaco: "rust" },
19+
rs: { ext: "rs", monaco: "rust" },
20+
csharp: { ext: "cs", monaco: "csharp" },
21+
cs: { ext: "cs", monaco: "csharp" },
22+
terraform: { ext: "tf", monaco: "terraform" },
23+
tf: { ext: "tf", monaco: "terraform" },
24+
yaml: { ext: "yaml", monaco: "yaml" },
25+
yml: { ext: "yml", monaco: "yaml" },
26+
scala: { ext: "scala", monaco: "scala" },
27+
json: { ext: "json", monaco: "json" },
28+
xml: { ext: "xml", monaco: "xml" },
29+
sql: { ext: "sql", monaco: "sql" },
30+
dockerfile: { ext: "dockerfile", monaco: "dockerfile" },
31+
plaintext: { ext: "txt", monaco: "plaintext" },
32+
txt: { ext: "txt", monaco: "plaintext" },
33+
dart: { ext: "dart", monaco: "dart" },
34+
elixir: { ext: "ex", monaco: "plaintext" },
35+
ex: { ext: "ex", monaco: "plaintext" },
36+
jsp: { ext: "jsp", monaco: "jsp" },
37+
html: { ext: "html", monaco: "html" },
38+
css: { ext: "css", monaco: "css" },
39+
scss: { ext: "scss", monaco: "scss" },
40+
less: { ext: "less", monaco: "less" },
41+
bash: { ext: "bash", monaco: "shell" },
42+
apex: { ext: "cls", monaco: "apex" },
43+
cls: { ext: "cls", monaco: "apex" },
44+
closure: { ext: "clj", monaco: "clojure" },
45+
clj: { ext: "clj", monaco: "clojure" },
46+
libsonnet: { ext: "jsonnet", monaco: "jsonnet" },
47+
jsonnet: { ext: "jsonnet", monaco: "jsonnet" },
48+
ocaml: { ext: "ml", monaco: "ocaml" },
49+
ml: { ext: "ml", monaco: "ocaml" },
50+
solidity: { ext: "sol", monaco: "solidity" },
51+
sol: { ext: "sol", monaco: "solidity" },
52+
generic: { ext: 'txt', monaco: "plaintext" },
53+
vue: { ext: "vue", monaco: "javascript" },
54+
react: { ext: "jsx", monaco: "javascript" },
55+
jsx: { ext: "jsx", monaco: "javascript" },
56+
angular: { ext: "ts", monaco: "typescript" },
57+
svelte: { ext: "svelte", monaco: "javascript" },
58+
};
59+
60+
export function getLanguage(language) {
61+
const mappedLanguage = languageMappings[language];
62+
63+
if(!mappedLanguage){
64+
return;
65+
}
66+
67+
return {
68+
extension: mappedLanguage.ext,
69+
monacoLanguage: mappedLanguage.monaco
70+
};
71+
}

src/renderer.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ configureMonacoYaml(monaco, {
5858
},
5959
],
6060
});
61-
62-
loader.config({ monaco })
61+
loader.config({ monaco });
6362

6463
app.mount('#app');

src/store.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ export const store = reactive({
1111
languageDetails: null,
1212
ruleFilePath: '',
1313
codeSampleFilePath: '',
14-
ruleEditorCode: '',
14+
ruleEditorCode: {
15+
originalRule: '',
16+
normalizedRule: ''
17+
},
1518
codeEditorCode: '',
1619
codeEditorDebugLocation: null,
1720
mustNotMatchTestCases: [],

0 commit comments

Comments
 (0)