Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/ide/lib/editorconfig/parser.js')
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/parser.js55
1 files changed, 55 insertions, 0 deletions
diff --git a/app/assets/javascripts/ide/lib/editorconfig/parser.js b/app/assets/javascripts/ide/lib/editorconfig/parser.js
new file mode 100644
index 00000000000..a30a8cb868d
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/editorconfig/parser.js
@@ -0,0 +1,55 @@
+import { parseString } from 'editorconfig/src/lib/ini';
+import minimatch from 'minimatch';
+import { getPathParents } from '../../utils';
+
+const dirname = path => path.replace(/\.editorconfig$/, '');
+
+function isRootConfig(config) {
+ return config.some(([pattern, rules]) => !pattern && rules?.root === 'true');
+}
+
+function getRulesForSection(path, [pattern, rules]) {
+ if (!pattern) {
+ return {};
+ }
+ if (minimatch(path, pattern, { matchBase: true })) {
+ return rules;
+ }
+
+ return {};
+}
+
+function getRulesWithConfigs(filePath, configFiles = [], rules = {}) {
+ if (!configFiles.length) return rules;
+
+ const [{ content, path: configPath }, ...nextConfigs] = configFiles;
+ const configDir = dirname(configPath);
+
+ if (!filePath.startsWith(configDir)) return rules;
+
+ const parsed = parseString(content);
+ const isRoot = isRootConfig(parsed);
+ const relativeFilePath = filePath.slice(configDir.length);
+
+ const sectionRules = parsed.reduce(
+ (acc, section) => Object.assign(acc, getRulesForSection(relativeFilePath, section)),
+ {},
+ );
+
+ // prefer existing rules by overwriting to section rules
+ const result = Object.assign(sectionRules, rules);
+
+ return isRoot ? result : getRulesWithConfigs(filePath, nextConfigs, result);
+}
+
+// eslint-disable-next-line import/prefer-default-export
+export function getRulesWithTraversal(filePath, getFileContent) {
+ const editorconfigPaths = [
+ ...getPathParents(filePath).map(x => `${x}/.editorconfig`),
+ '.editorconfig',
+ ];
+
+ return Promise.all(
+ editorconfigPaths.map(path => getFileContent(path).then(content => ({ path, content }))),
+ ).then(results => getRulesWithConfigs(filePath, results.filter(x => x.content)));
+}