Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 26 additions & 17 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,23 @@ import { SubstitutionCompletionProvider } from './substitutionCompletionProvider
import { SubstitutionHoverProvider } from './substitutionHoverProvider';
import { FrontmatterCompletionProvider } from './frontmatterCompletionProvider';
import { FrontmatterValidationProvider } from './frontmatterValidationProvider';
import { SubstitutionValidationProvider } from './substitutionValidationProvider';

import { outputChannel } from './logger';

export function activate(context: vscode.ExtensionContext): void {
// Debug logging
outputChannel.appendLine('Elastic Docs V3 Utilities: Extension activated');
outputChannel.appendLine('Registering completion providers...');

// Apply color customizations programmatically
applyColorCustomizations();

// Test grammar loading
testGrammarLoading();

// Ensure we're working with markdown files and handle potential conflicts

// Note: getLanguages() is async, but we'll proceed without this check
// as the extension should work fine even if markdown support is loaded later

Expand All @@ -53,6 +54,7 @@ export function activate(context: vscode.ExtensionContext): void {
const substitutionHoverProvider = new SubstitutionHoverProvider();
const frontmatterProvider = new FrontmatterCompletionProvider();
const frontmatterValidator = new FrontmatterValidationProvider();
const substitutionValidator = new SubstitutionValidationProvider();

// Register completion providers for markdown files
context.subscriptions.push(
Expand Down Expand Up @@ -111,34 +113,39 @@ export function activate(context: vscode.ExtensionContext): void {
// Register diagnostic providers
const diagnosticCollection = vscode.languages.createDiagnosticCollection('elastic-directives');
const frontmatterDiagnosticCollection = vscode.languages.createDiagnosticCollection('elastic-frontmatter');
const substitutionDiagnosticCollection = vscode.languages.createDiagnosticCollection('elastic-substitution');
context.subscriptions.push(diagnosticCollection);
context.subscriptions.push(frontmatterDiagnosticCollection);

context.subscriptions.push(substitutionDiagnosticCollection);

// Update diagnostics when document changes
const updateDiagnostics = (document: vscode.TextDocument): void => {
if (document.languageId === 'markdown') {
// Directive diagnostics
const diagnostics = diagnosticProvider.provideDiagnostics(document);
diagnosticCollection.set(document.uri, diagnostics);

// Frontmatter diagnostics
const frontmatterDiagnostics = frontmatterValidator.validateDocument(document);
frontmatterDiagnosticCollection.set(document.uri, frontmatterDiagnostics);
// Substitution diagnostics
const substitutionDiagnostics = substitutionValidator.validateDocument(document);
substitutionDiagnosticCollection.set(document.uri, substitutionDiagnostics);
}
};

// Initial diagnostics
if (vscode.window.activeTextEditor) {
updateDiagnostics(vscode.window.activeTextEditor.document);
}

// Listen for document changes
context.subscriptions.push(
vscode.workspace.onDidChangeTextDocument(event => {
updateDiagnostics(event.document);
})
);

// Listen for document opens
context.subscriptions.push(
vscode.workspace.onDidOpenTextDocument(document => {
Expand All @@ -150,9 +157,11 @@ export function activate(context: vscode.ExtensionContext): void {
context.subscriptions.push(
vscode.workspace.onDidSaveTextDocument(document => {
if (document.languageId === 'markdown') {
// Re-run frontmatter validation on save
// Re-run validation on save
const frontmatterDiagnostics = frontmatterValidator.validateDocument(document);
frontmatterDiagnosticCollection.set(document.uri, frontmatterDiagnostics);
const substitutionDiagnostics = substitutionValidator.validateDocument(document);
substitutionDiagnosticCollection.set(document.uri, substitutionDiagnostics);
}
})
);
Expand Down Expand Up @@ -184,13 +193,13 @@ export function activate(context: vscode.ExtensionContext): void {

const position = editor.selection.active;
const line = editor.document.lineAt(position.line);

// Replace the entire line with the template
const range = new vscode.Range(
new vscode.Position(position.line, 0),
new vscode.Position(position.line, line.text.length)
);

editor.edit(editBuilder => {
editBuilder.replace(range, template);
});
Expand All @@ -211,7 +220,7 @@ export function activate(context: vscode.ExtensionContext): void {
function applyColorCustomizations(): void {
const config = vscode.workspace.getConfiguration('editor');
const currentCustomizations = config.get('tokenColorCustomizations') as Record<string, unknown> || {};

// Define our custom color rules
const elasticRules = [
{
Expand Down Expand Up @@ -276,11 +285,11 @@ function applyColorCustomizations(): void {
}
}
];

// Merge with existing rules
const existingRules = (currentCustomizations.textMateRules as unknown[]) || [];
const newRules = [...existingRules, ...elasticRules];

// Apply the customizations
config.update('tokenColorCustomizations', {
...currentCustomizations,
Expand All @@ -294,12 +303,12 @@ function testGrammarLoading(): void {
const activeEditor = vscode.window.activeTextEditor;
if (activeEditor && activeEditor.document.languageId === 'markdown') {
outputChannel.appendLine('Elastic Docs V3: Testing grammar on active markdown file');

// Check if our scopes are being applied
const document = activeEditor.document;
const position = new vscode.Position(0, 0);
const token = document.getWordRangeAtPosition(position);

if (token) {
const tokens = document.getText(token);
outputChannel.appendLine(`Elastic Docs V3: Found tokens at start: ${tokens}`);
Expand Down
16 changes: 5 additions & 11 deletions src/frontmatterSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* under the License.
*/

import { PRODUCTS } from './products';

// Embedded frontmatter schema for Elastic Documentation
export const frontmatterSchema = {
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down Expand Up @@ -175,15 +177,7 @@ export const frontmatterSchema = {
"properties": {
"id": {
"type": "string",
"enum": [
"apm", "apm-agent", "auditbeat", "beats", "cloud-control-ecctl", "cloud-enterprise",
"cloud-hosted", "cloud-kubernetes", "cloud-serverless", "cloud-terraform", "ecs",
"ecs-logging", "edot-cf", "edot-sdk", "edot-collector", "elastic-agent",
"elastic-serverless-forwarder", "elastic-stack", "elasticsearch", "elasticsearch-client",
"filebeat", "fleet", "heartbeat", "integrations", "kibana", "logstash",
"machine-learning", "metricbeat", "observability", "packetbeat", "painless",
"search-ui", "security", "winlogbeat"
],
"enum": Object.keys(PRODUCTS),
"description": "Product identifier. Must match one of the predefined product IDs."
}
},
Expand Down Expand Up @@ -279,7 +273,7 @@ export const frontmatterSchema = {
},
{
"key": "beta",
"alias": "beta",
"alias": "beta",
"description": "Beta release - feature is stable but may have bugs"
},
{
Expand Down Expand Up @@ -324,7 +318,7 @@ export const frontmatterSchema = {
"keys": [
"stack", "deployment", "serverless", "product",
"ece", "eck", "ess", "self",
"elasticsearch", "observability", "security",
"elasticsearch", "observability", "security",
"ecctl", "curator",
"apm_agent_android", "apm_agent_dotnet", "apm_agent_go", "apm_agent_ios", "apm_agent_java", "apm_agent_node", "apm_agent_php", "apm_agent_python", "apm_agent_ruby", "apm_agent_rum",
"edot_ios", "edot_android", "edot_dotnet", "edot_java", "edot_node", "edot_php", "edot_python", "edot_cf_aws", "edot_cf_azure", "edot_collector"
Expand Down
91 changes: 91 additions & 0 deletions src/products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export const PRODUCTS: Record<string, string> = {
'apm': 'APM',
'apm-agent': 'APM Agent',
'apm-agent-dotnet': 'APM .NET Agent',
'apm-agent-go': 'APM Go Agent',
'apm-agent-java': 'APM Java Agent',
'apm-agent-node': 'APM Node.js Agent',
'apm-agent-php': 'APM PHP Agent',
'apm-agent-python': 'APM Python Agent',
'apm-agent-ruby': 'APM Ruby Agent',
'apm-agent-rum-js': 'APM RUM JavaScript Agent',
'apm-k8s-attacher': 'APM Attacher for Kubernetes',
'apm-aws-lambda': 'APM AWS Lambda extension',
'apm-server': 'APM Server',
'auditbeat': 'Auditbeat',
'beats': 'Beats',
'cloud-control-ecctl': 'Elastic Cloud Control',
'cloud-enterprise': 'Elastic Cloud Enterprise',
'cloud-hosted': 'Elastic Cloud Hosted',
'cloud-kubernetes': 'Elastic Cloud on Kubernetes',
'cloud-serverless': 'Elastic Cloud Serverless',
'cloud-terraform': 'Elastic Cloud Terraform Provider',
'curator': 'Elasticsearch Curator',
'ecs': 'Elastic Common Schema (ECS)',
'ecs-logging': 'ECS Logging',
'ecs-dotnet': 'ECS Logging .NET',
'ecs-logging-go-logrus': 'ECS Logging Go (Logrus)',
'ecs-logging-go-zap': 'ECS Logging Go (Zap)',
'ecs-logging-go-zerolog': 'ECS Logging Go (Zerolog)',
'ecs-logging-java': 'ECS Logging Java',
'ecs-logging-nodejs': 'ECS Logging Node.js',
'ecs-logging-php': 'ECS Logging PHP',
'ecs-logging-python': 'ECS Logging Python',
'ecs-logging-ruby': 'ECS Logging Ruby',
'edot-cf': 'EDOT Cloud Forwarder',
'edot-sdk': 'Elastic Distribution of OpenTelemetry SDK',
'edot-collector': 'Elastic Distribution of OpenTelemetry Collector',
'edot-ios': 'Elastic Distribution of OpenTelemetry iOS',
'edot-android': 'Elastic Distribution of OpenTelemetry Android',
'edot-dotnet': 'Elastic Distribution of OpenTelemetry .NET',
'edot-java': 'Elastic Distribution of OpenTelemetry Java',
'edot-node': 'Elastic Distribution of OpenTelemetry Node',
'edot-php': 'Elastic Distribution of OpenTelemetry PHP',
'edot-python': 'Elastic Distribution of OpenTelemetry Python',
'edot-cf-aws': 'EDOT Cloud Forwarder for AWS',
'edot-cf-azure': 'EDOT Cloud Forwarder for Azure',
'eland': 'Eland',
'elastic-agent': 'Elastic Agent',
'elastic-serverless-forwarder': 'Elastic Serverless Forwarder',
'elastic-stack': 'Elastic Stack',
'elasticsearch': 'Elasticsearch',
'elasticsearch-client': 'Elasticsearch Client',
'ess': 'Elastic Cloud Hosted',
'filebeat': 'Filebeat',
'fleet': 'Fleet',
'heartbeat': 'Heartbeat',
'integrations': 'Elastic integrations',
'kibana': 'Kibana',
'logstash': 'Logstash',
'machine-learning': 'Machine Learning',
'metricbeat': 'Metricbeat',
'observability': 'Elastic Observability',
'packetbeat': 'Packetbeat',
'painless': 'Painless',
'search-ui': 'Search UI',
'security': 'Elastic Security',
'self': 'Self-managed Elastic',
'serverless-elasticsearch': 'Elasticsearch Serverless',
'serverless-observability': 'Elastic Observability Serverless',
'serverless-security': 'Elastic Security Serverless',
'winlogbeat': 'Winlogbeat',
}
Loading