Files
vscode-front-matter/src/helpers/SettingsHelper.ts
T

213 lines
6.3 KiB
TypeScript

import { workspace } from 'vscode';
import * as vscode from 'vscode';
import { TaxonomyType } from '../models';
import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, CONFIG_KEY } from '../constants';
import { Folders } from '../commands/Folders';
import { join, basename } from 'path';
import { existsSync, readFileSync, writeFileSync } from 'fs';
import { Extension } from './Extension';
export class Settings {
private static config: vscode.WorkspaceConfiguration;
private static globalFile = "frontmatter.json";
private static globalConfig: any;
public static init() {
const fmConfig = Settings.projectConfigPath;
if (fmConfig && existsSync(fmConfig)) {
const localConfig = readFileSync(fmConfig, 'utf8');
Settings.globalConfig = JSON.parse(localConfig);
} else {
Settings.globalConfig = undefined;
}
Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
Settings.onConfigChange((global?: any) => {
if (global) {
Settings.globalConfig = Object.assign({}, global);
} else {
Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY);
}
});
}
/**
* Check for config changes on global and local settings
* @param callback
*/
public static onConfigChange(callback: (global?: any) => void) {
workspace.onDidChangeConfiguration(() => {
callback();
});
workspace.onDidSaveTextDocument(async (e) => {
const filename = e.uri.fsPath;
if (Settings.checkProjectConfig(filename)) {
const file = await workspace.openTextDocument(e.uri);
if (file) {
const fileContents = file.getText();
const json = JSON.parse(fileContents);
callback(json);
}
}
});
workspace.onDidDeleteFiles((e) => {
const needCallback = e?.files.find(f => Settings.checkProjectConfig(f.fsPath));
if (needCallback) {
callback();
}
});
}
/**
* Retrieve a setting from global and local config
*/
public static get<T>(name: string, merging: boolean = false): T | undefined{
const configInpection = Settings.config.inspect<T>(name);
let setting = undefined;
const settingKey = `${CONFIG_KEY}.${name}`;
if (Settings.globalConfig && typeof Settings.globalConfig[settingKey] !== "undefined") {
setting = Settings.globalConfig[settingKey];
}
// Local overrides global
if (configInpection && typeof configInpection.workspaceValue !== "undefined") {
if (merging && setting && typeof setting === "object") {
setting = Object.assign([], setting, configInpection.workspaceValue);
} else {
setting = configInpection.workspaceValue;
}
}
if (setting === undefined) {
setting = Settings.config.get(name);
}
return setting;
}
/**
* String update config setting
* @param name
* @param value
*/
public static async update<T>(name: string, value: T, updateGlobal: boolean = false) {
const fmConfig = Settings.projectConfigPath;
if (updateGlobal) {
if (fmConfig && existsSync(fmConfig)) {
const localConfig = readFileSync(fmConfig, 'utf8');
Settings.globalConfig = JSON.parse(localConfig);
Settings.globalConfig[`${CONFIG_KEY}.${name}`] = value;
writeFileSync(fmConfig, JSON.stringify(Settings.globalConfig, null, 2), 'utf8');
return;
}
} else {
await Settings.config.update(name, value);
return;
}
// Fallback to the local settings
await Settings.config.update(name, value);
}
/**
* Create team settings
*/
public static createTeamSettings() {
const wsFolder = Folders.getWorkspaceFolder();
const initialConfig = {
"$schema": `https://${Extension.getInstance().isBetaVersion() ? `beta.` : ``}frontmatter.codes/frontmatter.schema.json`
};
if (wsFolder) {
const configPath = join(wsFolder.fsPath, Settings.globalFile);
if (!existsSync(configPath)) {
writeFileSync(configPath, JSON.stringify(initialConfig, null, 2), 'utf8');
}
}
}
/**
* Return the taxonomy settings
*
* @param type
*/
public static getTaxonomy(type: TaxonomyType): string[] {
// Add all the known options to the selection list
const configSetting = type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES;
const crntOptions = Settings.get(configSetting, true) as string[];
if (crntOptions && crntOptions.length > 0) {
return crntOptions;
}
return [];
}
/**
* Update the taxonomy settings
*
* @param config
* @param type
* @param options
*/
public static async updateTaxonomy(type: TaxonomyType, options: string[]) {
const configSetting = type === TaxonomyType.Tag ? SETTING_TAXONOMY_TAGS : SETTING_TAXONOMY_CATEGORIES;
options = [...new Set(options)];
options = options.sort().filter(o => !!o);
await Settings.update(configSetting, options, true);
}
/**
* Promote settings from local to team level
*/
public static async promote() {
const pkg = Extension.getInstance().packageJson;
if (pkg?.contributes?.configuration?.properties) {
const settingNames = Object.keys(pkg.contributes.configuration.properties);
for (const name of settingNames) {
const setting = Settings.config.inspect(name.replace(`frontMatter.`, ''));
if (setting && typeof setting.workspaceValue !== "undefined") {
await Settings.update(name, setting.workspaceValue, true);
await Settings.update(name.replace(`frontMatter.`, ''), undefined);
}
}
}
}
/**
* Check if its the project config
* @param filePath
* @returns
*/
private static checkProjectConfig(filePath: string) {
const fmConfig = Settings.projectConfigPath;
if (fmConfig && existsSync(fmConfig)) {
return filePath &&
basename(filePath).toLowerCase() === Settings.globalFile.toLowerCase() &&
fmConfig.toLowerCase() === filePath.toLowerCase();
}
return false;
}
/**
* Get the project config path
* @returns
*/
private static get projectConfigPath() {
const wsFolder = Folders.getWorkspaceFolder();
if (wsFolder) {
const fmConfig = join(wsFolder.fsPath, Settings.globalFile);
return fmConfig;
}
return undefined;
}
}