commands = new ArrayList<>();
+ String existingCmds = System.getProperty("eclipse.commands", "");
+ for (String line : existingCmds.split("[\\r\\n]+")) {
+ String trimmed = line.trim();
+ if (!trimmed.isEmpty()
+ && !trimmed.equals("-clean")
+ && !trimmed.equals("-clearPersistedState")) {
+ commands.add(trimmed);
+ }
+ }
+ commands.add("-clean");
+ commands.add("-clearPersistedState");
+
+ System.setProperty("eclipse.exitcode", "24"); // 24 = RESTART
+ System.setProperty("eclipse.exitdata", String.join("\n", commands));
+
+ PlatformUI.getWorkbench().restart();
+ }
+}
diff --git a/com.vogella.ide.parallelstart/.classpath b/com.vogella.ide.parallelstart/.classpath
new file mode 100644
index 0000000..5050774
--- /dev/null
+++ b/com.vogella.ide.parallelstart/.classpath
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/com.vogella.ide.parallelstart/.project b/com.vogella.ide.parallelstart/.project
new file mode 100644
index 0000000..d2a5dd4
--- /dev/null
+++ b/com.vogella.ide.parallelstart/.project
@@ -0,0 +1,39 @@
+
+
+ com.vogella.ide.parallelstart
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.eclipse.pde.ds.core.builder
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/com.vogella.ide.parallelstart/.settings/org.eclipse.jdt.core.prefs b/com.vogella.ide.parallelstart/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..c540a97
--- /dev/null
+++ b/com.vogella.ide.parallelstart/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=25
+org.eclipse.jdt.core.compiler.compliance=25
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=25
diff --git a/com.vogella.ide.parallelstart/META-INF/MANIFEST.MF b/com.vogella.ide.parallelstart/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..50202b1
--- /dev/null
+++ b/com.vogella.ide.parallelstart/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Parallel Startup Configurator
+Bundle-SymbolicName: com.vogella.ide.parallelstart
+Bundle-Version: 1.0.0.qualifier
+Bundle-Vendor: VOGELLA
+Bundle-RequiredExecutionEnvironment: JavaSE-25
+Automatic-Module-Name: com.vogella.ide.parallelstart
+Import-Package: org.eclipse.osgi.container;version="1.0.0",
+ org.osgi.framework;version="1.10.0"
+Service-Component: OSGI-INF/com.vogella.ide.parallelstart.ParallelStartConfigurator.xml
+Bundle-ActivationPolicy: lazy
diff --git a/com.vogella.ide.parallelstart/OSGI-INF/com.vogella.ide.parallelstart.ParallelStartConfigurator.xml b/com.vogella.ide.parallelstart/OSGI-INF/com.vogella.ide.parallelstart.ParallelStartConfigurator.xml
new file mode 100644
index 0000000..1d13a7f
--- /dev/null
+++ b/com.vogella.ide.parallelstart/OSGI-INF/com.vogella.ide.parallelstart.ParallelStartConfigurator.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/com.vogella.ide.parallelstart/README.md b/com.vogella.ide.parallelstart/README.md
new file mode 100644
index 0000000..963863f
--- /dev/null
+++ b/com.vogella.ide.parallelstart/README.md
@@ -0,0 +1,36 @@
+# Parallel Startup Configurator
+
+Marks Eclipse platform bundles as safe for parallel activation during startup using the Equinox `Module.setParallelActivation(true)` API.
+
+## Required Framework Configuration
+
+Add to your `config.ini` or launch arguments:
+
+```
+equinox.start.level.thread.count=0
+equinox.start.level.restrict.parallel=true
+```
+
+- `equinox.start.level.thread.count` — number of threads for bundle activation. `0` means auto-detect based on available processors. Default is `1` (sequential).
+- `equinox.start.level.restrict.parallel` — when `true`, only bundles explicitly marked via `setParallelActivation(true)` are activated in parallel. When `false` (default), all bundles within a start level activate in parallel.
+
+## How It Works
+
+Equinox processes start levels sequentially (level 1 completes before level 2 begins). Within each start level, bundles are grouped:
+
+1. Lazy parallel bundles (started concurrently)
+2. Lazy sequential bundles (started one by one)
+3. Eager parallel bundles (started concurrently)
+4. Eager sequential bundles (started one by one)
+
+Each group completes before the next begins. The parallel activation flag is persisted in the framework's module database, so it only needs to be set once.
+
+## Limitations
+
+This plug-in uses an OSGi DS immediate component. DS itself must be activated before this component runs, so the parallel flags are not effective on the first cold start. All subsequent launches benefit from the persisted settings.
+
+For first-launch effectiveness, use a `BundleActivator` at start level 1 instead of DS.
+
+## Bundle Safety
+
+A bundle is safe for parallel activation if its activator is thread-safe and does not depend on side effects from other bundles' activators within the same start level. Standard OSGi service dependencies (via DS) are safe since service lookup is decoupled from activation order.
diff --git a/com.vogella.ide.parallelstart/build.properties b/com.vogella.ide.parallelstart/build.properties
new file mode 100644
index 0000000..c58ea21
--- /dev/null
+++ b/com.vogella.ide.parallelstart/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ OSGI-INF/
diff --git a/com.vogella.ide.parallelstart/src/com/vogella/ide/parallelstart/ParallelStartConfigurator.java b/com.vogella.ide.parallelstart/src/com/vogella/ide/parallelstart/ParallelStartConfigurator.java
new file mode 100644
index 0000000..28b7c9b
--- /dev/null
+++ b/com.vogella.ide.parallelstart/src/com/vogella/ide/parallelstart/ParallelStartConfigurator.java
@@ -0,0 +1,140 @@
+package com.vogella.ide.parallelstart;
+
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.eclipse.osgi.container.Module;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Configures Eclipse platform bundles for parallel activation during startup.
+ *
+ *
+ * By default, Equinox activates bundles sequentially within each start level.
+ * When the framework properties {@code equinox.start.level.thread.count} and
+ * {@code equinox.start.level.restrict.parallel=true} are set, only bundles
+ * explicitly marked via {@link Module#setParallelActivation(boolean)} are
+ * activated in parallel.
+ *
+ *
+ *
+ * This component marks well-known Eclipse platform bundles as safe for parallel
+ * activation. The setting is persisted by the framework, so it only needs to
+ * take effect once. On subsequent launches the flags are already stored in the
+ * module database.
+ *
+ *
+ *
+ * Required framework configuration (e.g. in config.ini or launch args):
+ *
+ *
+ *
+ * equinox.start.level.thread.count=0
+ * equinox.start.level.restrict.parallel=true
+ *
+ */
+@Component(immediate = true)
+public class ParallelStartConfigurator {
+
+ private static final Logger LOG = Logger.getLogger(ParallelStartConfigurator.class.getName());
+
+ /**
+ * Eclipse platform bundles considered safe for parallel activation. These
+ * bundles have thread-safe activators or use lazy/DS activation and do not
+ * depend on a specific activation order beyond what OSGi services guarantee.
+ */
+ private static final Set PARALLEL_SAFE_BUNDLES = Set.of(
+ // Eclipse core runtime
+ "org.eclipse.core.runtime",
+ "org.eclipse.core.commands",
+ "org.eclipse.core.contenttype",
+ "org.eclipse.core.databinding",
+ "org.eclipse.core.databinding.beans",
+ "org.eclipse.core.databinding.observable",
+ "org.eclipse.core.databinding.property",
+ "org.eclipse.core.expressions",
+ "org.eclipse.core.filesystem",
+ "org.eclipse.core.jobs",
+ "org.eclipse.core.resources",
+ "org.eclipse.core.net",
+
+ // Equinox
+ "org.eclipse.equinox.common",
+ "org.eclipse.equinox.preferences",
+ "org.eclipse.equinox.registry",
+ "org.eclipse.equinox.app",
+ "org.eclipse.equinox.event",
+
+ // E4 platform
+ "org.eclipse.e4.core.commands",
+ "org.eclipse.e4.core.contexts",
+ "org.eclipse.e4.core.di",
+ "org.eclipse.e4.core.di.annotations",
+ "org.eclipse.e4.core.di.extensions",
+ "org.eclipse.e4.core.di.extensions.supplier",
+ "org.eclipse.e4.core.services",
+ "org.eclipse.e4.ui.bindings",
+ "org.eclipse.e4.ui.css.core",
+ "org.eclipse.e4.ui.css.swt",
+ "org.eclipse.e4.ui.css.swt.theme",
+ "org.eclipse.e4.ui.di",
+ "org.eclipse.e4.ui.model.workbench",
+ "org.eclipse.e4.ui.services",
+ "org.eclipse.e4.ui.workbench",
+ "org.eclipse.e4.ui.workbench.addons.swt",
+ "org.eclipse.e4.ui.workbench.renderers.swt",
+ "org.eclipse.e4.ui.workbench.swt",
+ "org.eclipse.e4.ui.workbench3",
+ "org.eclipse.e4.emf.xpath",
+
+ // UI and JFace
+ "org.eclipse.jface",
+ "org.eclipse.jface.databinding",
+ "org.eclipse.jface.text",
+ "org.eclipse.ui",
+ "org.eclipse.ui.forms",
+ "org.eclipse.ui.navigator",
+ "org.eclipse.ui.views",
+ "org.eclipse.ui.workbench",
+ "org.eclipse.ui.ide",
+
+ // Text and editors
+ "org.eclipse.text",
+ "org.eclipse.ui.editors",
+ "org.eclipse.ui.genericeditor",
+ "org.eclipse.ui.workbench.texteditor",
+
+ // Help
+ "org.eclipse.help",
+ "org.eclipse.help.base",
+ "org.eclipse.help.ui",
+
+ // EMF (commonly used, thread-safe activators)
+ "org.eclipse.emf.common",
+ "org.eclipse.emf.ecore",
+ "org.eclipse.emf.ecore.xmi",
+
+ // Third-party libraries (typically stateless)
+ "org.eclipse.equinox.bidi",
+ "com.ibm.icu"
+ );
+
+ @Activate
+ void activate(BundleContext context) {
+ int count = 0;
+ for (Bundle bundle : context.getBundles()) {
+ String bsn = bundle.getSymbolicName();
+ if (bsn != null && PARALLEL_SAFE_BUNDLES.contains(bsn)) {
+ Module module = bundle.adapt(Module.class);
+ if (module != null && !module.isParallelActivated()) {
+ module.setParallelActivation(true);
+ count++;
+ }
+ }
+ }
+ LOG.info("Marked " + count + " bundles for parallel activation");
+ }
+}
diff --git a/com.vogella.lsp.asciidoc.server.tests/manual/Help.adoc b/com.vogella.lsp.asciidoc.server.tests/manual/Help.adoc
index a6889f0..f8c9330 100644
--- a/com.vogella.lsp.asciidoc.server.tests/manual/Help.adoc
+++ b/com.vogella.lsp.asciidoc.server.tests/manual/Help.adoc
@@ -3,10 +3,6 @@ ddd
image::Sample.png[]
include::Help2.adoc[]
-include::Testing.adoc[]]
-include::[]
+include::Testing.adoc[]
-include::
-
-image::Sample.png[]
-image::Test.png[]
\ No newline at end of file
+image::Test.png[]
diff --git a/com.vogella.lsp.asciidoc.server.tests/manual/Testing.adoc b/com.vogella.lsp.asciidoc.server.tests/manual/Testing.adoc
index 630b30a..2e4208b 100644
--- a/com.vogella.lsp.asciidoc.server.tests/manual/Testing.adoc
+++ b/com.vogella.lsp.asciidoc.server.tests/manual/Testing.adoc
@@ -1,5 +1,5 @@
= Title
-image::[]
+image::Sample.png[]
-linclude::[]
\ No newline at end of file
+include::Help.adoc[]
diff --git a/com.vogella.lsp.asciidoc.server/src/com/vogella/lsp/asciidoc/server/AsciidocTextDocumentService.java b/com.vogella.lsp.asciidoc.server/src/com/vogella/lsp/asciidoc/server/AsciidocTextDocumentService.java
index cb78060..ae75ad1 100644
--- a/com.vogella.lsp.asciidoc.server/src/com/vogella/lsp/asciidoc/server/AsciidocTextDocumentService.java
+++ b/com.vogella.lsp.asciidoc.server/src/com/vogella/lsp/asciidoc/server/AsciidocTextDocumentService.java
@@ -321,7 +321,7 @@ private void collectLinks(String baseUri, String lineContent, int lineIndex, Lis
if (path.startsWith("http://") || path.startsWith("https://")) {
// External link - use URL directly
targetUri = path;
- } else if (path.startsWith("./") || path.startsWith("../")) {
+ } else {
// Internal file link - resolve relative path
Location loc = resolveFileLocation(baseUri, path);
if (loc != null) {
diff --git a/icon-replacement-plugin.md b/icon-replacement-plugin.md
new file mode 100644
index 0000000..5715a92
--- /dev/null
+++ b/icon-replacement-plugin.md
@@ -0,0 +1,233 @@
+# Icon Replacement Plugin Implementation
+
+## Overview
+
+This plugin replaces icons in the running Eclipse installation by patching existing
+bundles using `Bundle.update(InputStream)` — no file locking issues since content
+is streamed directly into Equinox's internal bundle cache. After patching, the IDE
+restarts with `-clean -clearPersistedState` to apply changes.
+
+Icon packs are contributed via an extension point, pointing to an
+[`icon-mapping.json`](https://github.com/eclipse-platform/ui-best-practices/blob/main/iconpacks/eclipse-dual-tone/icon-mapping.json)
+file and a folder of replacement SVG files.
+
+The mapping format is:
+
+```json
+{
+ "terminal.svg": [
+ "org.eclipse.ui.console/icons/full/eview/console_view.svg"
+ ]
+}
+```
+
+Each key is a filename in the icon pack folder; each value is an array of
+`bundleSymbolicName/path` pairs to replace.
+
+A similar (workspace-based) approach exists in `com.vogella.ide.icons.dualtone`.
+
+---
+
+## 1. Extension Point (`com.vogella.ide.iconreplacer`)
+
+Define `schema/iconpack.exsd`:
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+`plugin.xml` registration:
+
+```xml
+
+```
+
+Consumers contribute like this:
+
+```xml
+
+
+
+```
+
+---
+
+## 2. Plugin Structure
+
+```
+com.vogella.ide.iconreplacer/
+ META-INF/MANIFEST.MF
+ plugin.xml
+ schema/iconpack.exsd
+ src/com/vogella/ide/iconreplacer/
+ IconReplacerHandler.java ← e4 handler, triggered by a command/menu entry
+ BundlePatcher.java ← patches a single bundle JAR
+ RestartHelper.java ← restarts with -clean -clearPersistedState
+```
+
+**`MANIFEST.MF`** — key dependencies:
+
+```
+Require-Bundle:
+ org.eclipse.core.runtime,
+ org.eclipse.ui,
+ org.eclipse.equinox.app,
+ com.google.gson
+```
+
+---
+
+## 3. Reading Extension Point Contributions
+
+```java
+IExtensionRegistry registry = Platform.getExtensionRegistry();
+IConfigurationElement[] elements =
+ registry.getConfigurationElementsFor("com.vogella.ide.iconreplacer.iconpack");
+
+for (IConfigurationElement element : elements) {
+ Bundle contributor = Platform.getBundle(element.getContributor().getName());
+ String mappingFile = element.getAttribute("mappingFile");
+ String iconFolder = element.getAttribute("iconFolder");
+
+ URL mappingUrl = contributor.getEntry(mappingFile);
+ URL iconFolderUrl = contributor.getEntry(iconFolder);
+ // ... parse and apply
+}
+```
+
+---
+
+## 4. Parsing the Mapping and Patching Bundles
+
+**`BundlePatcher.java`**
+
+```java
+// Parse icon-mapping.json with Gson
+Type type = new TypeToken