From 4c3f4934168c33ca17df63427fe8fa7466c1388d Mon Sep 17 00:00:00 2001 From: Ghazi Date: Mon, 13 Jul 2026 11:36:40 +0530 Subject: [PATCH 1/5] fix(#175 #177): conditional base tag + consumer-scoped retry load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three changes that close issues #175, #177, and the pwa/math auto-install regression reported on the 0.8.13 branch: 1. Conditional in layout templates - Offline mode: NO tag (fixes #177 — file:// resolution re-roots to filesystem root when is present) - Online mode at root: NO tag (relies on relativePathToRoot + ./assets/... for resolution, fixes #175 — no manual base config needed for GH Pages project sites) - Online mode at subpath or workspace sub-site: keep (preserves the no-trailing-slash fix from 0.8.10) - Applied to both packages/ui/templates/layout.ejs and packages/templates/summer/templates/layout.ejs 2. Consumer-scoped retry import in tryLoadAfterInstall - Previous bare import(name) walked up from the calling module's location, finding the monorepo's stale workspace copy of the just-installed package instead of the consumer's copy - Now uses createRequire(consumerCwd) to resolve the entry point in the consumer's node_modules, then imports via file:// URL - Fixes pwa/math/threads auto-install: install succeeded but import failed because Node found the monorepo's version 3. Asset-base-URL test additions - URL-1f: GH Pages subpath () - URL-1g: --offline mode (no tag at all) - Updated URL-1c/1d for the new conditional behavior Note: URL-1c/1d/1g assertions check the auto-installed template dist which currently resolves to the published 0.8.12 npm version. These assertions will pass once this fix is released as 0.8.13. --- package.json | 2 + packages/api/registry/plugins.generated.json | 2 +- packages/api/src/hooks.ts | 78 +- packages/api/src/runtime-deps.ts | 24 +- .../templates/summer/templates/layout.ejs | 4 +- packages/ui/templates/layout.ejs | 2 + tests/cli-contracts/asset-base-url.test.js | 60 +- tools/simulate-consumer.mjs | 686 ++++++++++++++++++ 8 files changed, 824 insertions(+), 34 deletions(-) create mode 100644 tools/simulate-consumer.mjs diff --git a/package.json b/package.json index f5ece4b7..44ec9d33 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "docmd-live": "node packages/live/bin/docmd-live.js --cwd packages/_playground", "prep": "node tools/prep.js", "verify": "node tools/verify.js", + "simulate": "echo 'Run from a consumer project: cd ../docs && npm run sim' && exit 1", + "simulate:local": "echo 'Run from a consumer project: cd ../docs && npm run sim' && exit 1", "lint": "eslint .", "bump": "node tools/bump.js", "docker:build": "docker build -t docmd:latest -f docker/Dockerfile .", diff --git a/packages/api/registry/plugins.generated.json b/packages/api/registry/plugins.generated.json index c618eab0..3fd948be 100644 --- a/packages/api/registry/plugins.generated.json +++ b/packages/api/registry/plugins.generated.json @@ -1,6 +1,6 @@ { "$meta": { - "generatedAt": "2026-07-12T12:23:44.202Z", + "generatedAt": "2026-07-13T06:05:40.151Z", "generator": "scripts/build-plugin-registry.mjs", "packageCount": 15 }, diff --git a/packages/api/src/hooks.ts b/packages/api/src/hooks.ts index ca4eebc4..a0e14612 100644 --- a/packages/api/src/hooks.ts +++ b/packages/api/src/hooks.ts @@ -327,27 +327,60 @@ export function resolveTemplateName(key: string): string { // --------------------------------------------------------------------------- // // The registry loader, package-manager detector, version pinner, and -// `spawn`-based installer live in `./runtime-deps.ts`. This module -// replaces the previous inline `execSync(\`pnpm add ${pkg}\`)` which -// was a CWE-78 (shell injection) surface. The shared module is also -// consumed by `engine.ts` for engine auto-install. +// `spawn`-based installer live in `./runtime-deps.ts`. We import them +// here and wrap `installRuntimeDep` with the project's warn-once +// deduper so a dev-server rebuild can't flood the TUI. // --------------------------------------------------------------------------- // Load & Register // --------------------------------------------------------------------------- export async function loadPlugins(config: any, opts?: { resolvePaths?: string[] }): Promise { - // 1. Resolution paths for plugin imports - the caller (e.g. @docmd/core) should - // pass its own __dirname so plugins that are core's dependencies can be found - // even under pnpm's strict node_modules layout. - const resolvePaths = [ - process.cwd(), - __dirname, - __monorepoRoot, - path.join(__monorepoRoot, 'packages/plugins'), - path.join(__monorepoRoot, 'packages/templates'), - ...(opts?.resolvePaths || []) - ]; + // The monorepo dev fallback (loading plugins/templates from + // packages/plugins or packages/templates in the monorepo source) + // should ONLY fire when the process is running from inside the + // monorepo itself. When an external project runs the monorepo's + // dist binary (e.g. docs/ running `node ../docmd/packages/core/ + // dist/bin/docmd.js dev`), the monorepo root is resolvable but the + // external project's node_modules is the right place to look. + // Without this gate, a template like @docmd/template-summer is found + // in the monorepo source, loaded directly, and auto-install never + // fires — so the package never lands in the user's package.json or + // node_modules. (Search plugin already scopes itself to + // process.cwd()/node_modules; this applies the same principle to + // the generic plugin/template loader.) + const isMonorepoContext = process.cwd().startsWith(__monorepoRoot + path.sep) || process.cwd() === __monorepoRoot; + + // 1. Resolution paths for plugin imports. + // + // When running INSIDE the monorepo (dev/test), we include __dirname + // and the monorepo package dirs so workspace packages resolve during + // development. + // + // When running OUTSIDE the monorepo (an external consumer project like + // docs/ running `dev:local`), we deliberately EXCLUDE __dirname. Why: + // __dirname inside the monorepo binary points to docmd/packages/api/dist/, + // and Node walks up from there to docmd/node_modules/ where EVERY workspace + // package is symlinked. That means template-summer, math, pwa — packages + // the consumer never installed — resolve silently from the monorepo. The + // consumer never sees the auto-install path fire, the package never lands + // in their package.json, and CI/production breaks. Restricting to + // process.cwd() means core plugins (deps of @docmd/core) resolve from the + // consumer's own node_modules, and optional plugins trigger auto-install. + const resolvePaths = isMonorepoContext + ? [ + process.cwd(), + __dirname, + __monorepoRoot, + path.join(__monorepoRoot, 'packages/plugins'), + path.join(__monorepoRoot, 'packages/templates'), + ...(opts?.resolvePaths || []), + ] + : [ + process.cwd(), + path.join(process.cwd(), 'node_modules'), + ...(opts?.resolvePaths || []), + ]; // 1. Reset hooks hooks.markdownSetup = []; @@ -436,14 +469,17 @@ export async function loadPlugins(config: any, opts?: { resolvePaths?: string[] // 1. Monorepo Priority: if it's an official plugin OR template, try local // monorepo source first. This prevents older versions installed in project // node_modules from taking precedence during monorepo development. - if (name.startsWith('@docmd/plugin-')) { + // Gated on isMonorepoContext so external projects running the monorepo + // binary (e.g. via `node ../docmd/.../docmd.js`) don't accidentally load + // from the monorepo source and bypass auto-install. + if (isMonorepoContext && name.startsWith('@docmd/plugin-')) { const id = name.replace('@docmd/plugin-', ''); const localPath = path.resolve(__monorepoRoot, 'packages/plugins', id, 'dist/index.js'); if (nativeFs.existsSync(localPath)) { rawModule = await import(pathToFileURL(localPath).href); loadedFromMonorepo = true; } - } else if (name.startsWith('@docmd/template-')) { + } else if (isMonorepoContext && name.startsWith('@docmd/template-')) { // Templates live under packages/templates// in the monorepo. const id = name.replace('@docmd/template-', ''); const localPath = path.resolve(__monorepoRoot, 'packages/templates', id, 'dist/index.js'); @@ -521,10 +557,10 @@ export async function loadPlugins(config: any, opts?: { resolvePaths?: string[] warnOnce(`registry:${name}`, TUI.yellow(`Plugin "${shortNameLocal ?? name}" not in official registry`)); continue; } - // Retry loading after install. We use dynamic `import()` (not - // `require.resolve` + file:// import) so packages that declare - // `exports` with only an `import` condition are still resolvable. - const reloaded = await tryLoadAfterInstall(name); + // Retry loading after install, scoped to the consumer's + // node_modules (not the monorepo's, which is what bare + // `import(name)` would walk into). + const reloaded = await tryLoadAfterInstall(name, process.cwd()); if (!reloaded) { warnOnce( `autoinstall:${name}`, diff --git a/packages/api/src/runtime-deps.ts b/packages/api/src/runtime-deps.ts index e1dab2d4..eaae08a4 100644 --- a/packages/api/src/runtime-deps.ts +++ b/packages/api/src/runtime-deps.ts @@ -44,7 +44,7 @@ import path from 'node:path'; import nativeFs from 'node:fs'; import { createRequire } from 'node:module'; -import { fileURLToPath } from 'node:url'; +import { fileURLToPath, pathToFileURL } from 'node:url'; import process from 'node:process'; import { spawn } from 'node:child_process'; import { TUI } from '@docmd/tui'; @@ -349,14 +349,24 @@ export function shortKey(packageName: string): string | null { } /** - * Re-load `pkg` after an install attempt. Returns the module reference - * or null when the import still fails. We use dynamic `import(pkgName)` - * (not file:// resolution) so `exports` with only the `import` - * condition still resolves on modern Node. + * Re-load `pkg` after an install attempt. Resolves the entry point via + * `createRequire(consumerCwd)` so the resolution is rooted in the + * consumer's directory, then imports via file URL. This is critical: + * a bare `import(pkgName)` uses Node's default resolution which walks + * up from the calling module's location — when this code runs from + * the docmd monorepo, that walk would find a stale workspace copy of + * the package instead of the one we just installed for the consumer. + * + * Returns the module reference or null on failure. */ -export async function tryLoadAfterInstall(packageName: string): Promise { +export async function tryLoadAfterInstall( + packageName: string, + consumerCwd: string = process.cwd(), +): Promise { try { - return await import(packageName); + const consumerRequire = createRequire(consumerCwd + '/'); + const entry = consumerRequire.resolve(packageName); + return await import(pathToFileURL(entry).href); } catch { return null; } diff --git a/packages/templates/summer/templates/layout.ejs b/packages/templates/summer/templates/layout.ejs index 0c92d4ed..489a938d 100644 --- a/packages/templates/summer/templates/layout.ejs +++ b/packages/templates/summer/templates/layout.ejs @@ -32,7 +32,9 @@ <%= pageTitle %><% if (siteTitle && pageTitle !== siteTitle) { %> · <%= siteTitle %><% } %> - + <% if (!locals.isOfflineMode && siteRootAbs && siteRootAbs !== '/') { %> + + <% } %> diff --git a/packages/ui/templates/layout.ejs b/packages/ui/templates/layout.ejs index 31ea1949..4ab487d1 100644 --- a/packages/ui/templates/layout.ejs +++ b/packages/ui/templates/layout.ejs @@ -46,7 +46,9 @@ <%= pageTitle %><% if (siteTitle && pageTitle !== siteTitle && !(frontmatter && frontmatter.titleAppend === false)) { %> : <%= siteTitle %><% } %> + <% if (!locals.isOfflineMode && siteRootAbs && siteRootAbs !== '/') { %> + <% } %> <%- faviconLinkHtml || '' %> <% if (config.theme?.codeHighlight !==false) { const isDarkDefault=appearance==='dark' ; %> diff --git a/tests/cli-contracts/asset-base-url.test.js b/tests/cli-contracts/asset-base-url.test.js index 4c84511f..72c3ad1c 100644 --- a/tests/cli-contracts/asset-base-url.test.js +++ b/tests/cli-contracts/asset-base-url.test.js @@ -40,6 +40,7 @@ import { } from '../shared.js'; import fs from 'node:fs'; import path from 'path'; +import { execFileSync } from 'node:child_process'; let passed = 0; let failed = 0; @@ -99,8 +100,10 @@ export const test = runTestFile({ const result = build(proj); assert(result.ok, 'URL-1c: sub-project build with summer template succeeds'); const html = fs.readFileSync(path.join(proj, 'site/index.html'), 'utf8'); - assert(//.test(html), - 'URL-1c: rendered HTML contains (root project) so ./assets/... resolves at any URL shape'); + // Root deploys no longer emit — relies on + // relativePathToRoot + ./assets/... + assert(!//.test(html), + 'URL-1c: root project does NOT emit (fixes #175 and #177)'); assert(/href="\.\/assets\/template\/summer\.css/.test(html), 'URL-1c: rendered HTML uses relative ./assets/template/summer.css'); assert(/src="\.\/assets\/template\/summer\.js/.test(html), @@ -123,8 +126,10 @@ export const test = runTestFile({ const result = build(proj); assert(result.ok, 'URL-1d: default-template build succeeds'); const html = fs.readFileSync(path.join(proj, 'site/index.html'), 'utf8'); - assert(//.test(html), - 'URL-1d: default-template HTML also contains '); + // Root deploys with default template: no tag (relies on + // relative ./assets/... resolution + assert(!//.test(html), + 'URL-1d: root deploy default template does NOT emit '); } // URL-1e: the workspace sub-site case — a /search project must @@ -164,6 +169,53 @@ export const test = runTestFile({ 'URL-1e: /search/ sub-site has window.DOCMD_SITE_ROOT = "/search/"'); } + // URL-1f: issue #175 — GitHub Pages project site (url has subpath, + // no explicit base). base must be auto-derived to the subpath and + // must point at it so assets resolve correctly. + { + const proj = setup('asset-base-url-gh-pages-subpath'); + writeFile(proj, 'docs/index.md', '# Home\n'); + writeFile(proj, 'docmd.config.json', JSON.stringify({ + title: 'URL-1f', + url: 'https://alexhelms.github.io/some-project', + src: './docs', + out: './site' + }, null, 2) + '\n'); + + const result = build(proj); + assert(result.ok, 'URL-1f: GH Pages subpath build succeeds'); + const html = fs.readFileSync(path.join(proj, 'site/index.html'), 'utf8'); + assert(//.test(html), + 'URL-1f: GH Pages subpath emits (fixes #175)'); + assert(/href="\.\/assets\/css\/docmd-main\.css/.test(html), + 'URL-1f: CSS link is relative (resolves via base)'); + } + + // URL-1g: issue #177 — --offline mode must NOT emit a tag. + // file:// resolution breaks if is present because + // it re-roots every relative URL to the filesystem root. + { + const proj = setup('asset-base-url-offline-mode'); + fs.mkdirSync(path.join(proj, 'docs/guide'), { recursive: true }); + writeFile(proj, 'docs/index.md', '# Home\n'); + writeFile(proj, 'docs/guide/page.md', '# Guide\n'); + writeFile(proj, 'docmd.config.json', JSON.stringify({ + title: 'URL-1g', + src: './docs', + out: './site' + }, null, 2) + '\n'); + + const result = execFileSync('node', [path.resolve(import.meta.dirname, '..', '..', 'packages', 'core', 'dist', 'bin', 'docmd.js'), 'build', '--offline'], { + cwd: proj, encoding: 'utf8', stdio: 'pipe' + }); + assert(result.includes('Build complete'), 'URL-1g: --offline build completes'); + const pageHtml = fs.readFileSync(path.join(proj, 'site/guide/page/index.html'), 'utf8'); + assert(!/ tag (fixes #177)'); + assert(/href="\.\.\/\.\.\/assets\/css\/docmd-main\.css/.test(pageHtml), + 'URL-1g: nested page uses page-relative CSS path (resolves under file://)'); + } + // URL-2: `engine: "rust"` (and `engines: { rust: {...} }`) is in // KNOWN_KEYS so a project that requests the rust preview engine // does not print an "Unknown property" warning. diff --git a/tools/simulate-consumer.mjs b/tools/simulate-consumer.mjs new file mode 100644 index 00000000..da0cee32 --- /dev/null +++ b/tools/simulate-consumer.mjs @@ -0,0 +1,686 @@ +#!/usr/bin/env node +/** + * -------------------------------------------------------------------- + * docmd : the zero-config documentation engine. + * + * @package @docmd/core (and ecosystem) + * @website https://docmd.io + * @repository https://github.com/docmd-io/docmd + * @license MIT + * @copyright (c) 2025-present docmd.io + * + * [docmd-source] - Please do not remove this header. + * -------------------------------------------------------------------- + * + * simulate-consumer : test @docmd/core the way a real user installs it. + * + * PROBLEM: + * dev:local runs the monorepo binary directly. Node resolves modules + * from the monorepo's node_modules, which has EVERY workspace package + * symlinked. This masks missing deps, auto-install failures, and + * version mismatches. Issues only surface after publishing, when CI + * or GitHub Pages deploys fail. + * + * SOLUTION: + * Create a throwaway project, install @docmd/core the same way a user + * would, copy a real config + content set, and run the build. Any + * missing-dep, auto-install, or resolution issue fires here, before + * the release. + * + * USAGE: + * Run FROM the consumer project directory (docs/, docmd.io/, your own repo): + * + * node /path/to/docmd/tools/simulate-consumer.mjs # npm, temp dir + * node /path/to/docmd/tools/simulate-consumer.mjs --local # monorepo tarballs, temp dir + * node /path/to/docmd/tools/simulate-consumer.mjs --local --in-place # work in consumer dir directly + * node /path/to/docmd/tools/simulate-consumer.mjs --local --dev # live dev server + * node /path/to/docmd/tools/simulate-consumer.mjs --local --in-place --dev # full real-user dev experience + * node /path/to/docmd/tools/simulate-consumer.mjs --keep # keep temp dir for inspection + * node /path/to/docmd/tools/simulate-consumer.mjs --no-clean # in-place: keep existing node_modules + * node /path/to/docmd/tools/simulate-consumer.mjs --verbose # stream all output + * node /path/to/docmd/tools/simulate-consumer.mjs --skip-monorepo-build # assume dist/ is current + * + * Or pass --source explicitly (overrides process.cwd()): + * node tools/simulate-consumer.mjs --source ../docs --local + * + * The consumer project is the directory you point at: it must contain + * a docmd config (docmd.config.{js,json,mjs}) and the markdown source + * the config references. + * + * MODES (two independent axes): + * + * Install source: + * default : npm install @docmd/core@latest from the public registry. + * --local : Copy every monorepo package to /tmp staging, resolve + * workspace:* refs in the COPIES (monorepo never touched), + * pack tarballs from staging. Tests UNRELEASED local changes + * with zero risk to the monorepo working tree. + * + * Working directory: + * default : Copy consumer content to a throwaway temp dir + * (/tmp/docmd-consumer-sim-*), install there, build there. + * Cleanest simulation — nothing touches the consumer dir. + * --in-place : Install and run directly in the consumer dir. The + * consumer's package.json, node_modules, and site/ are + * modified exactly as a normal `docmd build` would. + * This is the closest to the real user experience: + * you see site/ appear, node_modules get updated, and + * live changes are reflected in `--dev` mode. + * --dev : Run `docmd dev` (live server) instead of `docmd build`. + * Inherits stdio so you interact with the server normally. + * Best with --in-place: edit your docs and see live + * updates, exactly like a real user. + * + * SAFETY: + * This is a read-only diagnostic tool. It never commits, never + * pushes, never modifies git state, and NEVER mutates the monorepo's + * package.json files. The --local mode COPIES each package to a + * staging directory under /tmp, rewrites workspace:* refs in the + * COPIES only, and packs from there. If the process is killed at + * any point (Ctrl+C, crash, power loss), the monorepo is untouched. + * Only /tmp is dirty. The only monorepo side-effect is an optional + * `pnpm -r run build` (writes gitignored dist/). + * + * EXIT CODES: + * 0 : build succeeded, no missing-dep warnings + * 1 : build failed OR auto-install warnings appeared + * 2 : setup error (build failed, pack failed, etc.) + * (dev mode: exit code is the server's exit, usually 0 on Ctrl+C) + * -------------------------------------------------------------------- + */ + +import { execSync, spawnSync, spawn } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const MONOREPO_ROOT = path.resolve(__dirname, '..'); + +const args = process.argv.slice(2); +const USE_LOCAL = args.includes('--local'); +const IN_PLACE = args.includes('--in-place'); +const RUN_DEV = args.includes('--dev'); +const KEEP = args.includes('--keep'); +const NO_CLEAN = args.includes('--no-clean'); +const VERBOSE = args.includes('--verbose') || args.includes('--v'); +const SKIP_BUILD = args.includes('--skip-monorepo-build') || args.includes('--skip-build'); +const SOURCE_FLAG = args.find((a) => a.startsWith('--source=')); +// Default: the directory you ran the tool from. Makes it generic: cd into +// any consumer project (docs/, docmd.io/, your own repo) and point at the +// monorepo tool. No hardcoded path. +const SOURCE_DIR = SOURCE_FLAG + ? path.resolve(SOURCE_FLAG.slice('--source='.length)) + : path.resolve(process.cwd()); + +const TMP = path.resolve('/tmp/docmd-consumer-sim-' + Date.now()); + +// --- ANSI helpers (minimal, no deps) --- +const DIM = (s) => `\x1b[2m${s}\x1b[0m`; +const GREEN = (s) => `\x1b[32m${s}\x1b[0m`; +const RED = (s) => `\x1b[31m${s}\x1b[0m`; +const CYAN = (s) => `\x1b[36m${s}\x1b[0m`; +const BOLD = (s) => `\x1b[1m${s}\x1b[0m`; +const YELLOW = (s) => `\x1b[33m${s}\x1b[0m`; + +function step(label, fn) { + process.stdout.write(` ${DIM('WAIT')} ${label}...`); + try { + const result = fn(); + process.stdout.write(`\r ${GREEN('DONE')} ${label} \n`); + return result; + } catch (err) { + process.stdout.write(`\r ${RED('FAIL')} ${label} \n`); + if (VERBOSE) console.error(err.stderr?.toString() || err.message); + throw err; + } +} + +function run(cmd, opts = {}) { + return execSync(cmd, { encoding: 'utf8', stdio: VERBOSE ? 'inherit' : 'pipe', timeout: 120000, ...opts }); +} + +// ----------------------------------------------------------------------- +// Step 1: Build the monorepo (needed for --local mode, skipped for npm mode) +// ----------------------------------------------------------------------- + +function buildMonorepo() { + step('Building monorepo (pnpm -r run build)', () => { + run('pnpm -r run build', { cwd: MONOREPO_ROOT }); + }); +} + +// ----------------------------------------------------------------------- +// Step 2a: --local mode — pack all packages into tarballs +// +// SAFETY: This function NEVER mutates the monorepo. Instead of rewriting +// package.json files in place (which risks leaving the monorepo broken +// if the process is killed mid-pack), it COPIES each package to a +// staging directory under /tmp, rewrites the copies, and packs from +// there. If the process is killed at ANY point, the monorepo is +// untouched — only /tmp is dirty. +// ----------------------------------------------------------------------- + +// Collect all @docmd/* packages under packages/ with their file lists. +// Returns [{ pkgDir, name, version, files }] for every packable package. +function collectMonorepoPackages() { + const packagesDir = path.join(MONOREPO_ROOT, 'packages'); + const out = []; + const walk = (dir) => { + for (const entry of fs.readdirSync(dir)) { + const full = path.join(dir, entry); + const pkgJsonPath = path.join(full, 'package.json'); + if (fs.existsSync(pkgJsonPath)) { + const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')); + if (pkg.name && pkg.name.startsWith('@docmd/')) { + out.push({ + pkgDir: full, + name: pkg.name, + version: pkg.version, + files: Array.isArray(pkg.files) ? pkg.files : ['dist'], + }); + } + } else if (fs.statSync(full).isDirectory() && !entry.startsWith('_') && !entry.startsWith('.')) { + walk(full); + } + } + }; + walk(packagesDir); + return out; +} + +// Copy a package to a staging dir, including only the files listed in its +// `files` field (what would go into the tarball) plus package.json itself. +function copyPackageToStaging(pkgInfo, stagingRoot) { + const { pkgDir, name } = pkgInfo; + // Scoped name → flatten to a safe directory name. + const flatName = name.replace('@', '').replace('/', '-'); + const destDir = path.join(stagingRoot, 'packages', flatName); + fs.mkdirSync(destDir, { recursive: true }); + + // Always copy package.json. + fs.copyFileSync(path.join(pkgDir, 'package.json'), path.join(destDir, 'package.json')); + + // Copy each entry from the `files` field (usually ['dist'] or ['dist','registry']). + for (const fileEntry of pkgInfo.files) { + const src = path.join(pkgDir, fileEntry); + const dest = path.join(destDir, fileEntry); + if (fs.existsSync(src)) { + if (fs.statSync(src).isDirectory()) { + run(`cp -R "${src}" "${dest}"`); + } else { + fs.copyFileSync(src, dest); + } + } + } + return destDir; +} + +// Build version map from all collected packages (name → version). +function buildVersionMap(packages) { + const map = {}; + for (const p of packages) { + map[p.name] = p.version; + } + return map; +} + +// Rewrite workspace:* → ^ in a SINGLE package.json (the staging copy). +// Uses the version map to resolve cross-package refs. +function rewriteDepsInPackageJson(pkgJsonPath, versionMap) { + const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')); + let changed = false; + for (const field of ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']) { + if (!pkg[field]) continue; + for (const dep in pkg[field]) { + if (pkg[field][dep].startsWith('workspace:')) { + const version = versionMap[dep]; + if (version) { + pkg[field][dep] = `^${version}`; + changed = true; + } + } + } + } + if (changed) { + fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8'); + } +} + +function packLocal() { + const stagingDir = path.join(TMP, '_staging'); + const tarballDir = path.join(stagingDir, 'tarballs'); + fs.mkdirSync(stagingDir, { recursive: true }); + fs.mkdirSync(tarballDir, { recursive: true }); + + console.log(DIM(` staging: ${stagingDir}`)); + + const packages = collectMonorepoPackages(); + const versionMap = buildVersionMap(packages); + + const stagedDirs = []; + step(`Copying ${packages.length} packages to staging (monorepo untouched)`, () => { + for (const pkgInfo of packages) { + const stagedDir = copyPackageToStaging(pkgInfo, stagingDir); + stagedDirs.push(stagedDir); + } + }); + + step('Resolving workspace:* → ^version (in staging copies only)', () => { + for (const stagedDir of stagedDirs) { + const pkgJsonPath = path.join(stagedDir, 'package.json'); + if (fs.existsSync(pkgJsonPath)) { + rewriteDepsInPackageJson(pkgJsonPath, versionMap); + } + } + }); + + const tarballs = []; + step('Packing @docmd/* packages into tarballs (from staging)', () => { + for (const stagedDir of stagedDirs) { + const pkg = JSON.parse(fs.readFileSync(path.join(stagedDir, 'package.json'), 'utf8')); + const result = spawnSync('pnpm', ['pack', '--pack-destination', tarballDir], { + cwd: stagedDir, + encoding: 'utf8', + }); + if (result.status === 0) { + const tgzName = result.stdout.trim().split('\n').pop(); + if (tgzName) tarballs.push(path.join(tarballDir, path.basename(tgzName))); + } else if (VERBOSE) { + console.error(` pack failed for ${pkg.name}: ${result.stderr}`); + } + } + }); + + return tarballs; +} + +// ----------------------------------------------------------------------- +// Step 2b: npm mode — just install from the public registry +// ----------------------------------------------------------------------- + +function installFromNpm(projectDir) { + step('Installing @docmd/core from npm', () => { + run('npm install @docmd/core@latest', { cwd: projectDir }); + }); +} + +function installFromTarballs(projectDir, tarballs) { + step(`Installing ${tarballs.length} local tarballs`, () => { + // Install all local tarballs in one npm install so npm resolves the + // full dep graph from the tarballs first, then npm for anything else. + run(`npm install ${tarballs.map((t) => `"${t}"`).join(' ')}`, { cwd: projectDir }); + }); +} + +// ----------------------------------------------------------------------- +// Step 3: Copy consumer content (config + docs) +// ----------------------------------------------------------------------- + +function copyConsumerContent(projectDir) { + step(`Copying content from ${path.basename(SOURCE_DIR)}`, () => { + // Validate: the source dir must look like a docmd consumer project. + const configCandidates = ['docmd.config.js', 'docmd.config.json', 'docmd.config.mjs', 'docmd.config.ts']; + const foundConfig = configCandidates.find((c) => fs.existsSync(path.join(SOURCE_DIR, c))); + if (!foundConfig) { + throw new Error( + `No docmd.config.{js,json,mjs,ts} found in ${SOURCE_DIR}. ` + + `Run this tool from inside a docmd consumer project, or pass --source=.`, + ); + } + + // Copy the entire source project, excluding paths that would either + // pollute the temp project or mask the consumer experience we're + // trying to simulate. node_modules is the key exclusion: if we copied + // the consumer's own node_modules we'd inherit whatever they happen to + // have installed, defeating the point of a clean install. + const EXCLUDE = new Set([ + 'node_modules', + '.git', + '.DS_Store', + 'site', // docmd's default build output + 'dist', // common alt build output + 'package-lock.json', + 'pnpm-lock.yaml', + 'yarn.lock', + ]); + + const entries = fs.readdirSync(SOURCE_DIR, { withFileTypes: true }); + for (const entry of entries) { + if (EXCLUDE.has(entry.name)) continue; + const src = path.join(SOURCE_DIR, entry.name); + const dest = path.join(projectDir, entry.name); + if (entry.isDirectory()) { + run(`cp -R "${src}" "${dest}"`); + } else { + fs.copyFileSync(src, dest); + } + } + + // Strip @docmd/core from the consumer's package.json so the install + // step is the only thing that adds it (mimics a fresh user install). + const consumerPkgPath = path.join(projectDir, 'package.json'); + if (fs.existsSync(consumerPkgPath)) { + const pkg = JSON.parse(fs.readFileSync(consumerPkgPath, 'utf8')); + let changed = false; + for (const field of ['dependencies', 'devDependencies']) { + if (pkg[field] && pkg[field]['@docmd/core']) { + delete pkg[field]['@docmd/core']; + changed = true; + } + } + // Force private so npm doesn't complain about missing fields. + pkg.private = true; + if (!pkg.name) pkg.name = 'docmd-consumer-sim'; + if (changed || !pkg.private || !pkg.name) { + fs.writeFileSync(consumerPkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8'); + } + } + }); +} + +// ----------------------------------------------------------------------- +// Step 4: Run the build and capture issues +// ----------------------------------------------------------------------- + +function runBuild(projectDir) { + let output = ''; + let exitCode = 0; + + process.stdout.write(` ${DIM('WAIT')} Running docmd build...`); + try { + output = run('npx docmd build', { cwd: projectDir, timeout: 120000 }); + process.stdout.write(`\r ${GREEN('DONE')} Running docmd build \n`); + } catch (err) { + output = (err.stdout || '') + (err.stderr || ''); + exitCode = err.status ?? 1; + process.stdout.write(`\r ${RED('FAIL')} Running docmd build \n`); + } + + if (VERBOSE || exitCode !== 0) { + console.log(output); + } + + return { output, exitCode }; +} + +// ----------------------------------------------------------------------- +// Step 4b: Run the dev server (long-running, inherits stdio) +// ----------------------------------------------------------------------- + +function runDev(projectDir) { + // Dev server is long-running: inherit stdio so the user sees live + // output, can edit docs and watch hot reloads, and Ctrl+C to stop. + // No timeout, no output capture — this is the real user experience. + console.log(` ${CYAN('▶')} Starting docmd dev server in ${DIM(projectDir)}`); + console.log(` ${DIM(' Edit your docs and watch live changes. Ctrl+C to stop.')}`); + console.log(''); + + const child = spawn('npx', ['docmd', 'dev'], { + cwd: projectDir, + stdio: 'inherit', + shell: process.platform === 'win32', + }); + + return new Promise((resolve) => { + child.on('close', (code) => { + resolve({ exitCode: code ?? 0 }); + }); + child.on('error', (err) => { + console.error(RED(`\n Dev server failed: ${err.message}`)); + resolve({ exitCode: 1 }); + }); + // Propagate Ctrl+C to the child so the user can stop the server. + process.on('SIGINT', () => child.kill('SIGINT')); + }); +} + +// ----------------------------------------------------------------------- +// Step 5: Analyse output for issues a real user would hit +// ----------------------------------------------------------------------- + +function analyseOutput(output, exitCode) { + const issues = []; + + // Check for missing-dep warnings that auto-install couldn't fix. + if (/not found in official registry/i.test(output)) { + issues.push('Plugin/template not in registry — auto-install refused'); + } + if (/Auto-install of.*failed/i.test(output)) { + issues.push('Auto-install failed for at least one package'); + } + if (/Could not load.*after auto-install/i.test(output)) { + issues.push('Package installed but could not be loaded (exports/ESM issue)'); + } + if (/pluginLoadErrors|Could not load plugin/i.test(output)) { + issues.push('Plugin load error — missing or misconfigured'); + } + if (exitCode !== 0) { + issues.push(`Build exited with code ${exitCode}`); + } + + return issues; +} + +// ----------------------------------------------------------------------- +// Main +// ----------------------------------------------------------------------- + +function cleanup() { + if (KEEP) { + console.log(DIM(`\n Kept: ${TMP}`)); + return; + } + try { + fs.rmSync(TMP, { recursive: true, force: true }); + } catch {} +} + +async function main() { + // Guard: refuse to simulate the monorepo against itself. Running from + // inside docmd/ would copy the entire monorepo (packages/, scripts/, + // tests/) into the temp project, which makes no sense and would take + // forever. The user must point at a CONSUMER project (docs/, docmd.io/, + // or their own repo). + if (SOURCE_DIR === MONOREPO_ROOT || SOURCE_DIR.startsWith(MONOREPO_ROOT + path.sep)) { + console.log(''); + console.log(RED(BOLD(' ✗ Source is inside the docmd monorepo.'))); + console.log(YELLOW(` SOURCE: ${SOURCE_DIR}`)); + console.log(YELLOW(` MONOREPO: ${MONOREPO_ROOT}`)); + console.log(''); + console.log(DIM(' This tool simulates a CONSUMER project (docs/, docmd.io/, your repo).')); + console.log(DIM(' Run it from the consumer directory:')); + console.log(DIM(' cd ../docs')); + console.log(DIM(' node ../docmd/tools/simulate-consumer.mjs --local')); + console.log(''); + process.exit(2); + } + + console.log(''); + console.log(CYAN(BOLD('docmd consumer simulation'))); + console.log(DIM(` install: ${USE_LOCAL ? 'local tarballs (unreleased)' : 'npm (published)'}`)); + console.log(DIM(` workdir: ${IN_PLACE ? 'in-place (' + SOURCE_DIR + ')' : 'temp (' + TMP + ')'}`)); + console.log(DIM(` command: ${RUN_DEV ? 'dev (live server)' : 'build (one-shot)'}`)); + console.log(DIM(` source: ${SOURCE_DIR}`)); + console.log(''); + + try { + if (IN_PLACE) { + await runInPlaceMode(); + } else { + await runTempMode(); + } + } catch (err) { + console.log(''); + console.log(RED(BOLD(' ✗ Simulation setup failed:'))); + console.log(RED(` ${err.message}`)); + if (VERBOSE && err.stack) console.log(DIM(err.stack)); + cleanup(); + process.exit(2); + } +} + +// ----------------------------------------------------------------------- +// Install @docmd/core into a target directory (shared by both modes) +// ----------------------------------------------------------------------- + +async function installCore(targetDir) { + if (USE_LOCAL) { + if (!SKIP_BUILD) { + buildMonorepo(); + } else { + console.log(DIM(' (skipping monorepo build — assuming packages/*/dist/ is current)')); + } + const tarballs = packLocal(); + installFromTarballs(targetDir, tarballs); + } else { + installFromNpm(targetDir); + } +} + +// ----------------------------------------------------------------------- +// Mode A: Temp-dir simulation (isolated, clean, CI-like) +// ----------------------------------------------------------------------- + +async function runTempMode() { + fs.mkdirSync(TMP, { recursive: true }); + run('npm init -y', { cwd: TMP }); + + await installCore(TMP); + copyConsumerContent(TMP); + + if (RUN_DEV) { + const { exitCode } = await runDev(TMP); + cleanup(); + process.exit(exitCode); + } + + const { output, exitCode } = runBuild(TMP); + const issues = analyseOutput(output, exitCode); + + console.log(''); + if (issues.length === 0) { + console.log(GREEN(BOLD(' ✓ No consumer-facing issues detected'))); + console.log(DIM(` Build succeeded, all deps resolved, no missing-plugin warnings.`)); + console.log(DIM(` Site output: ${TMP}/site`)); + console.log(DIM(` Preview with: npx serve ${TMP}/site`)); + cleanup(); + process.exit(0); + } else { + console.log(RED(BOLD(` ✗ ${issues.length} issue(s) a real user would hit:`))); + for (const issue of issues) { + console.log(RED(` - ${issue}`)); + } + console.log(DIM(`\n Temp dir preserved: ${TMP}`)); + console.log(DIM(' Re-run with --keep to inspect, or --verbose for full output.')); + process.exit(1); + } +} + +// ----------------------------------------------------------------------- +// Mode B: In-place simulation (works directly in the consumer dir) +// +// This modifies the consumer dir exactly as a normal `docmd build` would: +// - package.json gets @docmd/core (and auto-installed plugins/templates) +// - node_modules is created/updated +// - site/ (or dist/) is created by the build +// +// The user sees everything happen in front of them. To revert: +// git checkout package.json && rm -rf node_modules site +// ----------------------------------------------------------------------- + +// Remove stale state from the consumer dir so every sim run starts from +// a clean install. Without this, leftover node_modules from a previous +// sim run or from dev:local mask missing-dep issues — the exact bug we're +// trying to catch. The clean is mandatory in in-place mode unless the +// user passes --no-clean. +function cleanConsumerDir(dir) { + step('Cleaning stale state (node_modules, lockfiles, site/)', () => { + const paths = [ + 'node_modules', + 'package-lock.json', + 'pnpm-lock.yaml', + 'yarn.lock', + 'site', + ]; + for (const rel of paths) { + const full = path.join(dir, rel); + if (fs.existsSync(full)) { + fs.rmSync(full, { recursive: true, force: true }); + } + } + }); +} + +// Reset the consumer's package.json to a known-clean baseline before +// installing. Strips @docmd/* entries (added by auto-install in previous +// runs) and any stale dep references, leaving only the user's own deps. +function resetConsumerPackageJson(dir) { + const pkgPath = path.join(dir, 'package.json'); + if (!fs.existsSync(pkgPath)) return; + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); + + for (const field of ['dependencies', 'devDependencies']) { + if (!pkg[field]) continue; + // Remove any @docmd/* packages that a previous sim auto-installed. + // The user's real deps (docmd-search, etc.) stay. + for (const dep of Object.keys(pkg[field])) { + if (dep.startsWith('@docmd/')) { + delete pkg[field][dep]; + } + } + // Drop the field if it's now empty. + if (Object.keys(pkg[field]).length === 0) { + delete pkg[field]; + } + } + + pkg.private = true; + if (!pkg.name) pkg.name = 'docmd-consumer-sim'; + fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8'); +} + +async function runInPlaceMode() { + console.log(YELLOW(` ⚠ In-place mode: ${SOURCE_DIR} will be modified.`)); + console.log(DIM(' package.json, node_modules, and site/ will change as a normal docmd run.')); + console.log(DIM(' Revert with: git checkout package.json && rm -rf node_modules site')); + console.log(''); + + // Clean first so every run starts from a real fresh install. This is + // the whole point of the simulation — if stale node_modules survive + // from a previous run, the sim can't catch missing-dep issues. + // Pass --no-clean to skip (useful for rapid iteration where you only + // changed markdown content and want to keep the install step fast). + if (!NO_CLEAN) { + cleanConsumerDir(SOURCE_DIR); + resetConsumerPackageJson(SOURCE_DIR); + } else { + console.log(DIM(' (--no-clean: keeping existing node_modules and package.json)')); + } + + await installCore(SOURCE_DIR); + + if (RUN_DEV) { + const { exitCode } = await runDev(SOURCE_DIR); + process.exit(exitCode); + } + + const { output, exitCode } = runBuild(SOURCE_DIR); + const issues = analyseOutput(output, exitCode); + + console.log(''); + if (issues.length === 0) { + console.log(GREEN(BOLD(' ✓ Build completed in-place, no consumer-facing issues.'))); + console.log(DIM(` site/ is ready in ${SOURCE_DIR}`)); + process.exit(0); + } else { + console.log(RED(BOLD(` ✗ ${issues.length} issue(s) a real user would hit:`))); + for (const issue of issues) { + console.log(RED(` - ${issue}`)); + } + process.exit(1); + } +} + +main(); From f4c52782f33e59187f01a34d18a725ad08099b1f Mon Sep 17 00:00:00 2001 From: Ghazi Date: Tue, 14 Jul 2026 01:34:45 +0530 Subject: [PATCH 2/5] fix(#175 #167 #177): centralised base tag + auto-install retry fix 1. Centralised base-tag enforcement: normaliseBaseTag() in @docmd/parser strips all base tags and injects one canonical based on (isOffline, siteRootAbs). Generator owns it, not templates. 2. Auto-install retry with manual node_modules walk-up: Node caches failed require.resolve. New manualResolvePackageEntry() bypasses cache with fresh fs.existsSync checks. Plus DOCMD_INSTALL_VERSION env var. 3. Lint + prep fixes: ignore _-prefixed vars, openapi dead code, prep streams tests live. Version bumped to 0.8.13. Tests: 90/90. --- eslint.config.mjs | 2 +- package.json | 2 +- packages/_playground/package.json | 2 +- packages/api/package.json | 2 +- packages/api/registry/plugins.generated.json | 2 +- packages/api/src/runtime-deps.ts | 78 ++++++++++-- packages/core/package.json | 2 +- packages/core/src/engine/generator.ts | 40 ++++-- packages/deployer/package.json | 2 +- packages/engines/js/package.json | 2 +- packages/engines/js/src/index.ts | 2 +- .../bin/docmd-engine-darwin-arm64.node | Bin 771536 -> 771536 bytes .../engines/rust-binaries/native/Cargo.lock | 2 +- .../engines/rust-binaries/native/Cargo.toml | 2 +- packages/engines/rust-binaries/package.json | 2 +- packages/engines/rust/package.json | 2 +- packages/engines/rust/src/index.ts | 2 +- packages/legacy/doc.md/package.json | 2 +- packages/legacy/mgks/package.json | 2 +- packages/live/package.json | 2 +- packages/parser/package.json | 2 +- packages/parser/src/index.ts | 1 + packages/parser/src/utils/url-utils.ts | 65 ++++++++++ packages/plugins/analytics/package.json | 2 +- packages/plugins/analytics/src/index.ts | 2 +- packages/plugins/git/package.json | 2 +- packages/plugins/git/src/index.ts | 2 +- packages/plugins/installer/package.json | 2 +- packages/plugins/llms/package.json | 2 +- packages/plugins/llms/src/index.ts | 2 +- packages/plugins/math/package.json | 2 +- packages/plugins/math/src/index.ts | 2 +- packages/plugins/mermaid/package.json | 2 +- packages/plugins/mermaid/src/index.ts | 2 +- packages/plugins/okf/package.json | 2 +- packages/plugins/okf/src/index.ts | 4 +- packages/plugins/openapi/package.json | 2 +- packages/plugins/openapi/src/index.ts | 6 +- packages/plugins/pwa/package.json | 2 +- packages/plugins/pwa/src/index.ts | 2 +- packages/plugins/search/package.json | 2 +- packages/plugins/search/src/index.ts | 2 +- packages/plugins/seo/package.json | 2 +- packages/plugins/seo/src/index.ts | 2 +- packages/plugins/sitemap/package.json | 2 +- packages/plugins/sitemap/src/index.ts | 2 +- packages/plugins/threads/package.json | 2 +- packages/plugins/threads/src/index.ts | 2 +- packages/templates/summer/package.json | 2 +- packages/templates/summer/src/index.ts | 2 +- .../templates/summer/templates/layout.ejs | 4 - packages/themes/package.json | 2 +- packages/tui/package.json | 2 +- packages/ui/package.json | 2 +- packages/ui/templates/layout.ejs | 3 - packages/utils/package.json | 2 +- tests/cli-contracts/asset-base-url.test.js | 20 +-- tools/prep.js | 117 +++++++----------- tools/simulate-consumer.mjs | 4 +- 59 files changed, 271 insertions(+), 165 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index cdcdd4e3..eb7ca47d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -39,7 +39,7 @@ export default [ }, rules: { '@typescript-eslint/no-require-imports': 'off', - '@typescript-eslint/no-unused-vars': 'warn', + '@typescript-eslint/no-unused-vars': ['warn', { varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', argsIgnorePattern: '^_' }], '@typescript-eslint/no-explicit-any': 'warn', 'preserve-caught-error': 'off', '@typescript-eslint/ban-ts-comment': 'warn', diff --git a/package.json b/package.json index 44ec9d33..71c73708 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/monorepo", - "version": "0.8.12", + "version": "0.8.13", "private": true, "description": "The minimalist, zero-config documentation generator monorepo.", "scripts": { diff --git a/packages/_playground/package.json b/packages/_playground/package.json index bdd06625..e58941ea 100644 --- a/packages/_playground/package.json +++ b/packages/_playground/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/playground", - "version": "0.8.12", + "version": "0.8.13", "private": true, "dependencies": { "@docmd/core": "workspace:*", diff --git a/packages/api/package.json b/packages/api/package.json index 6dabfa8f..c2950207 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/api", - "version": "0.8.12", + "version": "0.8.13", "description": "Plugin API surface for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/api/registry/plugins.generated.json b/packages/api/registry/plugins.generated.json index 3fd948be..22834b9e 100644 --- a/packages/api/registry/plugins.generated.json +++ b/packages/api/registry/plugins.generated.json @@ -1,6 +1,6 @@ { "$meta": { - "generatedAt": "2026-07-13T06:05:40.151Z", + "generatedAt": "2026-07-13T19:46:21.764Z", "generator": "scripts/build-plugin-registry.mjs", "packageCount": 15 }, diff --git a/packages/api/src/runtime-deps.ts b/packages/api/src/runtime-deps.ts index eaae08a4..384bed3e 100644 --- a/packages/api/src/runtime-deps.ts +++ b/packages/api/src/runtime-deps.ts @@ -137,6 +137,11 @@ export function detectPackageManager(cwd: string): 'pnpm' | 'yarn' | 'bun' | 'np * a CI image without node_modules linked). */ export function getDocmdVersion(): string { + // DOCMD_INSTALL_VERSION overrides everything. Lets users / CI pin auto-installs + // to a specific version (or 'latest') independent of the installed core. + if (process.env.DOCMD_INSTALL_VERSION) { + return process.env.DOCMD_INSTALL_VERSION.trim() || 'latest'; + } try { const corePkgPath = require.resolve('@docmd/core/package.json', { paths: [process.cwd(), __dirname, __monorepoRoot], @@ -349,13 +354,52 @@ export function shortKey(packageName: string): string | null { } /** - * Re-load `pkg` after an install attempt. Resolves the entry point via - * `createRequire(consumerCwd)` so the resolution is rooted in the - * consumer's directory, then imports via file URL. This is critical: - * a bare `import(pkgName)` uses Node's default resolution which walks - * up from the calling module's location — when this code runs from - * the docmd monorepo, that walk would find a stale workspace copy of - * the package instead of the one we just installed for the consumer. + * Manually resolve a package entry point by walking up from `startDir` + * looking for `node_modules//package.json`. This bypasses + * Node's internal module resolution cache, which can fail to find a + * package that was just installed during the same process (the cache + * remembers the "not found" result from the initial failed resolve). + * + * Returns the absolute path to the entry JS file, or null if not found. + */ +function manualResolvePackageEntry(packageName: string, startDir: string): string | null { + const pkgSubPath = path.join('node_modules', packageName); + let dir = path.resolve(startDir); + // Walk up the directory tree looking for node_modules/ + while (dir !== path.dirname(dir)) { + const candidate = path.join(dir, pkgSubPath, 'package.json'); + if (nativeFs.existsSync(candidate)) { + try { + const pkg = JSON.parse(nativeFs.readFileSync(candidate, 'utf8')); + // Resolve the entry point: exports['.'] > main > index.js + let entry: string | undefined; + if (pkg.exports && typeof pkg.exports === 'object' && pkg.exports['.']) { + const exp = pkg.exports['.']; + entry = typeof exp === 'string' ? exp : (exp.import || exp.require || exp.default); + } + if (!entry) entry = pkg.main || 'index.js'; + const cleanEntry = (entry || 'index.js').replace(/^\.\//, ''); + const entryPath = path.join(dir, pkgSubPath, cleanEntry); + if (nativeFs.existsSync(entryPath)) return entryPath; + // Try dist/index.js as a common fallback + const distEntry = path.join(dir, pkgSubPath, 'dist', 'index.js'); + if (nativeFs.existsSync(distEntry)) return distEntry; + } catch { + // Malformed package.json — keep walking + } + } + dir = path.dirname(dir); + } + return null; +} + +/** + * Re-load `pkg` after an install attempt. Tries `createRequire` first + * (honours exports conditions), then falls back to a manual node_modules + * walk-up that bypasses Node's internal resolution cache. The cache can + * stale-fail when a package was just `npm install`ed during the same + * process — the initial `require.resolve` failure is remembered even + * after the package appears on disk. * * Returns the module reference or null on failure. */ @@ -363,11 +407,29 @@ export async function tryLoadAfterInstall( packageName: string, consumerCwd: string = process.cwd(), ): Promise { + // Strategy 1: createRequire (honours exports field, but may stale-cache) try { const consumerRequire = createRequire(consumerCwd + '/'); const entry = consumerRequire.resolve(packageName); return await import(pathToFileURL(entry).href); } catch { - return null; + // Fall through to manual resolution + } + + // Strategy 2: manual node_modules walk-up (bypasses cache, always + // does a fresh filesystem check). This is the reliable path when + // the package was installed seconds ago in the same process. + const manualEntry = manualResolvePackageEntry(packageName, consumerCwd); + if (manualEntry) { + try { + return await import(pathToFileURL(manualEntry).href); + } catch (e: any) { + const detail = e?.code ? `${e.code}: ${e.message}` : (e?.message || String(e)); + TUI.warn(`Post-install load of ${packageName} (manual resolve to ${manualEntry}) failed: ${detail}`); + return null; + } } + + TUI.warn(`Post-install load of ${packageName} from ${consumerCwd} failed: package not found in node_modules tree`); + return null; } diff --git a/packages/core/package.json b/packages/core/package.json index c460a32b..d86f5128 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/core", - "version": "0.8.12", + "version": "0.8.13", "description": "Build production-ready documentation from Markdown in seconds. No React, no bloat, just content.", "type": "module", "browser": false, diff --git a/packages/core/src/engine/generator.ts b/packages/core/src/engine/generator.ts index ed1c8ef4..4fc68e06 100644 --- a/packages/core/src/engine/generator.ts +++ b/packages/core/src/engine/generator.ts @@ -46,7 +46,7 @@ import nativeFs from 'fs'; const _require = createRequire(import.meta.url); import * as parser from '@docmd/parser'; import { TUI } from '@docmd/tui'; -import { findPageNeighbors, findBreadcrumbs, normalizeNavPaths, createUrlContext, buildContextualUrl, computePageUrls, buildAbsoluteUrl, sanitizeUrl } from '@docmd/parser'; +import { findPageNeighbors, findBreadcrumbs, normalizeNavPaths, createUrlContext, buildContextualUrl, computePageUrls, buildAbsoluteUrl, sanitizeUrl, normaliseBaseTag } from '@docmd/parser'; import * as ui from '@docmd/ui'; @@ -540,6 +540,19 @@ export async function renderPages({ config, srcDir, fallbackSrcDir, outputDir, h else relativePathToRoot += '/'; relativePathToRoot = relativePathToRoot.replace(/\\/g, '/'); + // Canonical absolute site root (subpath deployment). The generator + // owns this decision — templates never compute it themselves. + // root deploy → '/' + // locale/version subpath → '/de/' or '/v1/' + // explicit `config.base` → '/my-repo/' (3rd-party deploys) + let siteRootAbs = '/'; + if (config._activePrefix && config._activePrefix !== '/') { + siteRootAbs = config._activePrefix; + } else if (config.base && config.base !== '/') { + siteRootAbs = config.base; + } + if (siteRootAbs !== '/' && !siteRootAbs.endsWith('/')) siteRootAbs += '/'; + // Navigation Context let navPath = '/' + page.outputPath.replace(/\\/g, '/').replace(/\/index\.html$/, '').replace(/^index\.html$/, ''); if (navPath === '/.') navPath = '/'; @@ -777,16 +790,7 @@ export async function renderPages({ config, srcDir, fallbackSrcDir, outputDir, h localePrefix: config._localeOutputPrefix || '', currentPagePath: navPath, outputPrefix, - siteRootAbs: (() => { - let root = '/'; - if (config._activePrefix && config._activePrefix !== '/') { - root = config._activePrefix; - } else if (config.base && config.base !== '/') { - root = config.base; - } - if (root !== '/' && !root.endsWith('/')) root += '/'; - return root; - })(), + siteRootAbs, t, buildAbsoluteUrl, sanitizeUrl, @@ -815,6 +819,20 @@ export async function renderPages({ config, srcDir, fallbackSrcDir, outputDir, h fullHtml = pageObj.html; + // ── Centralised enforcement (single source of truth) ── + // The generator is the ONLY authority for the tag. Templates + // must not emit one themselves — anything they emit will be stripped + // here and replaced with the canonical one computed from + // (siteRootAbs, isOfflineMode). This way old templates, third-party + // templates, and the default template all produce identical + // behaviour without any per-template logic to drift. + // + // Emit rules: + // isOfflineMode=true → no (file://) + // siteRootAbs === '/' (root deploy) → no + // siteRootAbs !== '/' (subpath deploy) → + fullHtml = normaliseBaseTag(fullHtml, !!options.offline, siteRootAbs); + // Queue the write writeQueue.push({ finalPath, html: fullHtml }); (page as any).urls = pageUrls; diff --git a/packages/deployer/package.json b/packages/deployer/package.json index efe5f636..75b556e9 100644 --- a/packages/deployer/package.json +++ b/packages/deployer/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/deployer", - "version": "0.8.12", + "version": "0.8.13", "description": "Deployment configuration generator for docmd - Docker, Nginx, Caddy, GitHub Pages, Vercel, and Netlify.", "type": "module", "main": "dist/index.js", diff --git a/packages/engines/js/package.json b/packages/engines/js/package.json index 4c78eff3..38c369b9 100644 --- a/packages/engines/js/package.json +++ b/packages/engines/js/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/engine-js", - "version": "0.8.12", + "version": "0.8.13", "description": "Default JavaScript engine for docmd using Node.js native APIs.", "type": "module", "main": "dist/index.js", diff --git a/packages/engines/js/src/index.ts b/packages/engines/js/src/index.ts index a3ef7f0d..3edc2272 100644 --- a/packages/engines/js/src/index.ts +++ b/packages/engines/js/src/index.ts @@ -275,7 +275,7 @@ const handlers: Record = { export function createJsEngine(): Engine { return { name: 'js', - version: '0.8.12', + version: '0.8.13', supports(taskType: string): boolean { return taskType in handlers; diff --git a/packages/engines/rust-binaries/bin/docmd-engine-darwin-arm64.node b/packages/engines/rust-binaries/bin/docmd-engine-darwin-arm64.node index 5218260e5909874773b6c442870bfa910b341e22..aa43e1f6c7ebaee94f4087d95823ea2564086130 100755 GIT binary patch delta 112488 zcma%E30xJ`_n$KlWKmGyJs$h2ppYWs65;~5W~qrwE~&UBX=!e`3%KM~%5%`8mWFHc z)Y5QCb3-c4QbDs)(?HX}a={%F`G4=sJbn4I&*$IgL-X#v=bU@)+3vZ^jD-th3Kzy~ zdrzh`WsKax!{-YZN&HtRllt_@`(CbcsI{c^rUrQ6tdXgO-3G9n^b_Fbra9&ylw{DCnv@_&UU?&g2vC_Y;nd&PO>L$-I3j1`jxV6QmUtX|5CWiIP@Qg{wFB+UK(!d zcb2m67$j@X5Vc!Cd4=y zC_Ha^qgezHYOFXn_(gOS@)H-SlLYz47RuNrgXNaLu=|e` zl6SvJ1d+26*z65zmN%i9L8dp9$?@GOA@6wnVh1uS{ab~TyOP-|n5rpjTJ11)t7X|V ztJcFc28W^y2WgvB9B4V9yxn>#?NqL`PJFI8OEfP~;uAZ*s9~J4G%@Q%4V{$uq=_Ep zLdqTmSvpI%PL&RkD!i2Zq;PUot|Z0K6UCI=hOR4plEdi_Wjg+UK5tEOGm?+R=bdXa zkp742mLN+zrE|NwFKTG2%x_oM=idX%l7JC;lCq1H&}6ex+-@3us`PJfCJ$vo`}bZ% z<(yK{{)Oa!P?~gjVZ%OUOowRsNW8MTLzLsbcqw~>vZjNVQryAlxE-Y}YN@BwG+%M-9_*VrQOcgRq)l!P?4iUUZ40dx zWVwV`07vW|OyiXP-NWgMl8OKSrfldwgfbPE9&uD#Y1zX}E0mr+TGL=gDJ|&uECLlcThbKYo}1j)gj#k+H_UY<=~kztIOSx|P+F>#_e_9e*Y9Pf7^PjW zNDr^3Qg#|TZvfXxt(I6ZUzy%ZFtMsvWRqV`Pj`_*HGPZzloH6 zZ+K!wYlG>pVg$asXe-8mWu>B5w0xzB67j~2^m$OptS43G5J%~jlo(;@3xdHQsFp*V zEWwV_m?R*dMg8yilSo8FFYD0blx-4lU@R1MsVIBsp5?E0OG;UFR-;6W$Y9?jxLunP%rOFhJ zvq>5Brr9M6aG#(Bx_Fa?)AjG?)(v%cU}ZwSDN1Jl1Zu79?;lJF%7y-$DO;I8;MKs& zA2mvifGa2p=?sO17Z*5Kjw|H@{2gxs;)dce&@BHEr$i0(bIAb{qIsFpd7!!fnK&uC zCXjyt*w6SoqZ7oOR*@#b6pkcTO!*rw0QG+fSm6ps#j}m0Wxk-)#$fpd<&IFpyqQvb zG2%cV;0r+Ku#!LUGJJPK>LfWSSP33sMu_MsmrI}vSg zuR5Hn`$imVIbzWLG|jasyjA)zh*=88p<3b}18vD)gS> zGOUC906^RqUT`w8qNt%VU|5v*>$WPe-l@KjDS~L6vU*s1w|F$YjK601YpRqF`;+b{ zXWxpUKNXkZ=P}1#8D2&0l`CmSsVMLBw@(nF-1LzX<$Gt8C+|g2FD3AuVmYa{QuWSK z#~+7E+4q(5vCWjicZ+F`vVGKNv@5UA=xD+uJmZu}2g*?5C$@I^2^|%~^lB-Y6Qk*fvUOqt^-#*tvPo_6w*H~S zPKrj3*B}4SQs(3TbCi-vUdqu)K5)+xlt(LWlY`TT1HP{_`~;5bewDIQQ67lD0r*P* zC&f;Q7D1vOqW43+t!`PglwAWbz3l3K0-OnT-R$a`0*?wgGj~`287vi!`t< zev1(lUZLzhlC(2aEgP*rq8x}7FMdd`S+Iq;*D9gf;BlsPjJJQ%QMzzTimJ7lDM zrWDPHZ1*W(iZO@1`Uk8Dts>zS%If%`q%I@=238vS6pWYQx7yxDvJ76Y;k5+bWu;|$ zI{l>V$N$$TEi-l_YTnBj?Xm*-qTuzO@@{5=M-Z^T{xfxKcRSvnSaJ2Nu57KQ2qpT1wVmm8Zt6T`457?_F4T*JGxSKzQ~27W|q{Ml10X>|Ai7d+v^o8T0~8W!3P-?5)cit zFtlU13c1#hk+Q~Cw@<4}h5$c#isubHvvs*LeRcwZ&7Rr)Rw;Pfg~8*Ks^d z*_*|v!yGL4VIXN!v{0WqBeA0DlGgcbW%`_GkHFDVb_utsxTmy1gf>}!Q})dHnil3w z_+SkW8*tO!GQWpwfSy*`s}oq>4>#D{!~WROZYJHtj{n z!uIEaifG9RHx&J&?3w3JJ@U@XgM|%Jx-Br90=uYU!r+4~8JEa17#;fLO*zKU7yap1qE$^2RI; zmys+l<&SBt61zM=&h%HhE}sln|9*KKol+{7o3Uy%tyo7SDSK9qq$Nt7k7vu>YAKsP z_N9;WzWsO{5h?MjLK5@+Ev1oxxk(PvtaLY{VO4iBT|zZOt99|$ z(IDnkZ>w`&yHAf0wNc#G9Fp@xm6K~q#Eh_Zyqs@FAxTMFmxCwa_mdW z@9P8Uo4m^P(Iht?sYGpTAU7DP^xfEA4j8Gd-PoQAl(LQMXp{2MXPM-u)ZA1?i`nbBD^9hx>i*>+(1aV~A^0u}pcz z+6GJNkF5T(-w4HO-AKEYZkw0O6a*QYmTb8N6D;2nZ910nztq<$v0Kgbt@6s&(bQJi zvvn5LQCfZ;P+LfOs$)f2x?=?-T^KrBmvlk2<>qj$U*zzg5AQYwVY0Mfq}{?G+Hxxx zI(Vah?!!BfJ!Jkj%DW*_;m0<;i2AFj|3w#f*{rs?bxDdpqcr*AJaQF}Z95dVO?8#) z+m2AGvU7V({pH>Mm;EuQThSLe3d~QYMEFZ9HKU1FJieSO*N9bCemOV&-(%Sp+9OP} z8jNNCTiRIeM#1C8KB;cqafe5uAEqq(dS&QW!(hwV(vC;4?T(`p zE1o>8GMm+X4KwyNe61anZu`6(lXpN~%GQ06d0G1cNbWN%@ALhK30qKO4lb0x9jZJz z7*Q=H4@;oO%7Od{<@G~_^0c8!SpG7s-uL7mAqOS%@M0`TJqpZzNBc?H1)iFG*BD?A ze}t-w$;17W1J zm!NvQ0vYOG&_4YCZLB{CpuEqn{4&a4y%^V=g|^M24c1=@3$de1 zvlKdJ4!j14<$$OtkSZjR&xKU8TtS_Jx>Tjfv0&=0^gI@gd^+=(SG|gDls(x7Ei$y6 zjFh{m8~OMkHb|?v!p}SEETAG6?OL`^}59B7NMc`HoQYFmRl$%+scW~mcLPM zWh;a3O_ZBgR4M#}Te^@&ljrCOX*9IKgI)>BFWJhVcLC+PPs@&$vnba_S<68Eto<>L zkf&u|Yaf&Y^s*RdPn3PMaswRv-#P1M~#>5wbxLQx0D_|c!X zEARej4&01RE8#e$(TNq#Npex?Qz3a;HY;m>^h)0dh;l#(>?B}Ef#P+PHHFl&Fxtyd zei*EaGRMQR1a*Jd!7N3&*j7fn1?AsRwhh$;n!i3R`&vCv{z<@7MnsC(bZ|pOp^X4m zNmD@JN4xU-N}uEY?cPUiK5Fko>#P8B4C?l2q#z`-_1+h-`ln@YYdOk0P*z#N5aIR5 zhot|6S{6{k0zoASR1{k|(ZkXb<;Au#+7nS;Xe*;#_}W}i7D-BtjFdy5H_NWP59M^b z@>eKNeO7LivI7+pMTO2lCRNq%6g6vvL8y zM=F6u3z16Z7R8C3fTCvDXf~aSqY&klQwi94oP*yE%AQjNF0YuR?6sg>q|7UNbF<-Ea3@keE;iIxpX79?T6deuLLzC(056eEVN0B2q(e+)_jD@{&}-y}&* zL>9V48S`tnX+9wQ0I^VqC~hNL1}eF~`oG=V3wZ#dx-^I^QvfBlCTuCx8b2vp^!%2C zWSj`h_ifmit$#OT23D7AUX~8N8eCsU=Uu?OV+VJ~T@ssZ#^Fl+vyrC$b}jGK)LMEg zZ=a3yIETLGMYN5d7cMpR1)WaHnzR1M-u9n02Y#=&rG-jOozWH#Dyp=nwyW5pl%I`u zi?-GLl~}P_sdp~gFVI#4UN@j88?OVsl~L!~H*$iI#n2u?L?vL4050LLYAY7q_*2OP zHK7(zq0}UA8-IVN)qu?Rf&-B8^j6lM zk81xl6et8;h8QN2r(&cd8M+V!M;i>1aTm~c;%^83^6W^B*Gb(sDW1PIpw&v!Z(e~z z?2zXHc?A%b=m4iAquFTK4nh7iq z9m_dU>{`i_#r*E4bi3%)#09O@&}v3Eg07ILFs)s}IFP1$+KeQlj%6&AC`90_thne; zj>^u9G4eex`S$^CvFYIz7@@>*xq%O%gXlrFb>XH@uUZ^Du z!6`<0_YbpgJ+-ynv(_!4mbH**xUveZ!$j+n_G&BEjkiMAd#GuTSvmg4KzdoJf2BK} zRx+=6(JRW*D?QxQWX7zr?-H%tztV{wD@j-12zB;+mPVEZKa)z3H;xt%rS2boa*|^vwP*-&g`B~xQsslg|o^WyjDdx|PB<-vYjHZBXqTDNsBvt~i zwT=xyPd2MCg0gC>cH@r*jd|ZC#$(U3so2S@u6%UO?BW6{&iHduwq9#P$CUDGd2~B( z!(T%TG)8f`=`UZYsYKiiuc1oYN0s(=rRU8KNFP_-d;`<_y_@|I6T97-OFt@SZzTj? zb_3hUI!#AOU2lBqDNnYsHCTx)_wqdmMg=4D-gRm^^dE?Lrc@**mkmn)a(}F&CYQe& zYTiWITW{LL>|?zOb>u!Ro2-|VE9Hw_Dlp7C5QUdA{dOK*Rbub>2Noc92~jzt{pV zIGO*jjchonoOn2b4k_^!L+XU!AQ-W_(3xsjc8AC2s%i>xw5%;K6oukAFtlx$B_J=q zVj*El>HLpBby42_Cz{??mj2TLdu4Pw)~CJi(RBS*oBE!0-wyn*58^Z2{c5x@T4^s zF@aU#7-3SCm%|0n;g=p7e3bX9KBQ?%WmVYHW>lw1NJwI?!7Z^OQ>-$+s$)rp5vNMQ zKVLS;SgDh>!~rf`jFX`rlCg5?!Q4uNWa+kaGQHtCrMh;ublYX=IeIJhR~KyuBz3K` zWg*xSyKiFir2_T#n=dk06+1t3c??l&mx-<#XxrU;h!&E=`&j95KrIU4Gy}a(gLm&S z&{T381h5hQPB_oG8Q7BKZ zNgb$}2J%}?x+~vxT<%5Dp^Fo=<#q0-+TKv=VNc5qXQ57`wekREuj7_RS}fml z;1fpbLdQ7N8{9TFflw1c$jqOZ$eCWzsDO(d7mM=A|(HWSjmn2KmCsoX;X4%MzepHtd1bJf( zG=!i*9N%>1`F`lBp59X%TTh3{GEeV`_fvLDzV1tLE=HZ~hwSE0tw~nNxq;mKIyvvv zJj$OULT|-uLwB{&8*H$2)#(iYJqMK@o#!%t3a_;sHL7jPWU)L3#|^!}al-&`e2_c) zlQ}S|s)_}~=~cQYXOhJS^u$i!3H~U6BHcEjOQC3g5X|v9f8zXcH7U_0;zf6 z6SRw9;anrJ0-J>aAu3U@f`EE$*m=xF3auCfcC38EI-hJly0 zir0janeK9IFtu=1rvfi)X#nxf>T;-yx;qWi|CQGSQ;b`WrCLut(BmV%5KNH{Ay{5; ztpl=3{0X-*k{|yaMlI+**9)hKF2AB)NO%qxg^?G(9!6~g4}DDth??}& z_!A;oY~@dQdl;Er@^rLR&JCwXkI#T1Ae|9nrL?q%>$oJGM$=sGR+~mfy@OV&;q zqkP035!B4V1^q8ufe@J*K@H{DX6#;%A{tx=8L`#)FYdvaCs;|n6m6M>?%dHH4;Ehj zn6E}ql)DGm5+j-o+^CN^D3XHcM{XGjQ}}K#uikD5;#*f795t>+{s&iz#?@NTc*+$5 zr6qzQ>woYcOl^ig38n&crcSM->>?gikD}eJO*NhZfm*Oqm9mSsF6ACv89=S&`AvC1 z9rAWE)or3acnb=;f%yijAV&NQ()nO`pYt9KIe+ z(e0K#N6zvbxsRSBH(w_Q8!8_O8xkaEbN`pfpQiKVmneZo@y?ehuAYKHeu_=rUjfA|itmWuFNylWlBGi(Jo{qJCfWxekH)jk9zIu}TDg>eMaI-F ziFM0_=TJ{g-#&}@U| zL9>tsn;O?>lLWF$eUaUNC7RS^oG`OZ=;rX?15H4k7L_$f-p3RH4@k(N6=b z_N-4rS+MSk^E<(B2b8Y^-dW06Qddgj2kF&J#^5Ylvid zH1$Pti3|z)R3Dll;a(RMCa9pd^a@nG`o2-4dj0MA(sp_{O0xsQj$?ORZk&v?Ba`Hb34AjlOg1=h=3o|>zKXy>|0?~Zvdj}tef7NbR8yH9B0S|?v9GW@cVTdTt9H^BsfB;d} z2XqMYosTGcCsxd>tlDu1^PLgpGVa{X!5^8h7?)DRwH6nC@8Ha@x1`#JhdYR0?dA~Z zaBByy7Cm+e5p9mVza`bA_I$i0R+7K+y_VEQ_I=E)JRKuwKM!h!sOP{RwIZ|o7O*TV zwhx|F+5BZIit?C(-}X`KeZCG*hxgC}r$&;A16xxw7jM{(m`+@{e`^YskN(3mT9bGE zYN)nF718{lyo%G;(&Y3`1{{rhS@-H`pb4FP&H1hARa(z(iQsc3H%UZkE@viEoA}c> zWlaB0iZ9ZiC-vuX{rQ9b{9b<^(VyRPWg@0$Cyq}7S5o~n)XMGbBQ42o46t)t-UeWO+E7CO78O-2(#zDt&X$`nCUx|p7S z`c#=LH}M>YZiIwv4!9HNpTc)U`=4lkCRNGux!#Wp`uRfi6YS9qKgFbNL;sXR+tRD9 zg^<6{!%sJPKx+z;XFgK(6mtmm&nS}R@Xdeg38$}Wx_%Ppg%cD#zb-rNSe+lYrN&rs z$F_qf5qE2cboa!x-!r1H+#dabO4Nv;p_&fGMHyJ}>G( ze!c-vN%{@v__QSmU@lU5st8~+9W36Qk0TgL;j9?KZQ$JLr&?leT1yNTvyeDTi$h(poRM;t z`*)#c9zOsKxx`Khd9t`pcY`-{fwT|uw_T8_{Df99V-OI%z%t*8Gz37brmhqh|LtN@ z7b=Ia=OsxsEjP1puC4#RgWsaJ67)0)aL@MS%+~Ro*_C2E-UjWC07)CHU0g77epk%9 zHBqfjdbsK&_BfZ!6)Z@W@A!IGif*(4gmF}F)IcQ5$9FY>mLRgc<@axjcW_*_B8yus zkwbXI>zLZR@~YSA4O2Y2n3C*mNyQ)5lookiMoMFL=|&3!*XC96CPRukgJ3(pM`>QN zcI9<=W(bF)0*oiUf<@aDG#aDQ@yT z!JgT=nR8RH2{(l+Q>Y)d)cSOXu}$I$cwvHO^Y-o(PVe)X?i8YtZ={j`gXJF7lsa&H z59p*X_vwM)RhKh+s42wK9!T?t^VuHA5F4>aPgsr2-FhMxJzBtHdt$t9yrCx|$5}4# zN#<8hhU!rs<5yuBBC-o<6TFk2r3kT7gvDJ~rN2E}<4d_>t{=*wnW2YJvNiEmXbxVLjCs@+i%Imavr}$60WwPd=X`peF0nSYB`Ov&9uaE^Z;}z zR(_qIT8PQo_j6oN)yp}v46a3+ppytxSlO{R1-pEJqS^=7N6{l0;38V71_p^_aeo2z z9-!KwdI8Vr4P`}hZf|N9D~{jN4kTANJ0Xf3POk7pS+(h_QR?liZ*XEHtn3MbY7DT4 zvqvBDO0NO1$A2Z}iVK`tKgeTlSFt_nmq4}g@cMIYoAtKRnp%D$rqu_iOWQa?J**Hn zzT1J}=QVjlz+6gpRZTh-s=UTq`%t9IV$?TTMA?n`LLX}8))edsT?(J7&7pl^ZOynz zUs#fXGy9UcP9@+=7AEFiM*bxLuc3Tb@Paf$q#uHxjl91vjrRBzO%-BlsU|f}tcF{P z+_E3cb^>SiqwX%ERZK(!_(DHw?eQauhbpTYW7iY6)-zIuas4-`LwvIjpJ{mws^d@= zS{9hQ;_!CGM>w=qyER+u>lC-4emZY`6FWvPabSPg>wTWypSsJBxA3X{bPPVbY5)}Z zJ?9Sq%zBO;2yPc`!S(ZNQ%?^v`z#c3Zvk%~h+)HR2U4W-duSDVV#`voTx*+3`v?oS zLDbJ97!C4Y0?k)N^XGR5VRComZwJvh`itWSqo+&Ue=xlG98Vui4@lt&Lx|z@ZbMNy zit7&r$T03Ul*R?V1rKS8ehLswhol;CS2*L8xcMnAI-ci}p=9g%je5bG#t5n*bhyE`mAsEqIbQs*L)|Gaq1LSILBCb=wl$ z4SgWuueWutATf(9u7JM>(xql}qvPeN-C$*hXEoqD+VC-xK0)qs_es@GVQRh6E(H8= z;6Cg^5q6_w_P^@blq=qX1x@9*hePMXIDa?-aZjc+@(=6+6fJhuw=@N+5QbV#t!-(< z@o6-dmhR3^!!86Z*j@fMGHFckIBfBvy=)o@`m4%65aes>()Y%m`mhiRb)JB|mWJ9i!r2l2)vJ{eQu?_o0HA~y1Q z&vimpfH>c zStd}h=SnoCz2#=X+dz9n^RIvN;R%#NpRnnD`ir_VO~gd|Ipe+0Xy2p{uz3jsS%=wU zNKReduL7(IJZK`)xF$Rq!1Wsd>VO8dZAgfh8sJKB(^cHNjzrsTv=zg&O7ND;F3z6_ z<(au01ROokx`wCYXG>T7T=^eF3}{pAh%Cv(oh6i2$1`T6r1PLj4SCKwsf*laUWx z#m{75!63IuAxMY7m+kjZ+wWA9We|Rg+xu#pWU}-^xv^cj4<83PobFwjjQKO?uPW9c zWy?Qs+OOF(g@%}fql9EpbZRBjVJTd}S&{d(54tO~KB%AT6?w zbsRbk+<9^QH1hXI1aWniO?Hd-KXS%bA`EkmYc#425Q&WLMOd)%gM#fEo+=JQd-UC)w8hhTD+bQ;OW~GxN0CoZwXgLZ(i0|)cwMhGa%Ks zIW(O$y;ut)3}CBEE|pbr5cSZs9VVOGoX?n?wkQPH}ldA ziiz4aOP`o=V1x;O>s|n=!<{8r(ynO3-HEz>v-$okio(noI-9&?@AcetHZ5{4Lerm5 zIT@pIf?%_M7CNXkha8%}0|=Fyb&}=EpBgvAQRg-rD?5Xs=x$fn+{&rdb1MsE%N-oY zi_R%kw&XP7Ml)!zTv)=(W>6i@%ODRqW)`2ALEe6`AYfC=fV(>fjsTPgU zz!V$0+Cgd0?f>a~KUZi~u`~NFC!R4P%xn)o09m zX&6}mzj;L`&>RB0=i^}aea*@pp_cNljkt7q7oS2+F=yx7}GV3 zfx5rh`q-yoY_h}1(=k#tj497ye5zqAw8L1YW3imi zQ!%`|**?e_FuNKN1gM{>0CU1&lWol)()`Zdaen>0MD|8K8bb40J0$QRP5USmKj zRL1&VJrp-uH%P>v`pG7T5wK1U3BV18!Vk$;JJ&Z_Eoh#aP5tRIcl(I^9Xf(juC<(u z$&Eos7@^3!Rbvd7ER8@znrb5Y6ZcR=*(RdKI}yTK8p ziE95JII1ejc&`8BC<|dt!7~tjE~6;NgZO=zL&ex2qyhYkLP?&p(p5?6_Y;iP-BrBW zPxi))os?}m{xVwE@#Jizh7zC6hIsmZs*A_e9@x)|r!9vr#Wqj{ZkO0gq&<2U9Npp0 zOJOW!6E%T+gyVe(#4iTTFA_+4II_bvjl*coe1Z!_7F^hPdll7o z(d~Qm6P}VyZTZ|P@^dcGN64x9)r<}iPsij5N%_! z&Ql-L!BzYuLiTps{l2EUei+jsF8_#vdCO{Y4yXj)*LLIS2%8pjpcnxMSSZKq(DZ+g z}?xE zvZj}~=f;qMvd~L?jA02yxrOLs_+|wX0CfzmbsuPId21C9P~d92rt{vV^p-Zga|M|j)B;DU^ajhSCw~9QzoqA`_gsMbw^pd0NX}diRMpSr z17>#50{P7)++_vGAOA%2^gYuwPtQX-tkTy#{hjCN??G9N>@7T9H2RL4@%u1mF2`2m zD~qVBY|@ADhCYP%^giCy`{*_8-(#o=e0vLc6J^nd3!Yn+Ytf_&eyh>M#EqEx%Dc_H zh%wE)cabkLdHb3_!TkbkvFg*zwq$*pF|fxPGS{!1s(0C3Q`jzCma*^Bpm(_q_1(Gr zQ>>xyapoGj<5C;yRyU4#`dXYPT=M4CJ8|ItEAL-R{tYakt9F~Crq)@>i3yf9?ineG zs27WOxRQQV%4j|C54-QeMVwHsvyOhjmR99DtOZ+e{q^KuZvyU4E3jVC)t29?cpiSM zgnw)#rp;~1$V&6^dUG_7Sx@GAb!`0(jnkSBVS$NRH5m2weRk*V>(NP9F2TdK4LT7W z#00S428wbC`lX6PV9GtY^9Ec5dw^RxxfE3IlX2QkP8$$wjWgwzx|i8zn?K=+LOmO;+T5u{NwzE$n z2cMzT$Xima0IkPjU&|T@Z89jl^&Ev6k9gx58tYfK6fc4p+QtXhlg1=sgTMH)18$%i zESHz^xnC%X-~5?sd+&IN`w5S$nuyK5;sWs=uEBC_DKGn(8p->Y^0A-cXa|?^)t_mE z-^VJ!Hu27ZQa5oi<0#IC1kUPZJmMGX<(K{+9Zps|?Bd<&1%0J1`Y2(_< zB~OiZk7XFdII@VZ8>Lq{mTz*?>a}eOf9sbk_{(4Enw+tMSD&RoXl>tF>gd<#1H3FB zAbAD{N@GJY_J9O94_F;NlY`D-NPjNp=I1CvzL(8|&rz2KPC7h><{2C-jad_bZm<&~ zzU#Bm0EY;W8rx{Jp2-)_QB;^WBH|-xs}!4VA^N$J*hjvLnM`b}Crsj~^VD80p2K6$ z(_4O%vxPpMi4X6IsN$Qply9G>)$-ouyyQ2!8ZaOCWW-&UR0r^l{m^~*BEfFh@h5ow zm$NU>YYh_SXrr@nn-9nkr}W(OGVISm+~9Y#Ovse7mjmlIv-?E~YlO3;?8o3XY24;#%AN#b4Ds7P&FJmk+WQUiJa zS-uGRB7;!d#hWj+AF})J)IREI9VAo}$`={PQP}etWFS8w1G$Th2SID;S)TDb1%=te zS3aE8?>IoeU|v70Tk=L9N61Z=mialwFWdiaKd- zo2?mGsEZBTe(zztIL9c)I~fxZB%1)P3R-)DKlLEO$p&k(z7ANit$J616(H}xT*{ZT zkP+j(Nf0nvmocv{CcmgFK-L)YvVO=~n2EX1--VhQs9QAvf+CxBg;@sB|w_S$It zfM*;hHBZ#E42c9FOFNF8hDXad`2^jTr{3hICn?B18`o1NOBgJqYgxvFPf{JQJMSd* zmbYN+ClO3T0OBGg?n#^FVtuf#dTwhEX$-pSkrO6aR;EkY*I;la^*!nUYdm0og$#Vw z`B*A`Pt1L6z@9b?wd2F8odtkfioxwX>~9g51MlG*es}Q1#nM|tLIM!Y#Ac?S)fGb$ z5l$U$t$+k=ym|~BhDI^riJi{N*i8{{>Rf`~Z^vQoIuNs$!_fPDppe4kUO)4tLTdEP z>LHI;?{ioYB}dr9H@k0d#fcTa!0Lt3y!10KD56IHviQ({!D<%oDhv@9yDU8FG=({ypCImPgdV{0k=sTb>vk-oh7OxBSMsznyuy*VlNxhj89BRs zeMYn3_8_>C%Qs>g{=OzZDx-+NgLpA6+orYW%s7;3FPJYJuj%fY%#GGA_jtrL><#wa z&JA`Ud0caicFXUK;8B|>(5p~tsAeUYv!Q9s*(b*Hg1^YmV*ol^3T+E-Y6qScaLIOT zW9~->s@3$?-6*G(Wf0JIkLT6<$lG%}+U+~Pa+lrzMp%5gCb#;V8o5S`m-|36!NiMl zDa!Rkk(Rey&EhV|W8`_+YT`1W{<~V@@)PJ4;#9qrYR%7<$&<1*&D6nDr1KpSN=q+0 z>=7wR$t*8R1>S5DhLsQ8G+cEGk%q4};spF4=o}o+8;{UiJnsNb@md_kK}W5Fl`=fjhT4ND+?LL1`RcKZ=aeFrF6`khkeeWL3gL$Zn&cA#W8}`!92s?{TiG zFRudc@{I4Xk$8{;57BN)G!ut-f zx}|dBpA_Kcu4u6~2Je%`a_Di`%7d{w!$|*BhV{g^e5@))?;Nz_LZI=P7){ooJACRA zwX1$h+ki1yUGH$%Wn?A~mhA3ynW~X|Na2(}D8*qOQfc1w2i2DAFX0n^An?Aqgd1I< zuoP8DNDR?uVX_|7Mxie?s9}24KBePp-HXFxF%y*4=yPR)MBFztDPr*9Kc_U+re z@d|9S^c0`ELY<%S*6}t+T_sESQ)WYNYvD~Ksk<;&?bgHFhEsg;DkTL!1$6!wpcdOU z*5X!wQY-K2r>a=Y)FKG6`YkCR>o*o&@+UQIG-L!=M!-j^*;ssAZ3fbQ8=K-_#`Zf_ zh!sPY#`2>-sgYYJ;0YyT$0S=)SFLW&`l>a{fI=l#Yzx99OsSlr5NyKP=->TQO0s&*CLp=|+tk)urs_(6?$uAAXL7P46r|@i~o< zZ!hNNUm#qLoXmZ{poo-hAL8=;OsRY((&iGJBa4Ko%t^c}N!AcqYT6i)r{qt(iVMas z;oSIe1k&19k>9vWJ1dZ8SKy`DyY5o6hkuFJb#ErI5FZWA`P~u{L zK2{GOFXm<2Xs!I)G;Y3~l52Iv!{T zgC6e-Lt%wBKc9S)uYL(9JLbxsdAQ|w0Piu1i6W&YcS2c?TFg`Os8uV!#oFNSE`lfE zI3Hr!Q4HHOqCQmjnqsIyIC3wniEtDz)PdcB>wy-)Xf;h7xDD2j~qmwo^5d64BE{-4-XDv(kKz*Om%X+$&mL=5tLCX@77HC<*<&U&1VcuKX+!h0((YR#M z0z$S|;%NjUp~MV4Uz8>E(BIn(0Pgcyf*%C2gBAn`l{kkQETvtgT=B+NnxoX@eN2i^ z6=X^@iN&#(b?XUDM+?x~2F_fI)NPluy2n&)i;$+SreW`DYBIk2ziL`?UENrc@8yVG z?S#B-Fh5y`H0^)X2h!7uekNIsYeg_98X?gY4i%ZjDPL|58)E z>)OmV4>Q|Ru~daS;CrfkWHJdQNTo5pspvM&M~v+ooCGUy1o)%@DchPuttFz_nM~A<%Jnm+=nL0-vX9 zJ1OM~pPuL5=BqQpr7@pS{%`leZLq(&!Cvf>gq`P3 zd$GEQ1#i=53afFrSIf`RBrVx`FSUbeND~dw%Ic7 z%OiQzx75WbUB{bE7@_tyvX`|fQe{3g*AVE09JxP+##xu(Bl|}3iNDA@dDloB31;!sfmHN_3OE~kMd{Lj*0NIQp|K>R@(#o=Yl8iK0@=5R3sjy5QiMBak&^N zy-$vZ=8r=PH6@3mhk4)t#~P4dIbKgkULW+QBfge~T2+SHYU=66W#tHNbq$ep3lbjP z6m)ePtx4YHtp-_!a=rw3rRa>`he zCYL^Ru55o=yygUkd(4xioiDP9l_Rtj!dTD}b{bkstPsMu^ceXV2chykNJKOoL1-TO z)HcSCP;Db(6!?CTZKR>zwp94;18u30hS;Yq6{6gRXnwf^VB2tOCs|jmZBFbBP@ytM zgyF;F=T}?h&S=d6Y@*#-;nNYq2mA7GhbhjqO%0xQUbs^z3SQWPQwzws&gXj6bOUkz z4}Co3me;Vl{p{`M)!}Web4~Ni{lEUNXL?@KJoEVR|MkqfWjx~>Iv@uP{BO_9cw2a8 zFV~=Inikr+^NDY<4d4cr2ik;AxCHeVnUlMNxfjX2GwSXAF|+K&{@DKb|N7&oGR+?w zVgSM)FAmcDan9SCKb}EZC}c7&5ea|vM?id$KaK_^XaM=LLu@|AlyX({VezV>;f%7vS|l zCL;XK#^^yiynX39;@dAkto!}H5x3hRey-#7dja0u=kV6q;pOOfopro)J6%|Rc}^8e z?GTsfh^=4H;o#@+=Gx)S*70IrfLC~|D*a!gnQVvnzK$6F0>sy!Q^iO-yfhup^a8x8 z&*Al-7xT>6`s#>Ic;bBxt9XypITU~RoPd;s59}f(e~&$Gk(WbZf1DAwy-SniJOdxN zi?ac%`a-%;a(kTgx67?6AWH&1_#hPj-qT*6wfW5B)wjtz&>>CBR|H&5oq>Ir$_CDc z<+Iyu8eZ>!9?)&}B>ZO~m)ru!eeU6c zc^f`{k0Rsa@m8$>sWQ~Yt6AFH@{dOsY?=w`qJAC{u@|+kReSMUWY^0Iy_fcQmd)ZR z4`>GNcZyzOSL?l0PVEA*bcR?Ama1x64Ab;N=$tLw>P=lL%gke z9!mSEZ_IPV z%#NBM2R|LK)=689SVKEv2|BS-#Cna`w@)RgAx(18h;4n2Gm}P4d}hHWxf(jLJ%U(P z1!dt@d*~y)4!a%iC2HcD?4*gydQ26U{No(WiN3<(z(%G(%sWuPdw6=`9^h{b1uH+aQ$0L?%%toKTw-+c=N?a}W1Y-zs#v_Q zgIPRFOZvU6v#)5gcpBD26R^ae$YUz;&4IXl(WM!?5BR4*vNBTM0l75ZUP(UMjY zohwVb$Wd~g0&Z1B-sTjwUu4w%#YnxZzado29HzdjjB649(EBE5K>WLRTt;Ev#}sWk ze?;^q-X8a|%6&3ZOaR@a_NLwbH(5g0Xv@bfY-TF?K%gDbIRQ+9|KRX)3ebMOy7C91C<<|mcZ zpk}m6)M$+c(W0Tmt=AaLJhO^AnFbVS_u=dXJC{qU@Df4SrM~h@+9)71_Nc-&4qiH0 z4mSSwrYhl3U~5g$X48fcG1cWI57f z8@6A>Hq1b5TlRu9HuGdz_J^M?mE~ya#rd-AA#liNRiHQV|JUbTih zyUHDWuBug7RpWlwJTNRaFcu8Pw`qQKG>Q)@wX-R{9gnFd8(qQZkDy-cl*9)^$(OfP zlU-~eahzXG_ThJ{%TGVK5v*c401I!TRhR49MC*2mZ&Zh9KLRcB+JMHXWSP&gHDv$h zlT@y}tdqcK5V%pBos$0b{iD%3=U(7kh+5oQ^BT+z=8*R?2f3ZCrxUo6i1CCkKo zUgjuAx!>)hS;Adh{9HMRPoU1{s#*uZPS@D`TnHBVK4%5M8@6#_fIN|vnz9GoVT+q= zj=G+T^avlQ)>Lk?hL${AoY>!s+>kHsMfQAl^kFFBM}cxvhbxE+obi>xNB$;*y9CKW z^*c&ZmUB{^C3grF<%TEZ=FSq&7Wn6$uvgK$wq-Duf64d+)S5O_)SJs|%Hl2Rdv0=^ zXBL<5DmtcfqWzsrBy&CBqt&Y-U6_-kifOC8rws!AwmjF39{El`B zVKh)yVDP0t6G2a0&o6ycwNo7NaB(mu@j|0qS6=uJKQhWGa=)J3pr+hN?w!wF+@QDE z3|?uHqauAk9c#KQX?z30H?D5AwyeQvrzh$+&GLU(7hev?SowDkxejJH>@JvT2M2n} zaq{hfJiuG_bE|+;3g$QB`3g_=l%wUp(s_nEZl)gclv_|guJn}0QFR{U1>`SzzLy*w zxnkgp`&Ce1ijO+m`aSQ3eiO8Qo2dQLIPPqe{XM7X-A3Yh441z$?yK@~zNg9O9bN+{ z-cn2U;OUWajC`?zKaZ4C=nbx4Q;zf7cu=1@3p}4Dl;ZPC_0zdaUA(Qb-a|G<8vlb! z@yUz-k>7F*1+x#ofaFX#~OMT-t!(mKQ&3;n%ifA=wZe?fTW zPtp1tBKlK>ktl~&@QqrKLl;i+fE-AK9n7v(hL`>&huSlEkq20FA_lhdRv)nX z8E^NOV^H%`)|0b5W)&PTWCzl7pH4RvaPoKGXEGL*Wx!n#9Q5E z0djS&RY!iE+Xl+U=;fgLA_HB5diZsrEtG$ELBB8C`5^DABiE_^v}Fe_(AJTg%ASWf z2zPWH-k%QV$eH0}j4d@kH8e{ZW}vcgLvGnD@pKT*T&O#9p>XDs0?ATc8?U1}Ue7k* zz}}f14)VDO+0V5-#wf;mXPSB^*!!=ZqKs?_GO+;XqsiEizRxo};rMB~wZ=^6lt{U+ zyyk&wr1H+!Rb%k`dH;*8^wu;xEByue!iz*yg!<>LRG$1Mf9``z?BjTQ5S)1Xo0^q= zg$N^<9)_p$WYub9>oiS4g`rSTsjvKD)X@LvX#nc&m9gYE^`^YT8%QdizEWUZ7A`w# zu^<1I%x`=Hcj;y6b*|&S)ucm}kKFJ2Xe%W+Me!O>IYgi98Y-iXWG>A1)(zN%_(oYgUAG4`*fiWd@s zJ$gLTR}YYReG+#HkfVHWBgm|IF5=dGT($EO$BLILioNC94jE$S?{&OBp_{Rv?97eL za!1YxgDr1C8WW=4`&EN&mMz$BL_Nf}&1TEz&g-^(@@sMTyQ#h43eK~)53Ko}{py<| z4tQ%2+rEyn(WeyutN_BM5D6@pEMiJ3GmwQJhsZv%pDrJxDj&}j!HR7rf_yT+W>;Sr zZ%+(T$U>f~UIzEP*Zr9=L}tbld4w;r`}nE6%vVlf=P;PX9pnrz8rOBy+m9>syk-_x z5B!%|xSiL`;%-;XEJo{5`gs#LHs$|k7BrBjM<7P_>B|j5UEb^P5)*HO#g>Is_Dz$_E85JWe~{!5r|#?kFjr$kLd{eKWFBg zO%}mQHW3lYCL$stB8X5VQdPGScSR*qMO8`BRyCEl6h&F0Pqjr9ZL;c;x*TzhyC4Wv zbx9>ug-Qv6b<6KNXE&Pmec#XL_s4$r%*-?Qc`ozJGtZ#0VtzFcp*KHt;Q6yDI-YB( zA*@7}r)pzDSuG~t(x!y5A$a+R&NXB0pocMqvo7#1G&r0cH;;mirKCz*g!co7$z5IB zXo_ymW?O0x`p2PxIHL9+=xB|&0W6GV>r-)a7N{P8E#eq5MzBb;1%(x%FyR@&VY%XI z3!wN2%-d5ew+I$sb^}N*m$nEIQ513&9IGa+ih#@)PQ?){u+iB8q8d?!yY008?YPEY zgcJ09)FpV_Cm&I@2#6)Ak<7z<5s^SwXOWJ#h%V8%7GP*w;7^W4nNy&#!j=7h-q!)1 z+$Xn|ERfLvYSMx=Gyf<`HdHOd!(i#^}3}kg5Zd^fW@1k3+O@%7Va7K zzm&gz4>gEn0gd2=#MvE~xBaI(-JRWe{2{ey$p(Ov&uz(un_D9~A*iw~!cmUd7Ddln zvV~@00vcnfI$ia}@U>zqm2?!1`C%gv$MF zYYJ))G4ThAZ;urlf+9q=_ng^QAls|7ygeHZ?>W!gvv7GDg>_(o#(sZG>8WsM^(qbS z!2D|D+(Gbr+1eFkiDq_S6XcFm-hs6<&2uLBAVG}vC5r9H{Hpn2ctrNU_t3i?SvMCi z)UzAI+c6ayrC&R;PhbZa9|NJkGaZUyfo9?MwFsuvRnZqqGX^V8q0X@^-1l}L@Ro}) zS*O5Yg|H-0B>)rs2==|#$r{U6S{Ur^9tOtPTUP@%!REXq9LjEdM^zW|pGCqml@KHK8F=b-op13P62Gh^|Bx1b>-Q2cZn7Kbr?hw|f?S5$(4a_N*M z9;=*AKmkGTqSGv2+ zgXEsjpHzcZM^vei=?&&ZJ$ka{-j5NNiX&D>bKPxaz3@H{ntPX)_GE#;(wv?cg$q>L zlld6W!n8~jkSYpzWZHmW2Cf=7@_O37B=26JZS7?0(2I35uGCxL|4R;8doeHXvChnO z@h^N?js|*2@ZJTF1-)1tpFBZc(!E-k+=E*6W>ewmE4w$-%$v{@*EKO&0W}=Ytrv5n z?ORHTN1GIQoPutOYx(iaMfNXwqq4td+jsabfn`zUBkem;3i&U96tjLjwOzmhSkMG| zYXRitNfT(t0@i>TCeXzNtWoVWD8K~HzNP=0ZC|A@5A8u8_MnD>OCfi)+r!yuqa~@U zoE``Ylavr{6_3DAuLti+i1QazCpX+WM=Kn|>ZzE;$L|Am7SW*bEDFknMdMjtd6V|X zcy?N5hem1Jl9{L4%I`J3v`tAxVJJ<|U3XhO#07}$bZ%3uHFsOD%CLW!9_|j`9iX$X zY37fxNv{cstt42@f~SJhuJN_0`xIu86SQ$tP^L!g?a1GWFq8PrcEYxK=wY=-oZMtIu|8L z4XqMv6Q_f%?xpx;=7WG%8pL+4u1V_KN18 z!D`Eft^;I`XRlN1RjiM9O+dszu5idiLiF;m)k56LC8p8s{1G6b%bL82=< zO3}p~g)c5oTP%5hk6u_P`g<1Y7Jw{{!vVa7LCN0(q2NX3d-V1`?fag2^)JPSrFdR! z*0t4+>=#8?I7fmjuS}i0d)Xd=&MX!2;2@$fPZT;yPcz#VB0dLp$O3*e;u3JM@CAjf zW*tp!Kra3fE<9|LDP=VawbVlnAzqKczn)8Y#zd}>dc3Etj+VEY{l(?cl$?px^OV#~ zHdc;ygig@DO!T1#oy!EL&LcGooO;DsT-OVbtzS|^7S0CvIRrb&FWpmG*FfF(b{1>i z>E17nl<8|6y5CN19j8p9m6fMWt~gH;m%wLy4{w$zbO2xlw_OB%W9zoGVgL`I$60LG zpl_lb21QfR>r}LV4FFQ7OV%U$ffVdv5S|2otJA7U_I|RoMHDg}+m0gr$tveJ;wFhW z{HFt6z*0;j?oUnEu|bx1P(?qqO?h_G(F71ragRzgP7HPoa*D$-cm^So|H;#3_A4H42<+haj6Z3E@XyeEg3FsE&y@3t)J9-{Z_BfZrKJ0dc zJK}G}f0LM;WrJi2_cQoH^4Yq9g)8u+=Rp%<4E3AO8T`-i=-=q`Cn662-yruiCcShT zEHoTcvVrwrbDq;%KeJu*dj|8S>YG@!`dJ^ip`fmt*hjcrzHbv&5oky@R?%Hb$wp`f zswss53myeTa8`kGx3fhMCxr6#|1DV-KY1=^gI#BU8)?Eg6 zXxO&Rd|IW|KHJgiPkIZF+=I76`jIbFeh%o=St`pxIY-E{0|gAAv>hNgUyykx)KV$^ z>8%>LMxL;f-Bv&CCButa{4PjR7RuR$K5il7Zq}VW=|?+uu{Xd6*6wC;rdANP6PVOe ztag9suy2!nH|pC=H*2x zgYt8kpCudxX2ev|JG{;TI@26+jyrQ6wi@KN5B#FyDzW{nk*WMD<_z0bvBrd_rhOE> z9|v`Z$-1BQG93}Au(;P#@v_kpD%;OOP22wyJ(I!?fMkD0oe!{Z!v^RsGW_W8y{rL! zeSppVSA$*ay=-tYMIVH`o^cI+u3l~>#k0)bwtkd+5DTgqN}BSflr`luIqRbUDaWx( z@~}0g2 zEtpmT6t>;xjWcd1$jWrV#>*5K0z1%lO=K&p$lJ7B~<1XrX457`GdnTvg4o=<4HXMX8jrk;jiJd4vxY39eb9Z41Kc#uo!V}C_>~>EuAMZ0_3ULSGC~}s-Fx!#a)#gRTCs=6p8qPv; zdh2^oZ)%>;8e*H(KcDrj8HV9Jr>`or?Rjt7md_f&9Y|q5aQPUSPvU53cR0QH4EGk_ zI>`*^#K@D(zei#OJmI!?VDvLDYtc2l+;~7L`0WaOCJuZxt3Q-cg7@r2vlCt_rUYu^ z^#H_)`@K4bqKn^B!AaIPU{-jQX|0l+3UDzGVZEutE6`3QoPxacB_*H2P>!Hwr!aU2 z0g}ok-FIjVR?o*GtY9d5e%Z%0Mw)UI#@clG6l*DWC(~)xrDYqvuGBuU0B+^1SCB<8 zndr&-Sh(Ao>-Bor3VXrCU4LC(|7<%s9jw65VZ%A zZvhUj?7isC0@ld)j>sP_*^83|K{ea@0Xzoa32=|hX?X$2_DxdHuuxw+Aag;2{TfTj zv8vRsqL#=dWHYnPlX?O~&Za46Kvr$E^bDB7Vk$oax|~L>&O%REh_RPmRB90%8apec zoW&v=P0R5Y-2f7?IC>IT77I)o(#)~w#4rrfzx{s^X^CiBKZJF)65!&g9NDXNL;J)` zJbHr~{KDFrW+E&Yicnh!m#w{N%rD?R!zkw$G}V)?|H7uShha409BX8D1+auUap*W4 zLamXOpF?kejOSP{%ZV^YYtH@)1>i#p+g(xZBrW7uh}Z1H`?&dlvyln+9bEMN9&$Bp z=x^BmVjnd5B9?{eS-7138H%Y7j}Q`CHjUO_f->(->Uo(x^{(3!GjP9RYZnYfMjS85 z#7|C>tge(;$gUapKuc7J%SowA(#qT^;dkcI;6bRIo(EI9*n?7fqCuP^z;|^gDLNfs z70qbz@9YJvfUQ@+;{VnPuYeojN^h%T=!ct=wU{-myRVHkbB6olqSZ$0_oz*5wk^N8 zTWe5$G4pC))*bBUmXiUFim?lU{~qE>qGBCbg1CHyw+xKT+A^(Wmd4H7i>Ko878G@e zELWMk5{E|9*Tu~DWmPj=|EX%ehxHE{cNJCTp&0)^|6SEFQI-2YRjvI$s#;F_P*szy zqKH4FEdpUGuZC|!TqK6G$fZ}-wQDZ82Up*AzdOCS$^v^=_PuI@hMKL}7vYZ8E7tzN zC)VE2O^^$CWkxZQo4nSRY_<*)RSk@_KOGWlAHqacKDIa%n^7Qb5ncrxDsvy(tD>sD z&VfKx5Fr16WK)BT*P*ldn`T|dy1u4mUuWYPHhq>72$BML!7VNy{fVMTZ`*^{>0T+@CLf@zzi~n^mE!L}n!ZAZ?ywfhX;-xL=^bW?{TLT?A72@e zHBc|kF`4VodjE~i7Gf!g;TisVm4V${$sOz3+R(7O7_Tr&yUV;RA%H6B>rCwerz9eb z0j`vGu>rUXiW))Z?y`=)#$a5Dge|1#QgLXE{S_$izDufOwGWT6Gm0oL62a{@(nG01h#aY${zu3>Qnp2>{F$-!P=L0KW6?Oxpl19K>!6U4**wD(5n7a z_878I2&s0|Zl`!V^D%dVHc&8B!79q(H@pbHYLq4*E>gao)o)W)$6666Wr3HSzEM<1 zFOi`%QDP7lrUC!HRSMY(2dNqOU4;oM>u&k^W(5@k%|$~x0L7jDklC;x`%GB>}$=so*JA_UmMR2CWz*{b%4o4d~D_ zjAT67pJ74*$^4vMk#nj1IU8b(j{rNt(5jNP8$d3vm#MEv`UGpdYQRy^pE{%2)4p^kMJ!tS^< z``yw49&T)h<}^a_&B-Y9E5M4Icumwe2<7IZ+%43e@phI%wBaZ&Z##-~x0XU6nTaA^ z;NKU#bSy1n$UK~;aAbY}E-o_nrhLxZnM4QPuFNc%V72G1@Hn`5AExkju*O`b@ZrYV z0k|LoAiU9}a(DJ3oIF+D!M73enh<>(MJ6nByvtOw-#z*$`g4PlRqg{JeSyluEmtfU z0T3a_FxItQLim1_@Odg!x!1S?MBha8BRp#_K#$-V6-O3OI;35FnFY6<5&j)v%p^|j zRO<$`@nV%Qup#}|D&ZdxKJzla*|v=m4Lk`-h(iWG3hfMY;a+k9b#~!nJ8uK*hk$*8 z-)4M^&5qF1b^5b{L^trdVtN=los4f$ZxejKkMDK(4#xLbd}mU*3lDVb+DT6T96_<` z$F9Vc_XQo9;>tsfcF2OlB=!?p@5;T}PeR^__zA8Yjc6f;`~@rc&G;UNcoDvV@J58k zIKv;NRgiG?Fp^{=4-6RU%&yZd2mv_!`A6Dm7i)hJORpJui;%KdIXwm0inwCUguW^U z`SzkU!uf#s-i2?Wv;s{saz9YteJI^G1Sz5TJs2BfPXMH7&}uYDbT)|OYFIA0)V>-I zciV#UCqW4*P#dx}qHwsIRgFi&DO_PSKHl;v0B&OqzK@C$o;nsz2oR!iTAk?gh(89y zQyy*}4X~n}F*$W_3yq;-#rbLaHp;HfM;W^!sT7dQ$x?$8I0CJB1_Qd&HF!g%PAr~N z%4k)WYP<1t`A=HwhNhjTVmBTNal@@9-w7pqUQMn+Oh~K6XBdYB!AKT`Nff)z#hv_X z^ZJ&U7}O1fFYWk`zCHjpi=End>9_s&(y-b*5R@pbHt(yx*%t4Z(1qH3hzb>`M>$2C z_*q==aI3>RV*Gm60sehJVeY(((X}aV#iO#fDa9T5x4;j}2O|jNg+ATgx}5UdF6MP?5k8od}mVvDf|{|oUG4Qo{4cu(|8gsY)UF=6xcG|8$WZ5F;~(-aSW9PULr zoB29C)(i`>S)JQvUu@!#x)J(^ckokk4Ad&iRP0aLxLg;Zm|{AI0HYZ z?YwxLB^HVlF|&dkk`qi2?sEXi#cu$`*X40aV}LEm_|)I1_Y9O}IPI&8p1Dw2UG8Ig z-auS8{JP?Iw27mq;=3qLvL1MjS48mL znbMG5o~f<(=20^C)7R_qOX~3UvWGt%@lmM-1HEgq90&uiudGlHa2X4S5u^x1~Bkya_@F&;;+anXo*?8FiAAonNSD+;hbb(W`>0I;e1>`kgL#Z4YcLNqjzEkUr&_c-n0xW{_4Jph z%yc`L`>gddWJ9LMPio#x_&mAwFmJfK z6eHyy1QDVdR-@522yqfli5u63KLP1z)Ewz_)R=R?YbhrB;`s_M_A6Zs<*ntenyD!d zb&+Rj?IZbc8Ty{(ExA{Sx0hbz=}vg$l(~38cp`tEqjY9E0a1>}Ko=uJd^_fS@qWEfPR@%2g&H*$| z{B@({ZTLXe@(4X_!@Dud5$Y7p7vmA5bJ4sDE?M}t1;s3+__kn7=V?q^jO<}r-<}m@I)kfG}B)QkFKy3O+AyQ_3X%NDL4%q7RQ4XWon%58_oZ-VJA# zrJeai*ajrNhG98I%U{F7-$LcD0c(Gtur6pdhO7$)a60Yof>uwavMw0Mab$WOk^L$8 zbx_?NwDfhpj#&;+r>^{-{D;=68;XJcYC(7Y5u|Rl2Z(zo+TDZq4GG(iT~lo-3a{eX zi=c%{6W*o#6{|Sr6NeH(BE6Orb%mz9j-jo;p9b{AEIgu{JyGu+GQNRUT&4DJpoPEC zwQ0dg^=^g`q;$`+v%D(J-<)I4pu%wN{@0X^@9#^aTM-h4dv z*w)?{FSN2Z4`k8%=xT4?gf-hoHRE|BW5azoEGu=1`k5?&xYyG!o;PIf`{)y-)i8=Q zF0~dtApc%C+d2`?{l(D6qXUuoRILwhV*Vo+NDSWk&;?ufKw*92Zd*!S`=IJ6l+yz7OK zzrtHkWJ6NUcPfH?;hLKwRdtm);!AUo#r_ z;)%SZnCJv5>w_NV4(1;6Gws}9pj6GjVIQ8V=X1B!IY0qJ_!D^&`3~iH;)tdU<*Qi} zn5+%shw(Vz^n%PN`(=4Jzb`-5%7^pWG7?h~xmVQX>OzRkjeZ>@ z8NR7>ONAx{HLOLeSr+_$>fumpE$gk-Jga0iOs`-nAf5*~p2&USEbL|?KLr6iX9U*4 z$5b|g5Axn0ZY_s4ajOB^L@~lBMA%{A655C){+6QT;h0pI7f|mPvZ7s1;*Dk2d>0u; z@(#>@7rizTM@$fvFM$2bu@pC1@ELLWB3ZWg7U_og=HkaivjtQ!rsM9U!-C0Lhw99*&-6l z_g(bmbG(GZ$AVaUzXz@~5YOH4iLC7o`u#or77N&+br=T@A_&j>NJfL+=jWkdu#V@Q zu&h&~Kr~=pjveO|DjpAdHHtzeK%Rbs7EA!^>_S-+umUbt3OkyE*oy zagy~KhI_hL{#xloK2?=p*T!ITqsVV+<5Ex{Ox~7#hM_t{7e3>`Zs`idXMLOCX8nlV zreTTBqo8R#7)sur)A)FgkpNhu)503oUm%;|8@GC?P=hh7`l)&ewszJ zp{Hrw0!K%_(|O&x@wK70?~vuM#AIECQoK{|rqq81CSfS$6K~phmBm^VDrLP}QE|7M zunP*6vu=j6%28d^=|QOV8kelkG|Sh#JBJuG?pv&jHB|a7--{#1_22Q0)23qy#oVsg zA|z@ddc68fN*9Me;yV`K!u`4U?tpJ`$xM8=!?$o%E56&{`>ON1RTcOa_}+^6*UM5C zyUNCSb6{2=*8dV$EZM6uS$^E>uSBSBE-mLKu%XiBn7~*vt^lz;LsP`xuXJ+-5TYB* zSRiVMcCE&4A}PZYcqFcxI`mbdU7{V1Hz(`aT2s%J+{gSLqQ4iLj~D^&I6fXlDJ%Ix zutK*C9;}r4pdtP>4Iz}6!IM~n`t-X|Zf&d$`B9X&o77cUOarL>Dn5kY^nv-{ABs1n z)=`bLdlmPq{TuQNz*+bYMQzmlb3+sI{GPW(%j3TXP92APZ;+C`wElbErDw`hNr;SA z35OaoG)br7OIpat`ufDd#|eam)=>}FfInV@g{YYT-(*sc+Schpbj$SxS4!=ZOtGuE zd)R3dDUR4OxLg3SUw_=_xHB#lHX0Lksnp%(hbA7PwAFl|aj@QM54_M`j1qjKMQ@$P zAo@3EC{!N-4;#*?*6{AWZJaq;<6jtl#1)7E#{|^VcS~z9NN3;?ocn~;2ZXRTskAhy z5ILQN>)$9`jJj9`CbF-AZe%i9*MiLE)Ah9=-hSl$0}of?kkSI+--Yd_X9e(SG$mj z9ip!gokg_JiVI1wpEE3umHW{?8^0rO)3Vp`BQmzLQ`YlfQ;Ldd07`(cV&ke>Pg3@J z?(X){eJT9~>WYQmy@6D)9!nHb#0H>wQ<}R0G`T+IZQ#Gu%?{O#7a*}NvJ`c+egn^q zMLv@KE^Xb&8@1RJ;!NKsq&1{};Y=^WzZj{bpwO-sv(+`NW1G>Km38E{iTg#ILGmLs zs*<0F#MacS5%z*z1wSvSjj)oX7kk3T`aTUqHaV42Hu1XtmB0sJlq`Tj*Ixqnt8X1d zTQ~9W!R25HVx5)*SH98Sz-B|edaq%{CYmZxp&EVyZVbXgxvw7|&%mvhDPqaF+csl+ zF&OTu&!Iel8bHo$9&CJw=ma=uxUBmwIBK!-0(v(ZHAaIlKOAvErZa& zTj8=GnTxs=`&$LMED7aV`!Q&pjyAJii<7M0nY3XuZ_BD>(yh(d$K4~-7T!_4j6k_STyR@W!!%IFFDOj|Pnbtb zHJ;$D4?Wk3zup@xfop)pwZEF%c}Esehk9-2X79g#z=;Kp=8vMS!cbZtV{B%cQ_6N8 z8G5W-P#wWmK{oKMPaD9oVzvmU*gnq2A2rLg_hW;Z?r!HwGlmBGGf1t0s1Uhjgk!kW zsu*E03V$J2f{;!Te&9&~Is7$McvY@Pt8#e58d6*9)g;N92rlhG%X2^pT&N%itIP`9 zBkta{AwczZ0!R@w4aH!sq#LkCe34eaO8T=G4mH9AGmsnc6%Z>bz0u(PxgA&_?^DVS zERb=ub_Yn%O0E4)UR$m`!N(ydMLOi9soJnz+>bHeO!{mO#|6$z`f3lhWz{q3@E&Z_ z8vjf!_VPa7mwv=%NXCXzpyhlH6CKIg2}5v>mha`gd}p8;F~OKdM2l~I8sjjH2!Bk* zT&$u5Y%Bd6Ri47Q>xYer)IJwYY)vC`v3r^e`y^1F8FXDlPJtN`LK7)yA3s~K1M1KH zy`q&xpnY>}Or7<&`H|}E=ik7es!*m?5E> zYMzavZn{MMx2Ss*asc~?OEl{MkMur?5^_(wM8%2Zf(Ubz9t&NryfbX55#515zXKC^o@c8d2?+hPhnNbTW$?3x%yF%NY3&DCC z!sVcy6ZL8Lu;KjjEEdRDH0CTn8fCXzo=lGAZe1h_S1-lL* zxAW-zo7%ba(BZ+PyYwQ)WIefE;(^WnS`PHsByG{(r*Mg}x~^hYd9v6Ad)St{Rd!Z5 z$M>)`SVM1J;%)1VLHrYR(tv{_F&IMP5b4G>^z$Vyu86Cbff8M5`DIiTOS>-vTaDyh zh|Q(HmQo1rhjWH~zeCZJM$uRJSkpT-z>rb<#P69tlq0mQS1_C25r}^W=U^qMrRYG2 zRkpxERZME1`V?QxqukcPgQG5M!&h}ZT3QSQlxcS{lvhuxljl_)0Ig5-RUBUZ3dMnA zns7xG({cvks?&5*n|l>|V`G$v$MJV7ZOk9s#UK}G$+v`%*MRc=!hWD9UH^;UfWV%A z8$1Ee#*`v5gnUcU6IWVV3Z1UqRXbD4ugci!Z@r@v$HF_ji?325rH>HGNB?%{pqDKg zVF#hXPDYEp%Uxvl>`&@e#_Qom&&V>2TP>PZ#sj_6u^$p2pPMW)akC)tGZ_*AKRzMRXH+G@C_q4t7|MS2Bf)KF961eLhf-NA>Nbode2wF}Y1NBmd#rpSK` zbjYFzI}gSI0KIAF!&$aF?X*Kz^(9@f^EUq3?$(kYSymzzjs*uxmDLr+L4C4X@au>t zSe>V6?h|Z!hS9z!7{L8>T|}FOD=m-nSZwUu_jLfNGFm|XvpNue;4672G%Lh`UzNHoNxj6?N#CdJSD9C*Lj zEC@|aCLipyRv!HL6v=fk5P3+3f3AO$!OSvd41NsDWF!mA(_|Oco|>K5&ysu|IN#Iqa(g)TV0~gL;MoT zc2~UATzt-_e0Rl9sCE$JyBRUKzFSt#)4uUSTlEGkiqtL~PghM)PwI5&sB7RK76Aeh^+*6!)On z$RSCn1GTlltMH%vXtn-P|l+1va)?wg}-gp}c|89Y_`Hr$mCW zPWDp{7)yVZ(k($!zXcTQuY?+l5L^`~^-I+z`wMbGwAP}`GfqOZ&^vxW(E&;qIf2pw zlu24d@z)lgZ8W2ERHB{bq8)HhWJ>z)W#8LYoW7=x7w zqA3RJ7A*}@+L@Z+idM-Hr;+9HSUb!ef)sZMt>r<=4Y?GDw~AN9chJo|iRxre9qZ{B zz39|F8&KYNE>NpN`VeM8-YBT(S`BO4a4G!`1qCZnASc6um9gy77j!IGX&ZFniwY6~ zU&c#%=WTl(O9*>q57C4YwCrmNX{>a&Y;uB1FW)Wmu{8zgWFh2!9f|ck(iA{i6zXM956nt6&0c=OGWTKO##pxvNv}I@mYkj2MqpeMpow7>F zp^Cek88M37^+^oS1LzQ{TrqA(W?TaE*rrWssvMA^5N+QK7`u^%HB*KJJp%p+n~88h zMFHx*GhBqln$`?N262B=VKc?Yc*B`=mE>?`iFd9u`1p)t0=&Z{-9Taotq)fsgKUVd zI>CJ(BfQZ$;hSUay%5$&ZLau5e20?0b(SXT9gC?H_`D27JOa*p$rG`=uj~r1WtBe-FP3?gB@FX^O{J5lTZD zyN3wDRR>W>3(RFI4Q`?MSxx{xSE*DAI4qF!5hsLMVeOGf%LMdx%4?y-H9ZOB5t})O zi0fgSjj%(ykgTs_425*j0=a)X4?T6lQRuPbBe6`|)7(f*`3TC6RJxm!0bu69k)+yI zp}1kw;Wm;?EtTQe6DGG*26Ep=5{=KsP8r(UmWrQZL=IY%t2V4w@laIaVf*PJtvI08 zr*~R`z`|Ct6)>tgEp3IhnonwLMVR(<#$Su|kWU^Z#b*5l1ah?6)0PQD60H_DNOWld zdZ#sd!SK@XkZK-MeW;){goOFz76l<;7Scw;<)wg4Xb@w^<|YbgfJ+8ZN*AMw)OEi~ z={72jQoO3Yp%>&~ds=0w$DZ;Ng!`<*Q4<){#c=7DJ60OYUzH~ZIaixqmurO9o*La}GS9JXi zrI$J#`RugH+u)9q)tcnq zS&~?|VuA%^hF&IocTz!r#mjgOAYzr`{qX)uFSor23gK5o;i}UBa1-2M9Dv0Nv$z3D z7q=xZ0dOsro(}*n%ya;JqV*rBY*ys=HRDhWg21m~ikAYC**;OZ2JNtAgtD5chmHZ| zDerB?$M+X}3h7ZSV4?RE_x@Tqx4L^Yd887oz^Ei-3^?2>8aD=ouG8j@QO0xm2-)9L zMw$LT>NvUy5JxmvK({D)oD!_w#HMo&#qYs8$UDX<)zk$DM^fH6Wh^!Zt=UdokF_Ann{@ zR0CD_xO8w37$u}DF4g7Pv|uGr7N?CX6~89m?fhqj^~SeQ*6n4iY>YmW?zSG69bK@) z^;L%Qr(Bz!XDB|3@iM$Z^j>TT&^oMAnsK?mHg1jJQnj>MYn6?h1zw~MiApovj#f(K zLanDwna0%_+okluI19n-EXL=*X9rIgfr<)=?o-XULFsE?54UM=ZBgF$fOatdDCVa* z-8`yvWa=3@xl(D+xDqd(Y;v}G11n2%w)!D(R}B1W{L|?Sr70^ZpcffRJ*BunxU*me zPihda80fb=rMWpDP)BjZm5KXJxwvqhhwwe>8IL;mQS>pOl?^eOPKXRZ{GdbVc$-1H zk14}_=lrLPnF7MO)Pe}Wl;#j>kq~7R^@*8gRCY-TwY)A$sX~}v72zs`IfmL_ z2Hj|j9(=Wy2hb;%l@{iP01~HVqpNJnaXaTSP*tYrLS;7i+rC0f#A$k7sC2aCo{&8D zo&es6BR?t3`r}WIDbT|S4aG^$?~3Lc4Uj8HqS}9|u{7)o*d>teiZamUHKZJE)QS9V zsL`&i5fJy!DWQh!;Tw)n5%eXZTrXr60)QSyx$fHXB4re3HP%swRUB{6|Dn{tZOX7e zfX*#x+#gE2T0zIfaF}gpK>a>mCoS=NVWty*C32lW2Gi*-YPES6aGV0;H&F4*r`_;dM|P z?9TrL3qOjOsx15l?__^Bvl`z89I#2h+?O_WN6`X*wWabTJDCk`A z4U~uj?-G>w8eq?(#LFo08A^NtMN7==X;~AfeF<pi3p1*z@Skn_$rydGz~r#S3?sl&FY80bB+5E{JfI z!p=Dh)5RYYRzUWfN;|jxh<30}4;)#?-crKdHdl$-L@BqFE@3MWRh5u^gRp}L!9*F~ zqpLXtAtHR{^tE;GDBeD%R=1UK);f=#v{V`xo9QJ9IbgwUu%Lz%R0{MlQ(~!dR!s)H zmlplE62;}3lw5|@dyTTo6u*$bAOB%S=YObVM#@WObQWw-AbYB2FH<%uEcY;dxe{FF zw}(n?w)C*h7edah{il$*`2H_Pn|0VxNDD3Ek+P6Ogx&W9G#7@wPp}SiG}BXo_oHd< zGvzPb!kzqFS*h#cuzzYb^8m0T$+_DY6>Cow;qlJ!#8~^MB0M$LeiOu3U|P|%So=p> zB3CcT(7Ux))lm!{Y1X=^3*{)b|KDZ3*!SR86MPYGgkNHh()cq4u9DI(;{J$WmoiMLgK2pUbqQQQMYyTh zpu9t^YNCuSG_Iz43T;PT6t@@lKSyp4zwNBw@XR5r(RWxdQ7 zE>T5rfxs!kq(*s{@5QFnDG6rG{y0lm#BmtKOrtcD>gC-r!?_DM-~#ozY+Z8CaiF`H zvXQLLNA4DskAe&-_zcVt1g-%!uA{!fw(X_&|4`sKu#Vce=31l*qSFWek5>vP>>lc< zL(DS~;ffm>V$>_?+cb)GSKYlo5lJ)tP0}VK?stmqAp5~qe1W^#*KHtTM9B*NZCa_j z+Qr2Xu^U8VIi9iurx@y^HkRjVvwTz+8N%{{`sxjSZ)!jBlGdIAb%kkP;KNTC4AGMwVs#gtme!Es}D0WryA}uXk^-|aunh=~? z)9Fa{CqSpPRM#=J=~vK(QdpGg)1Vzb|1CJdJawC+=|S7XcB-!SS(MtELu0$OtqM{3 zQ>~z#I*rTUY4IJ^8M53?I~Sv#;%fe4sDmi$Rn^D$GCu!XXxq(>LJw=jud0w;Z;;y| z)tgpq1UEj^1q&Mf7hYEbjSYTwz#Z4}U&n%C_G~)SRc!`ci`-2eD4*8`cT@djm4*Ez;lBj1sjhsQShb)?!> zzNwks5q()hL8H__QP3zg7^h6hqfpr-x;_en{vN5LQQklrJQ|^1G-Whqpo6x1w7S_< zPNw8!6z>M2E|&c=ZE3Pvonw2sYLe>iTJ$-F<^V=E!{P!HmPzUZw{alOcu6!u#>?T0 z>D**={4G*HR5$wW2B|KBjzLh`N|Wh5h!dCNw^6}|n4(Q|^FuYV$FW(CJ(W(3ka`&5 ze^eZvwrL1ER2*g-s0m7Sw>3dYjyMn7$9hdLEyh39uPysq#yMjuneLb$ggKZ40VUl- zUe-tImO41PDqk&UWd_Ox@4l!w-3=#9<3Co-U_7%v#<=aH^&hKAa<*ogqSlhJ3AcQr zc7a2|F`r;;1-4JcEPY6YQ!%4sHRGp%#j)AA6g3iaw<-m(pHhAbU?);pine6}OC!@(cUmb<>vy}N*oh_+szB-Wo1R|g6(tt)UPyhUkWBHM6U`lae; zE(GfmGhd9Kc*9mG>iU!KLN$ zqfx9Ck!xv{RrLy)GYw=AlaiDwV^WyyTZAF}+?C#IXVoVl7s?Q0YM;-j*s4zO?_EQ` z_BLZBMCY1VW(J7S%=IsEZXn3Sx0JkC9b%d~AHo)P6RxUc9SzwYhro-~QRdH4wpi{W zSEi5_v8BYWa0!-5wkY0@GB&FUl`K)~Mhrm>8PHG)y8Icqr$DY$gvDehi8S@!dc?OW zB3)hS)_qy!?NSdoXemrry* z+nT~b3)=Y*r;QS>MEyd8zd@$2Ddii`;nykW8`P7Fye~~+0d$6*f1~<%&s{F*PJ6_J zmvAt0(O2jUu@C$f_!UgUzEwM#M=zH=goCcCD4wKcf2(#^ln~6?R~hPeau;oRhI&Mn z&uJsSSEtI2rEeWHL4wnQ=imJE{a2Om5`60qgw$W7P7;?=)~HF|EzzHtCl#$?g@15i zh6Sltn1M~v+}5hq)sWVcr1WALCSpD6St}+==|d0>!4NjDjNjyKwIjYi#oE;H=-!pl zI19gt=ptO2=!7^EvWSzVk~k^4OBI+RCrmVD*;GG61d<+2q?0z)(^w{wuoB{^)TWa0 z{bdeX=|cMH&|pp>7$w}YKoexabCc&|2D_oo?SP$7Dhx%_&H5j9~ZN!v(N6{NWOL8c2qZ-E= zd`+KhQUfsA%Qr!wbR&6_8mu-1K_?2^gc@$rlucL+Nsjd2=$uHuGZQ8qBxkGFydQo9 zmc!+O2fbM3)5X?e40skj&sG;2e?zix>NJ9u{;WoN=OHLiN#_hnlJ!h#1qp-LQY!vg zb;o{NO20w&pVc_?Sc0~q%1eSmGTlb;n^kw#jHtmvH9(uQS?w)*yC6>nd@N<|mtar3 zx6OU11Rg*Ld56ljs55vW9ztFji0$kAt!f+Bg&#WVcU){K+NypHCI6IdYDaMKoNX8u z;gn7F3ZDVENeG!+eO=#S9HQ2Wal8=Hq3C1qT9e+IvdZSCE z2nSO3b~Vs<9NJYi+7nrNf#V84S!1XSrKm#z@)r5#r~|$3Ep@D~s)nznOR?K-BAZP& zoQc=Zo{kzp+- zI|emZSjWRE{_%92t)OAjlZuv2!5pU`Y?h=x1(=x+snt#lGw8xjHA?OGmEE_D$W$#uW)!c;n6wAgATzWi7Fra#LdJkrQHd*%SY`o`Q z2sRTaWv?3SYEH-X2tbnmHsDh3UezDMRPkO=#aN2Y1zal;3Z(hDYGbzm01K2nwFC!y zv@cgpQVocDK<#VDe*F0oU3cP3^Q+^ExY>4(Cht>2-EII_WWw{!>1{RWs+6}+ zZKs|@?bZ9>YWh0dW02Zd+ z2QVPbXxIVO%Wcd=(RKJ{!mccv(hjKZ#&`7++`%Z89{_58Li-M=p{AYz4k}(Qs5pSf z((?mqusIRHFLUCSQGw3F#8)6H z7TG~Gp{BD5JH_^*muC}<*k1U_66{{8sOTqF@cqT~!67w(-&*WcKmBw_t&M|}-8ecj zURdl{nV(bfA#`CBsfX2Y?*haMSv3ZB=%NTq?)*NowC023)blVF-}^N3u}LeJ}A zn}dHyn}W0)R^uXbK0u2>@ui|D>vXKdP8oHqGKj`z5noAiFlS@+?C!Q#(5{sOxP_V? zQJcHHhgeZ{BB~CfF-O$yZUd@BdC|TjYTue2szg;-Dd4F3n)hoM3XwCxRqB`7HYNuW zLhFnUF*)ri?Wh{)7UfI^GwOGVvX834A(76gBE0pR(I>{93Yp@T)!B6s*Ub@!qt!fY z1?!VS(J98h3dCn8;-=zfmSS=S zU=0fIp}i^g81xeh5$#u9N{+*9C)A9|nMY}ehAJ`p7^JfvNEH%=*a$3>9k|k^N*p8> z9e+Ae*)i4K+`dZE7tW+Mp@WRoYBV;YW(B;zl0<4(rfDpr>uPumtTd1%A>uCd(7l4>))b)%?*k~1>QIDJ6 z2JD>AA;{oVA@vLRilE(R)v>0|h^}gs2TJmbE>jQw1=Okyo%=->SX-S_KVlVM(uQ;D zpS~x*L{V{ybuKLNBwV|~g_(I*adh`6F2;U@vVVpAxSD*=t4mBX0h!xLu_kgaK-7b` z@qOpj?&b-i07Of&H!_PPVXkQTO}z%|3-y9J!&DOx5~^6mJoVISwCn;z_PZos#Afy! zO}Pm2g1Rn(uI!@1i{MOflXnUGRFrcWm^XqtUk07+Mb^vMD-EXN%ji`;$%U$q`S5#E zdQ&Wi@^Iln3M;O6YM;&&Q3!}qiZ4{XI&TJqHz4%XS5x~$B5W2paGH@S?6ot(t>+OZ zY@;hnXo7GJgdORD)>E`zlz5WzQK$F0`3`Iq7%NtgSaM<&K}Y?&8X9sC$t9sqw&)dO z&qY`)`8^^YYAu~z;;0|A_IEXSF?2NoZKzW2hnfd5!8!^`#^!u_4DL6+fLz`RDqzhfpdsOJ@oCsFbh^$`YgOc9nA z?0<_u*xS_b!jK+ZR4=^v;HE+4O>fNM16Iby^6(N z%zUtBachx^OVleer+qge+&!I3zutth=4ZU_4GrW^W5B*dZ@#W))qCh4YL(H$A7~ts zmlUA3cIFq#VblwB-% zA1%L&UU^d~CMmb8Vd=VuO1i2x8_n?ah(W%*xZk4Hj%W2w$dukh*^{Gwn z57aPt2#S4xU0f?ld4TZ>r=<_nU{)~^ZyE#mS6W{V_2ubz(7R0!RS&o{C`1H2pqH1c zr<6q^evzLclAbrqrqc70X$5^`E@JOo~$o9;llMB^)6k}IkWj~Fi6=w_$-27Cj4BmM9fl}LXvS3#` zcHSX!zo=*>gaQ2<|3B#^nr$brM=8fLA5XEt%7(Kqb)NAC zHU`uYkGsZUIf0byZzLCudE>eKdTYD*|ON&yKI7Pse63dwo~ z58DQqD63sq=}bELNNsJrf?@@snJ=Qb%aWenD?UL*a3< z=?itHYac{Cep^iPD2)1<7it~flqx0Y-zZ_cvxJ2tS76}{q}U2@icl)6P=_>l1!YVc zflDGIB>NVf9(vd$XNFcYshOX_XXz}%72FUQDI2D$pF{9(O4ntBpF1I^7>G(`-?15x zyo7ztqLutpu)u6)2!@*B0yA_G0zEg}5yyXuArh3Xvto!cHb+^4$`{fs#W39Dn&eo3 z@8W+9exs=zHUYwouWE==S|Ucbv4PG#%W-)|9$dHzcvQ z(;N$DfHN8fQ`HR%_2T@`Wo zXVl8gFhsbPbTfoPsMzgh@Co_enOHfu=TaTFpmsasH#+~paB3RX@inP9dNInaj9;ZX zh6kFEnuaLYj|bH<^kvDZ^!GDZmMyJi2z48-gTU1{{(q+YT38Q}nq1qkTG+O(H5uB$ z4_2|s5a@kiEDix6(&oPB*k?`)h>3~#!&=G5Viy$<*dZkjc*$_hkZxW6*Q!9{$syTQx*03d{1AVXdg zliVM>BOzPtrd3E*YflrNzIMACgbRsccSCnmGiP7?o&PXs@Gyj{*FKZd=TfqVVWN5n zpJT!aasdx+%b?X2T>LwU?O45A<`ap`p99}FPTTwm9MczKj0m^(8;|Iqdd6(~ zCVxb4`y=XarIgf|fvT*Y(K#ds2YGSf5kX#D$kZ)j8MsiF#2Uk+`;YqnA0CI!@$WEA z(=l;m0G>b2(DvkD{ac*TH0H9T=BLy54V^!W9mwi(edEp6CucKd+{=`4@4ru8e0*0h z-#6Y1{lVC%Q{U*+dxIGLjllO!UA*D*0vAA(|994Z&F{7qw>z^wTPqqE(J{H=g^4TZqncz80|xz@Y`nkFMv1DS}S78^J8Nv zsL+B!w$0O+DxUkdFvM1Z zEwqRm_2@>1+}Sm^k&z*XvA%6&#DsPjiKd!6IOV#f(;Nrm!Axy7HV)cSy+<1p5tkpG zO=M&{$M$u`(#zwmvGk8et+Djs`0gDxLHKXp@l6cGlehGgrp8#_L@RA-G^_stzOUjs z|1RHYh+#PuRonZ~1Lo+MX2yPbZ?Kv1PSoG@i{;$WH1WNjm9dqnf7(LT&{Vc6)Y7Y) z8@zVx4QXN2w7IWjsAcyO_;KB&r4b!ah>;zVEul4Ek7;RycK-+)*@+$}>pgQ)gkdl2 zk!^U!aFfRn+?wJh*-drWJgeY(?&B6wG2aK3@wmONx3`3==#AG$h^JWz zATK(pr4i*d@|j%G5Q2JiI<(#ZH(8QUs1YR{Ew|1sG(*yKCdqau!G`wFkjkiyIDky+QXrcw5g7ayRliP)~{ayR(VwnjwE z3q!9CGF;>@7c#sx9!_O+-oS_GH zFowuY!5t_&?sxBC^mETebsSHs4RlaPqj5kapX@Q}Xn1Y5r@WUt87y)--1_}4#*2h# z+trvY>|$4XAv?~x8nGc~ha$W~mNgQ)3Kr>*ZboDGyy;dSYRTJsMmiiGp2Kv0H=}w~ z2u@x?-5I+d@_VhWk9K1w7%W~xYe?Vh=Xa@i+S*UG1UT&vU<0$d;vZe(9sfVy<=^*>|F8Z2uhC|*hT#9vfBk=Zm;Z04 z`={~4{s6Knmh~tB*ok;2fzR&>;QJo7TMc~u+MwSx4%vY-fOgN(7HL7so3(fMHRt1;OU;$Woem2L9@Rk z-D~W<#>+697w)BhqgLo+OsGHVVLF?k+Mg%ZOh%&-5BYjygewz*&({4BIif?En~t+f((H0mi*ZOqBx|+))1v zgymZ}4OI)*Ugs@{+7X+frge`((adg-OM37?BO+)f&P8l5%yT$OpX4S%BPBSgo+s}e zTj?5XerD_3483O{gg>B93^cNA?YtxIr$gBc{lXwa*T3(6hH;9)rv_wU{$9*-QLxWU zDm`?U!A5M*hohD6N>kNcv4LXJV5ZUny#$wlwYWrS&tMAS4L)V{HFLi#{#zH{@7AXW zQ+S{0kRc2&obeuFEQtA=L@N1NyQJzcf<+bV;of$60uIh@2xWhc3;c{`0YBjDl&+s{ zgd!ldO{WS!<=h1^73t;a5aHE3(~Ys=Z~YTlSV70@Ra%xdSL)V73ARl49!e>;dy+Af zs+L_yb4SZ|IqnmCLM?ky&m9T}xr@&+I%JsfpyTQjmiSivckE;!Sb;^i4(zuq9A->+ z&%idC1jmh4>F8K_TU)rw;4tg8(U{=BaQT^jRP3ESqfJhn_EY$%ewfkenGu9 z(uf$GcgJ~mQ_H!ivroVH2KG!&g-UhyzqYsLK&hi4D&@8O<#ttuIoFl>k4{XKDi#Oc|N`#ZR2|5cSd7RIg6?=C0QZ$7C< zK4d%r%W(K1<5%`NYQwJtEV1x6XE4 zgk-9X`8~<=S3jT6uv;0r&KRSf`#feA`REqi$1o=Rp~s9NaCZ$?6~T%9{4sO__Ii#n z?hkkt={ZK%e}v>$>CulEuS7jR*^;YYf>D{lsFZr6D!DBQ&es8Bjac_I;*NuVnWccPBHe3 zXpgTy8S{PRl-=6X2J@Y7ar1o_HT5L(U4F+OD)c6p&)j8hj=Ag~b8Ancp7n&$s^&Vl z=Mt=$;zV%pdY_Q7qZ3zV8t=Lr3`MCxo?^9UDmgdx;i)tnw>~GP-*x?IaQ;R5>@=g9 zyC|KGh1Weg>M8te*Bzc>04vq|o}xKq>2pt^aU=RxPaA`6sJ-V+r_Ft#S5C)osNOl< z=;r?9UbU<<&C|g>byV?>deRJ|S&Q0zto0_EPl-BE*V91OK(brwUrv#pv6fG-?(aoLjnd zmNB-@nZIuPwkMtD(bc=RCpD?m1D}J@eO`b49F)<5W+TDA)m!-<6)0oja4IvrG{0Di z^9)&fT#uP;^h1K%G~2ksLC`gGD5)l-8^_C}NAi0q( zBB(@HI*2)s=r|m|tT%Q?^r^YVzVXbnz^sr+WmxL@sEm2WL^IhxDv0qgB=}QnRE7yN9U~9}&#K(FOTKECFWg zKkk-vv47KTUDhqNvW-7BCs=@=yEg)f2(6UebDCA4KY!+iUc3FDr#*i=!`>g<#qQTL zRYA~b9aRb%iW4!Ftqvtc3{ixT^H{yFIK#@cs*JxZGT&4eF zPn?YOe-pW{Bw!rB>u=@$n&0kg5s?tYxR*{9kp81x6=(`&0U(B%^^n@RVM< zz-Z+B?I&c^OE&|e+(v4C>Bif7Vm1AIHKR_@cRxwe=u64(7HwN-yb{uaY(!Ir**B|_ zzlZijy=Ec2L4CbvA%ofz`t(9$ukAkXniq^%2WtiUa!`kF@veW_SO@Q1NB3J~3}EGG zFfFyR?bfM^7Q%Qdu@^Qr0HDLBFT^ zx0j$k?WX50!KGYpUSdR#cXwwBq);-^pM2k6E$fSb{vQ~X2eJERfHkL=HQVJ}-* zYzX%Ch%FuWHh#hWDB&t_7xQew_Q&lIVVUEGi2VUxCN@Gl?8Qo*w`weHtm-hD8uPK7 z5M>Z$CxU&5pRynPe&TH%t`dB+p1ahDjnBhNbG!%@r)j)}-Q+e2I1hR9`F2%q6Rz^x zyVQtE7=XtZ@yI&4aG7iHC@bSa9-|URLSsG4^ey7#qJWrJXiM3IkR3I5T!oR%)&p>A z+nur&r*H6Lv95McXY4|W?C(h->cRr;{bB)lbhId&#=8xehF+8nrK|s(t zsFX;HuzFOt_83p{n9&*!;(ZNo%&W$ac6-1zeS4YlR7j7mYFQ)5j1z7%uAb*tJ#RS* z_}UaN)aJ@&AG-|tsmZ?0KEZnPa$|UufwK(qz8?2;h^J;+l@@`asjmMz?f(tk<#j}p zNImIw<8k|~u5!?;wm$#5kr-9|a+S`p&!~{a$axfp+$xgE1m0J-(C|A=^dwD4mQl6Q zre+AlNirXUd%D8BziN-we`(`GP7Q5ZVZ_>5b2<8kv6b!J^WH=xO7z-R8T;*U_y^y@ z_C7u9Z6Z6R*T2o8Mqk}Gj}$KJ7xIi}IZJvg4`mn^YX_}mI{i%dUdymrq^GQ(X_2>8FF%8*g%mAb-86R!Y2M z-X&7*;as_ag|maalT64${X#zROx3sY;V;|ivjzBlTd#hPDQ1Y5TcOyca6kJ^Vc>h{ z0h^3PsH;wFGKSk#y1wUq;~RFWx<8KP6OdtNh*cvh# z>s4Yc8%n}tVP#1nfg0%iLZjK>M(vT5aHUR5dK7i^ZQ70^1XU5njpl_-N|TVoqw~wy zLvVV(;n~B~^&D<-^b9$}P@C}2{9}$NsHGD&8$HA4?yS;V>G@Y)OWk?3XWxo4g3jda zU*o}$v+b%yeyrarTCs(j06^SCT*eoF6cE| z=u|LlTTt4SrB-Pl*<~rdo#$n|5U;i+deR_C8c8{6D(-OmM&H_Eu;u@t?z+|JIG}1T zUBQgb&*KhlA?r_0MG7t5;0*5sd7r4^77FXnY3#{^Z(19gJtP>rvhS6=WwTAft;c+y zKDd=}{Y`ytE0r`uci(2rZqeWXFPTsz^PodGD4z3L|L%u#;q=W34`~05j)+=7=pgt&+8?GZl^DAH`;fabc6!Uc<&Rf%7JqWS%;4)2y7qrZ~t;c?7bO}H8y^IQ>1;V(Scry3}=9`=MjiYfeXX_ekAvr>15XFT(De`X&}DD8!}TAlm-!xmk-mrlD{Clnd+?)cMHx-O}{r3V+$?Wb``sS(|`(N|SEg|;O3)=nasj9X?q znM35x*@@C_7_|Fh|JqHnozN>2*TX%eBx@IZ0*^V7yiDN75WSC;{daZ9CuFojcmD*& zbaESODwJaPGTyF-&n~N|N*>STzD3Xa#F*Gn?mcnmFi*pjc?fo)#3nSMVan0c4L%a^SFH=)z`s)bs=N|O|gaBV$Jd{oz~zcjklx;>2aVHuw>3$zz+0k(qkl*ED<{UHZm|j{32s)q=NlM0)^v(t3(#rES6(_MEtZnO&DEd!~8`xHSL zU|%DNSM|K(^n`4^@;LgEcW{y26?627<38$bCyY@0l$LU^GFqQ13aG9-pD@w_p245B zYhG_SVN7-p@rP@sW4<#s)ctoXC{ao6tg#?3&^H$J)2F{P7KF^~z(@lpUv#}Hxe-

0On!7XYgfp!O@heF(VR-V$YQik%Q;bRWx2Q)WxT7?jbm)x5ZCl&e2tfbA!Y;c43x9jj1hSkFhMWj zT)oyt1PUs|`@Kwat2QD~Od%dC1%9@%yT$upM8GBc$o?_SkswCIff1=&ZA3)Hk}K^Q z(gLc|UKc}bwl}0L$nNvcFBqy*%u#uqX>YvfJl%VG-3S1& z=tEI~aDSWnWz_&P@l@oF7vO7?Q(W!bvgdie^1<5_7V>Bg5ZiW3hH%LBUc>1$0 z%i2&k;0u}(EQcHJAea-P8?ab~KnvpY6pa2roB~m*8A!VnaDRl0$P=eXuH_|EWG$&qNr5wF&fB4Ax^R zY$&&H*#11CkGSj?kH#(brLacwAGnfb43&K&zlI9uX>@`k zeS(j3C}Yz5?M1FH-5|HNXAWWO(+H)OT=%fGYp%Z46o3kSd^8m{1|5Xm zMPrcfRx~^e0~$(;!{k&D$MP_-QIMgD+$vJSWhw)H)hNMf>z9GHXSj_Of_Pzp=~^tO zt()rEp3%f6a%iAQB+b-0v}`?f4p5%c)?Wf`eN@nVmcHqUo{*;LAV)ZI-qW8Dj$$wjhfaB zt9>`wn#sc&ilrwUf@2?|#kYZZML6Kjhqz$gpM7RRoCa>TQGx(Xp<1p&cRRm zG=NVfOQhUMf*cYl_UzF#yd|dd6I$F-4zgYZP`+HHRS?=Cll@o32_9LPIJ`|o0{ReD zw3HK#zhE&5QPIgco9s49Y9)KScS4417jT`v#jA>i=C%TI_Mm;OKz}CDjaFE=A5vs% z*&9d4om;~}UkYt#jn&qKDq5px=y9VkH4ssvkK9LD0%!-7`{=zTy!qS*djw1_ z`+`CaqF#OF5YNv}f$PD+qmZq;(5${-2=3F$zVdZe!&wkx_h?O$+z-mQ@+5hfxg72j zpiy>8`#8uG*1-4GlzxIC%%Qyga@sI!txl6YO%Kp|eIC`kk`c|LtYls&U zzJwYMlKXg`Ku|E!A_^wdgRq_aKq-TPsxV?3BzN_M!omfBLnw+I3=GBnGXXG9T`*YQ zE=x1j*w--{VnGd;ePxizv=sR|6vqQc%IleO>KGO_Rg9AT>s`U8cI1a1iNpSDSe2bz za`f@rbh4`wPKTnE0Tl7N(pOd9lm~O+$7CF~yv>v|4wdXw_l=V$ajBRhCdy-sPmW@_ zV^!7{Cl^4e2ee@#T80y+iE_B|1!US-s+cHGfUGg@Z8=D;TZl#J^+aiG_yK8x#T}>a zds|i+%;%=0$mpMniY%4a~M33TH#Y#t+3!!nc%y?0I)_KQdA?kw32B0m+Z z#j3?IWVRgCn~A{Z26`XNRc@h6(6-%j@+N4 zj-0PhwiKZ5-XL$~ti`W%vX#<|KF^iQq}ytSU7pRYi+4ek+3loT9OIU%85%p^0~9#= zC0W0fy$xay5Ukt+HTGM%zh2g<7`nzg6rWn+ui@>ni$FPFOj&~8Q zx8od#MR=+!{5~F&5aBtl@W*kE9}yO7wThVSDRRCzoIFRe4be`~;k{IYG1*7rUto}c z*Spfbb)^l%|BEd;diJZ_J?3)+sy8A_gsU}TsR*MHg0o9TBdRL@gl7GQF^#0vzsX(M zJ4N(kh0?|#suex2O${%};nsm7b2T!ZB*I<(CDSz3b#Of+U3!{)gwYWqc z!R3mq>*)@+C}K}chw>qbQho>i$5YPla{JmXkBhFG?N>qQ=4{q23wmK*aYIhV zmXLBo_HN>VJ0rIi8ea9agAF`orxpn2Emq6ocDhFfya zb|z%4j?i8rTn(W;MEL)L(E4Na=`HXCTWHHIxliP6Y!}swxhcZcin%7jC`KD{tcxoY zaa(Thc?!|aJ=KJ}p;K!yp0Gui52XO@jbSNbHJ1J@s4b2 z_@}(YEgaD&bK#O;H#ZvxBOq3GKl~?4y4GP-`ltLVi;SS=f60N6rF#7Zl~yHo$aOUC zFS$8OETm>pay>(PEu+a^Mg@OiM~bAOcd(%9)ABp=S>;2(Th)nw%h8gp^=Zd?ha$ZG@jUmQQPpijQUPh)SyB{YnzKZ6|L3 zdw@;qPDOwYT)SVV*_#VlARR_2xkwh6v=Z?hNUEbmE1%#qf@13^!{AS(z+3U9ZFQ8U zp5Gx_kf0IxXCgU(6mP)TVC%1Vhb=<%bkHz&Xw1c$(BUTJJjA(Y{x5x-L#w@&5Qsl0 zxxeQqSD{Ay?@+BKrK_9Lai1=$lqUKsJ*5@uZhys1s9FmGlt1LkAHau{e8Ph1M4*x! z`0FZ{OjFxgrSRx=5g?*JAFJK#VJ4+v>ct>sBZDDmMt#NCgZ;is?fAM3*Xyfy(QCtH zf3>)|@{CJFMXi+U(i>`CYh^Q2+N^-vGq}i8{Ofhb=YRRuufKN=Ma%CszEuU^8p5U1 z>aBJPc;N-A(m|QcVca{nlaeV(-Bd%oa*8V#J`?K8%daT@fj9B_-$J`?cNTh9HFs9P zm6lWdAxMzDN6X&i=&Jn2TYslfZy&nTO{r-J|IP{iiz;;o+A#fhr0)R~d`eM0l)=*P z>f#62IWz`Lb(~0y{dSz@I0|p8-XZWdnw+AfILyI z2?9ZEFXaOJeH+!gsrX1BZ@rcF{M0rbb@Gxd?C3V?og;^;TY4*y@M6`dBn5oZ-)dSv zMU|y|HEb}Jmk|<}XMPrmyFiNjW z;4#C7E8#Fi7&sg&s1eN_u8aUXaAUZ#5Em%Z-cY7NvwrIhfJk%5oUBZiMym^w70%$s zVDU(-5?qxWsjP)VzFDaV;Z539;Os048>RHe$@{EP%2tTH5u+7H5j{vrqcH)> zW~%X~(hl5u=Ql-P@@VK7ATA0TqlDrNYQq>*mO+-W80HxiGZy8IqQxTgI&B$?G4H9C zk5#t2H=H@&$(M);pRYG*++itqns?OQ46DVe?vNh`1*P@i_W-UJUp==4SHK7Dn$ zKJGe)h=&`!X-X^Wxw%d$N+U*yK8^6dS`8oj0!o{vc>6`8l&Vvixms;_90C6n;3WlH z-*?4S@rF~s7FJ^}Isk_0UAjC?+0ht>UJutxxtl_y;_)vkPxlZeH=9{*Fb=`4!Si%N zQyhY&>TH{6_jHW#Nh+PLq)JoO&NGzS5+w40?<-xUV0HETm<8O!Dwv7+%p~InnEUB! z><56wtmMp6;1!L|&qD0SBz*|jS=8`DWjk&#T>Ma(AVsO2XDjQ)^179wBwEj8VviIj zaJYpbloBVa!mcY6$EepF#n;{}&Q%&W&hfR~4l(AIfgq22QRO_PPHr*|Otr4dLAL8~tNa$_&PCTh zqvE+(rdK2AvT&R)P0dM1~ud@ z0(!?&!^I#bP(UrlHu->teyR*JPsr9~IX&A+_8bhIHM^0m0Tq6#1etGRYZGV!^tJ<4 z^Mt}~B>br%9!{r_{4mQPCo{wnFB}j|Ul!5N)HKF`XKeLn; ze}+wS18w+B8D^Zj2)q_Jd3T%!kHt|s4w#oIW6VpDQ!Ik9dY9Y-$rHlkGG&6ix2jOh z&qzR);ukn}ElwSvp%g1@A;w1VIO&>gp2_|WC1qjlrqSpuWv%DHl~wn@@Hh$?mn*)? z$u+vHG&N#5P@C^r1F0dyLQ7XDO=0}JZv}>a5t&J8W$Xel3A^~{h0d1Uq@jdVJLM5Z zE1Qg;W9&>6^|>iuZxO64!(4^82~1TB07%A&)C zr&3z{1@dm7ye~k(@uu1rsO}hwcxh(~pi30F3R~L>>a_}kx0FV&!t!cOwpEI7*IT>_ zU3^Equ}bMF%iSg2Qfm4U+(EyUt&Ea9)Z%OfhoxVrE7vJArG}oXoTNb~#W`wJ`+oAp zzwr+#<||+X?wNe0q*@%|umgEo85J*FVhh77sKtbJSw}T~gHlroOMDOP0xGq>TG!@* z@3HuWVW?uO;6(LRF zUA8Mh4Lc%9#t&wV@J*cvXXuhm_!1OD`a*zW?e~R)GldK@SBjvwy)hh_DIx4~7~R~g zj07@w{{}Q_G|du!Z~^j-5@KlWf-R-X-+=E~L}6Q$t_Dw6>>ir21>1`+6>R}$_&Y3H zl}vtMu8vOiWtL^>hDFq3s{$W-6u%Yol1me}f`}ZT?oM zmO7vF72d*3cHik#BTuPsn2r0i%|QEeC}kTO@QAi-16I5vGDSncGUO?tZjO(1S#M2u ziXilAo^ryXo34Z76sg$tf^}}i0jMl7Ki^a2cghmOwP`xd1=1uc{0@CROBLTKzLv*` z)%Ft5`l56v``MdxS>+V59oyz~O53h@`yBZE|0E^tiC%mP!{8sbD}ALv6Y^xkh0&&; z;Icnse_Qcd@r$K+gW9IcDyFm~?n`kym9hNx3LW)n1UrcQol0A5_Kuy{4Hnau?}5DU z!-7-^?c8muMp?G${5sm^2osBBy-kAs`C`OZ-HV-#>Y%KRs`4J$4x>@saOKkrB$#QzcZVQzA82xf52?x2aJLewya|x8l(btJY_44HM7FA@-5%jx zkf*e7x8hspfh+00_HVYYT~5tv=o9$W_ZWCM})D?M3%NPxeCmNI{8XsAw-x;bYbKgMyRE-W0eG z#A7e5+y~rzgKq3o9((Pdnt8E-!(WESP^$5_?R(q$c@ z%lm=OqiA(LcBHoXN^2B7F<+ZCMD_G+4j{3DFD=t$&8E@<#TObWg^UGCSH&A?4=C0{ z3Su>~=)(e~iBw6s1xmQ*13-&hIrx7?{CWPM!J6&k z@b5tdKcP8W$?+4q{{vYM01h+GdYwmjYB}84zrK^kKNK_`Ij2+PK_%4uHh|+WgW}j-94rVM#7XcGr(_0( zp=^x>1au>O3*s;86~>qK$@35-N6{2f_1c$iq)c{ySM^7QtkMSvY&)cQGu<-!`jAqe zKmN?6!YVlg>a>Z<4=Mg0Li7<-aT)%_H8nqKaaeJOgcoyIX>PfKSi$4QX$Kl+yET6i z_?NHV{e?0PW9OMkD-SC{M$*bK*_Y$r9W4cYIgBwoK%PfHU-rHG?>LDunyx{6+q+Zj z5r~{K5ENCUpo(_1`Us{ywOUjIdI+dmJ*!1|d`5$gDqWyATzwRc=s`P=Dj}Y)pzop_ z>`Md6=*CeDaGWcu1g19GIDJaTEIlS`q2e8Q7eq-wXG4pzDIsq6QJt<$PM0`%4^8hE zMoEQ=uep&cH@Niy*+Mq}cBKW)Dg@=+NqL39l;d=(Pzg`TM_FTQ;Ccm~kj8!R0m-%E zcJCE&b)0c?5GVWxJVW*45pM$HIu+KmWAKg38^XniDLWy~kpt>-6mj$MGvf*QL1>F` zp*ftU9D|I;;4cb|O0BVw!V!#f~Q?a*gD~{-FS`id*T513z^fx`95` zl9srVdQ^-1#1+?>dL38BcxYA6f{Y6SGHR7}ot1nVsF$VVB zl7Bm%`2sEViQ8QzhZIq1G0^1@K$7(s8-ZBhNDIh#2J^U=!p?w@9i&-j6k@M0p)U?A zb*aT!Wt%Y#Ip#yDHy;NQ>7T?oCQ|uXWrDdMqO05e^+xz1C3TkkVcxd*97q%#1fK^( zR-4A1SEezKC3Nk)auaSl3V#M+KSwuyh6J*Wk}fFAjJ8j4+MFQUQn>HJYcMoeOb;)B zy3L~aU%*aHr-8pfApxf~7nMw-KVWr`4|13fVEygj1TKP0ub`-3Apl>aEx!UgQ2ehT zAcbW74I2=g$^8b|7Uf(5VVFcSE}`((>Ch#t(^N8FR)PXAyrt7zWIb#i=g1U%K{cPl zrzz<&ngJK+fE@l9kiwBapthwZa~rVs%t)ZuPT_n>HS(GEEH1C^bp%cDn%8z@*!Qp7{O@m3g+e#MO{(C!-^L{&lc|51AXHh zMFd=GXFGSRZFW!pK$1akoWLN-5^cL>Ehu;g%|06T92js^@i~ zm;2kOL9)D0AXi;p)Dxrz$$7jSiaHF|el zvcZ>$MqyWef=w}83J_y@6Y|idPq4MWJY{+Prt-P;4L!UGF#>zeA4(_w@h8p$kp{Do zGud?@GRjrD7RG@{vMWqp(E#7%S}oaFEh%IzgYGSb^2&fhz_~I=7ClJ1 zg-~ZQ-%_sncp-~>ZOg)ZmWOuG#-{{1-YR)VwmysmAe;K_o+ zHG55*B_dg}tGjPwd}3`2zy&h@g#}nj38}i`#RxZcvn(`Y-1Bj2kiqL>$(Ze*AYLrD zqxeaZGj1+f|593+r-&^70340U;Lu80aXk=vbLCX)8sl7zXdB^dL`g@j5wbJ>o@Puc z8W-0|i+?c|yINclJm7zHM`>WLgzBfdP5(25A36^<|DnjcinsdL9px2VPZxm@13W8h zGZ#<8?<$j+JfBY9RocMapmI-{>HcIM4A4aRi#~(8d)+;yzGrK+98@h2^3Q-fRD2Hu z(ugYVfw65*vE^9l1+=&vgY}#?l!G3f4WWAXmA|Dfs^>poh1r>!)b)W90r`H)158mT z%6kCd7%F_Agfhc>bpHW>ak>5>rsLN)T_Z87m0!d7`wy>Je#%7+2a& zDtw|$V1wt;l_d~fj?++wGJ<_SS{SO-qhB0~2i&3Ga44MukBA&EDx(C8tbOBuw^oYT zei44T6mRo)uHYHSH@C&90+0%t$iamd=z08%=R4sUp{`?leOccpFGqq zpP227U1?jY6=kQ2rx?9C6!T1pHcrzZU|it(2N(Jb+tpt9@KP2U9zbZI(O8$ThQ`k1 zi(6&Nq@_7zIB$6qK< zbZ4a~_w=_cAh1wCyY8rJ-$>o-D&aSZd7*4}9|2%C8W~DBJQgW;z#!^dgN5}>B5Ju zqK}q4idfAIqy*S0#t!~-^?F}y%boT5>o8UdbJJ(yEaJ|~Ji^!>fOQk(|ytEctxIW$4 zDJVy3>!V?#KD0JEg<-C(@9O!MmI%Mu`2T?tizLAv6yQ)x6f_Lms<>8LMEkt; zzJW)OEEs8x<%P-vc9PoA1A0>QORKMct&+UKWVq8x&L z5sC|ozH7{F(HR&0*1pl=OIiob_U8bbGJfil+2h;1q`>E0X|N@-pc{8*IlEydN1(oD zP?1P=wNm>=6ZUI4O!lj@z{+jl4XJNkeFLn%DRuSX;+VBA+O>-gA>_FQ6^bEy4gVEX zQCHs;B6Vkfv^WGYhv}lfKEym8Rcf;iq!^=RFxgFH4A5US6#)Se0ax5nQE|sDvD8#FF|9B+Of4-f zEe+hBFgI>#W2J?r1*C;r7q`SMG4%=4iqZ~-G_8A2QmmxKYlfDx%3Ny9)}8J-8tEm`#&o&Szn&2oarA-kUNhnMREFoEPCcV@ zpY39;Y+|pO8ve)|gem(KBqB8M74XLUlWbO{Ujcsi=W7m5)HA{()`(XnbzU>ME%ycw z;+38Aau+$>xxUdM;FU_(DV4ZXPpc1K->YxbH%2<`B>mCIN~O`%2FxkVIreTm5*9fd zeHQ!T4JW`Zh?;V@BJLzYSCl^AfPTWocMZv-yB^SxM!DD+YUl-fI3!QUaJ=$w$FP!t zH1elb$mN|xu9OVI7QMO%NY34FZe%3OCtOt< z8xeuM9!EpX<(G0J(^+oc=WR&cxv_D`GQeYrAtBy{3Twg)a+CAvu*tuf-Gxn-kN2_3 zr|S3UxC#4p&)ZE5mKvO>Y|7-ZL_3-p&7zkR`Z~T#9tfSt>MEnWV*4ZX=Ktuy&5Q%Q za}eCz_#n)rC@cBUH}zxRN4}OoH8g=!36c6lbK?a*w&>HssBUrHO;#%&BJvFVL`x&w zu@h@oJ-Ve461){-dwirUtSa(UiQzt|a|qRN6kbg$y%KB|_lIM-qLFJmCFoG7tB+rn zKHrl0 z`)fUNL`xA&%AIkOL+jMz=lXUl228H*7fXY#B^e1U+AwdV`4;ZenHx(FSfcmEBIg`I zmpxhcXbq#d=~>j8iA_#*wlVUeuGZ!bCzW%a?S*s;XUoc~yL+Mw?U~iZeYTf!H_`64 zMtH!x!+pB81X*oGMY*5ms5oRC*59->`Z@wgog>z9#+&9JsCt(T_st7MaYlUA`V^R+ zkSRSOupK?&oc_L@5$>P)7(Gpv-l~rKvbMBms(ORCUh)}tqW7aX^vzniOK@-HY1iIZ zZmk~oyiZ2hCrK8?>yz=unjn7yh*o`ucYz#~>%#7R+a{}{5f|3?G2aBqCD6BHP%rtG z*nzp1d3euw#PvEl*%kz8u6uMc(7$5ja8W12W3hDbH0)xquUY8SzjQVJ!xzvKyTR1* zrt5og_LeNKgS#U*UKz?t8ghNS)|tC%x*pih-pFs+bl=eG489fah|yWyjTq#%BSZ?T zi{m~b-e=I0Dg%dVO9JfvN!=pB2=Pm*fo>cpf)LHB(Y<26GqO; z5MHFX>9rF6xfCYof$&~4;f%`gjU;?6!Z-alyz_zZUNhnUs-&m(bd|Outtk;W(>}Cv z5Alw8R`NWrnFyCFBUF*~y2D5ZkinD|fLH9x~e18{Le%JuEp4(;~&LpbSrW815O;U^tY?2-6Q4 ziGlf0{tA3Je01-*w)nSRo1P(;b zO=Qk(?Ae@%^vMlP$NL$7uqxc~u<<4-4tT@}4}Nv9TH)cdqZCdFBqQMVWaz!3=R9I` zs6Gj=^?0ondKjJu9x*m?d}UgHVmHu^0WkBXdg1^EQPpYse*=t%SnjkK2=$frjBOWY$q%h*Xs*$FW?-Z*k^Nvpb=jqCBmKcf#t+nTz=(b z_&j}eAcT+6{*M}ImR_Evk20FLdu_)cLq`vN6y{Dfc-4R|-Ur3r@xGlyCH>irGa~&9 zo`55WGoSGt)N2MapKjCp@IeoCR$#rh3^4*7Um&Va)6wC!NF6`K@C!RN(8rr(gI(U{ zyu~Hus33#*W_*Y-Kf*qU&*k`ey(@1}+ruUG@;Vwq+z=Y!nr@h6Gz;Sqy%oRn^Mwq` zy$U0g@7RCQ6O(AzBEHOk`F^R7BthCf?ii$6v-RMiMquy<4@BEUG)eqDJ!>c|r`L0E zTsnZ9_MY>E>}Lk&UV2uo$kdyMA~_afoTU2(8q@vi(T`u zHY9@vdh}z)F2`W3*LC!8qp$7Nf$UwDayBbtxRHuZ@ak}55}WiuxSpA81UYU{SF5x; znYLM`HwnD1k0cuj)`U8qsw0dh7IY`=9ygN0J{v$KvQ4fwHkXMguV+bD_h|GtsM8)d zLfYlt_uk#q=Uvdn-2?CSxHCEBDb>aO4raOHN@ms>Lo7L5ze7~V@F{3rwQHm?oU;I< zM^cevbk0bG5e^dw^w6zG0kL|9K&0LwP)*+zxT||SVLY04i;1?BWYRBJ#Kn{PpCh~* zJ40qL0#eo~_Z9q0@GrPh5f_X9g-U;U9YbC=`yKyc{7cFz;$rasrPBX3@&Co*{u%!w z{MDZoaZ&jHQ0bp3{`0J9?(YatNPwto6>*^i__{K{+Y+Fj&HWYr1^6diuZR<6_Lr6Z z>%@P*&3zdEeEd^xRKz*)-(TtfvG_l2ckjhN5C8O=6>(FL<#ty3%h&FAp3}>oG@eCp zxcj8>yXA5H+fyuf`{?Ktqj7LQBFfbQ4-tXu;fIuC?xmkdftSSUr76ZowfEv9B-2Vv z`mt`+-y1T>9H9q}HtM==KH^)q-qkZkGsepG%F#xvutx|b!@$DsgUA9W8B;=dAN}KK zIzLB2pEe$KEMW26SPy#|dbmO9X=8cV;>o^cwHv`@9y}`H?~1tYP_RUI9AiYfULmt6 zG=B5+=rN4D_MSy!j3g^pivKtcO$KKQ#~UGG2OjqJDQ=T#?%r|VT+)nF15?H$D!%v( zn+kgAcq37``gh}v5gfB?Jpm>Nm7#cV>%$! z2(Qv9M8;TPZq;XW`&8qP&*)z7!N@sz$a z$!P3K!YZjI>4?cjW1BgV(Hv)u)~ST~2-rJ7pt=(O* z-#3e&*Idxl-3@c;{cz~S+hRZWfW1BTl7H;2-EH)yXN^|XKS7i(!kHOORu7&(o)zZ6 z`)yN=k6g`%sukZ*3r+N)sT4U#-#*mIX09)j)QSTHJ*)>j zPnf-W%Jar+>~P(9p7vg%BVI6i3-1~8f-%?<)`*qU^}j2&Wq7CIaPKsHn#kYl(HLWO^wmGTXsmOb!S}RY_>z|o>ccM?CxZWEk+Tx#z3WuRH^H=emX6#R zK9dgjI@U${I7ZhzjC1*=>#H-3`Ho#gdQ#7tWh~}$8pq4VnA$lv?|Dxno#md^2Tvni zF4yy3MwDI5xgY4Ev%JD`HMX6Ti#7>}@UJNt@pjRJf# zo2qC}hEY7m`Gby_V}x59eXKjpF}iV`%&a-+wVL&2IaHb4X=c11N$z!|ls>q9s{>wT zZrG;hylOmUUq)-cnKdQ~g}fyVLUxb#RhJtg5-#1p=v#H1Kne`qG^3YmJW+%bbkGaa zXv!0MQ<~AL?;*1EtsSiHI^K0d2y2M&+#Fs_6@hBcKmNY8h4)*d?g_UODpLypxAj&! zqyqszV9#LY{KauOAD^_@vxczX> z_XWu{)VFW-R&RDsi_nAO=&7sHjW`a=9Z#p$m+9!a#-})*m}_*8xY5hkW28`rnO*ZJ z>x-0MKIPr7Tg*e^+C?SG#m92+tFWHx_&Gs7(@)GZ`ud$A_U~9ZpL1L1h1f#-ghHOA zCEwnj8(g7p+Bi5!TDJ)4ts>;ckqy2X5>v$g4u z`f{vM&suRtfBu-!$o}Im)JI-*Bh2JnsL3U6oWwEe_{#%-HBqM=^9fVsb}-m?JiJzAe#VC=PY^{icJMB3zr+zd3^8$25p8S9ap!}KGI zjRD-M{q|yGxc|A{6?&VkR(aNZ>xo7BE>8BA4@uS!Swh(ypSFbIU8HX>K~>aAw^(ZQ z@-I!OJS>8;v|;}P8D zV2Yfv3MaKB{M*t735Zc&60aP8vCkxKfBX&-mpN{TxbM@gml=T_cjKfkR^GKgMs<9G zw(`oK5M?7tS=4VOOvz7`Vd`5tUMKn|dd@N#h z8Z9Gc5LQIh-&n_FRECxMm+t+n-jr#C_(zgS0=@cd&sJ;sb$xGz@q9q{Zd^(TnNcEKM%8tn z({ooM8w66lP@AbrI=HRgjnz1|Yk4hEZ(eB(53}JdY~MTHehqM26DxE8sWjHnZ_)pk z>aK4wbp-2)ZyA%Ue|6KJoM(ga;#)>c*uAm}onf6(E+@F}^Pm(Ik6n0!8S$o(o~Vh* zmr&YhTfG{@NjAH{o!z`A0P5-+8r?;ZXVWSp(ux>+{2gN}QqkOZSr3JKEUS$JR$d-F z^d7EV^{n?vtVnNopDm1sbiXWexU3gu882D-cIEJv4uNhtL9v|KdOP5c$A#v(YPf>W&J%m63n#&4eA-d-W?XA?hSO zXR|Rf;FtEkiP4urSnf~yJTXENzTn2rtvz-Wa;au%FROcz40b-8>$Syb$oFs)w@`m2 zdhHel)eya73;SIs6ZoP^$S#R@pJjDh!V~OjTa3F8BuOVJB~QhXfg>DmHM(1`AJpBp z8l49GxtF0}hUa8)yS9+^8{a?*E!~k8??+in(q~C7dUj)X)@zm%>jH&&5%09Rogz~Q z@m68)s}F63uP@W*x6(+dy2m!-l@`GVd4hy0c@;WDe3HX?C6p+M2(tQ?+dRB(B+^lz z-$sX6spoDt`ZhU39h4lfxyz+4I9_xA6Vd`F*9gFZzC2K&dl9>>zPjD$(0SCc2RJifteJZI9wRB@)i|}{87M8WTHHtAmpfSjsN)rJFZGmrOd5X9 znqr$C_c;RWF?}3c@a_{8db7+*J#6l$nXmgZ`-JM~y(}iub-TTc`WN*Rd!etcUL>}+ zIj9N^9Ms;+pv}|`3)t?hb+$qycLlwx2Ny8x$Liw+MtHxllNCCiz9d)Ojv|}nyJmZt zL*y#jROvS`?Jl^#dB+F{5g)YjO7Q5-e>%b-X&l^1?9ZKeq_ao zZGBUrwAeQI?FJ<8lJbhUrJ*$Ud47@Vbs3SLAE`JEu(_Hg##!@ zih4+{!MO?K>YMR=ujzcr^TrIZgL>Ej<2x3+Ee^sfPU?OK*`ukgj~|3JnL6wcT>Q@y z`f{Ps)c<$NBT~>BI75QobBL-sqklYPd=&On87le9G z@A-nPUeMosVRWyxjAZT~;dat0LhEmBd=o{&VYWkO>CuOc`Su@*ki}BEAWYslY&58G zw8*DW+CW|+lj=d8Ep>vs(OXm4<@agSQB@;eYCXCT7P?AbDr9SCDe;8r1Ne;B4UbUG zPwHVuDBdI7iC_fUdbaUSFA=`e4#h`|6`Vwv@+DiFtKYn*b(Gy`pf`TWLT28Z`tp}d zoG-NY5&aE#ir+~+?I@+}rrk%44%V7S^|NtCBlg#?9yLO$r}4I=WN(svZtKdN;*Oy} zrFM_gzbd-;R(@Q`d>pF3^PD(NV!?0V{5^elc~_s%b_O#o`js)EVFPLzO+-*VuqK#Z z&+2}b;G!ytz)dt`6Sey*){3KIeWY>(>?@*I;hA9vTlgg-HsTw0zRN0OUpfs z2)mlV^ztGWF$?sbB0Bs3bjK6M;sMKB@$n#uGT#)b^a%Gw>>@;|`pW%nXY@8?ybwC2 zB~L&|FoNQjxcwJ%0oM|XaPQ=+j+3}?IPz;oTov8*Yj*$Zc(bQ*=m*#7q{74k^)w0L z)N8&ry4U=b`kTSxb-Q;5BsjO6&iJ)45Rtm;NrvnXdfZ9a>Nb7%B#N+H2+Pr7r-=TZ z?sE$N6?)1kc7ErzlFI|a^@&r44jV?O2k(4mI@u;%GfB_=hN19=9`UUa9(JasuTOv4 z2^|CENuPd#0&)8OTUd<0zVR(1rCiVY&PWTpNjFTjzT}f_I0NfjUj^oVp#zE`rkn0s zY_tmgR9LG`xhH|bax=+dxt?3>9UE^Kqd|EKAK5mXrN1wR`q#DPdn3^LOiSPOK&`(w zk{lBW;yVSev%fbcyZTf{iO~^17}<6HWei0sw!M!rWchhj>WTX7561j}866o2i1h`x zD&p$XdR%yOnyGDqe)}{WptIh7+UOjysD-aNeN&opXSDbA6Bh#gM(uwFj(toIK1008 z`uLB)7=2aXalJ zB

|iJy%6b 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�@zgey)vJpc7E#|+}jB|NRQo@7-k?+;v& zH1BAor>arlrwi@gzeTe&;ZdVxW@3t3LG(0t6^DCkm#X!SgwM}s6xBsoqj! zsCn(}uOt?0Yt!e&zYV&LitV(l&dnMuHS7M_;b%8Z(aCbkFx^}y(qb|4#{Q%QGb^3_ icWDUuoA19T)jv94Q7y}4!SgF$Y7Wi+1^IU*H2)uITe!sl diff --git a/packages/engines/rust-binaries/native/Cargo.lock b/packages/engines/rust-binaries/native/Cargo.lock index 7a1df150..33a3fe3c 100644 --- a/packages/engines/rust-binaries/native/Cargo.lock +++ b/packages/engines/rust-binaries/native/Cargo.lock @@ -50,7 +50,7 @@ dependencies = [ [[package]] name = "docmd-engine" -version = "0.8.12" +version = "0.8.13" dependencies = [ "napi", "napi-build", diff --git a/packages/engines/rust-binaries/native/Cargo.toml b/packages/engines/rust-binaries/native/Cargo.toml index 3013274d..db868cd0 100644 --- a/packages/engines/rust-binaries/native/Cargo.toml +++ b/packages/engines/rust-binaries/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "docmd-engine" -version = "0.8.12" +version = "0.8.13" edition = "2021" description = "Native Node.js addon for the docmd Rust engine" license = "MIT" diff --git a/packages/engines/rust-binaries/package.json b/packages/engines/rust-binaries/package.json index db05018c..84736bcd 100644 --- a/packages/engines/rust-binaries/package.json +++ b/packages/engines/rust-binaries/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/engine-rust-binaries", - "version": "0.8.12", + "version": "0.8.13", "description": "Pre-built Rust binaries for the docmd engine. All platforms bundled.", "scripts": { "build": "node build.js" diff --git a/packages/engines/rust/package.json b/packages/engines/rust/package.json index 1434b014..7564baa5 100644 --- a/packages/engines/rust/package.json +++ b/packages/engines/rust/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/engine-rust", - "version": "0.8.12", + "version": "0.8.13", "description": "Rust-accelerated engine for docmd. The postinstall script downloads a pre-built platform binary from npm CDN (unpkg/jsdelivr). No code is executed beyond copying the .node file. Source: https://github.com/docmd-io/docmd", "type": "module", "main": "dist/index.js", diff --git a/packages/engines/rust/src/index.ts b/packages/engines/rust/src/index.ts index 752b93a8..569aa477 100644 --- a/packages/engines/rust/src/index.ts +++ b/packages/engines/rust/src/index.ts @@ -129,7 +129,7 @@ export function createRustEngine(): Engine { return { name: 'rust', - version: '0.8.12', + version: '0.8.13', supports(_taskType: string): boolean { return true; diff --git a/packages/legacy/doc.md/package.json b/packages/legacy/doc.md/package.json index 1f296a1c..982ce4aa 100644 --- a/packages/legacy/doc.md/package.json +++ b/packages/legacy/doc.md/package.json @@ -1,6 +1,6 @@ { "name": "doc.md", - "version": "0.8.12", + "version": "0.8.13", "description": "Discontinued. Legacy wrapper for docmd. Please use @docmd/core.", "bin": { "docmd": "bin/docmd.js" diff --git a/packages/legacy/mgks/package.json b/packages/legacy/mgks/package.json index aee96550..f684c595 100644 --- a/packages/legacy/mgks/package.json +++ b/packages/legacy/mgks/package.json @@ -1,6 +1,6 @@ { "name": "@mgks/docmd", - "version": "0.8.12", + "version": "0.8.13", "description": "Discontinued. Legacy wrapper for docmd. Please use @docmd/core.", "bin": { "docmd": "bin/docmd.js" diff --git a/packages/live/package.json b/packages/live/package.json index 26972627..cae6205a 100644 --- a/packages/live/package.json +++ b/packages/live/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/live", - "version": "0.8.12", + "version": "0.8.13", "description": "Browser-based editor engine for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/parser/package.json b/packages/parser/package.json index 7bb91bb6..cab9197a 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/parser", - "version": "0.8.12", + "version": "0.8.13", "description": "Pure Markdown parsing engine for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts index 2f0a8cee..af886291 100644 --- a/packages/parser/src/index.ts +++ b/packages/parser/src/index.ts @@ -58,5 +58,6 @@ export { createUrlContext, computePageUrls, buildAbsoluteUrl, + normaliseBaseTag, } from './utils/url-utils.js'; export type { UrlContext, PageUrls } from './utils/url-utils.js'; \ No newline at end of file diff --git a/packages/parser/src/utils/url-utils.ts b/packages/parser/src/utils/url-utils.ts index 411288e4..919697cf 100644 --- a/packages/parser/src/utils/url-utils.ts +++ b/packages/parser/src/utils/url-utils.ts @@ -292,3 +292,68 @@ export function buildAbsoluteUrl( const result = normalizedBase + localePrefix + versionPrefix + pagePath; return sanitizeUrl(result); } + +/** + * Normalise the `` tag in a fully-rendered HTML document. + * + * The generator is the single source of truth for the `` tag. Templates + * are NOT allowed to emit one themselves — anything a template emits is + * stripped here and replaced with the canonical decision: + * + * • offline mode (`--offline`) → no `` tag (file:// re-roots) + * • root deploy (`siteRootAbs === '/'`) → no `` tag (relative URLs + * resolve against document path) + * • subpath deploy (`siteRootAbs !== '/'`) → `` + * + * Implementation notes: + * + * • Removes ALL existing `` tags (any source: template, partial, + * stray plugin output) using a regex that handles attributes in any + * order, self-closing forms, single/double quotes. + * • When emitting, inserts the canonical `` immediately after the + * `` tag so it applies to all subsequent `<link>`, `<script>`, + * and asset references in the document head. + * • Idempotent: running it twice is a no-op. + * + * Centralising this means old templates (pre-0.8.13 with unconditional + * `<base href="/">`), the default template, and any third-party template + * all produce the same correct output. Templates do not need to know about + * base tags at all. + * + * @param html - The fully-rendered HTML string from the layout template + * @param isOffline - Whether the build was invoked with `--offline` + * @param siteRootAbs - The absolute subpath root, e.g. `'/'`, `'/repo/'`, `'/docs/v1/'` + * @returns - The HTML with the canonical `<base>` (or none) in place + */ +export function normaliseBaseTag(html: string, isOffline: boolean, siteRootAbs: string): string { + // Step 1: strip every existing <base> tag (self-closing or with close, any attribute order) + const BASE_TAG_RE = /<base\b[^>]*\/?>/gi; + const cleaned = html.replace(BASE_TAG_RE, ''); + + // Step 2: decide whether to emit a canonical one + if (isOffline) return cleaned; + if (!siteRootAbs || siteRootAbs === '/') return cleaned; + + // Inject right after <title>.... If no exists, inject before </head>. + const canonical = `<base href="${escapeHtmlAttr(siteRootAbs)}">`; + + const titleClose = cleaned.match(/<\/title>/i); + if (titleClose && typeof titleClose.index === 'number') { + return cleaned.slice(0, titleClose.index + titleClose[0].length) + + canonical + + cleaned.slice(titleClose.index + titleClose[0].length); + } + const headClose = cleaned.match(/<\/head>/i); + if (headClose && typeof headClose.index === 'number') { + return cleaned.slice(0, headClose.index) + + canonical + + cleaned.slice(headClose.index); + } + // Final fallback: prepend (shouldn't happen for valid HTML) + return canonical + cleaned; +} + +/** Minimal attribute-value escaper for the canonical <base href="...">. */ +function escapeHtmlAttr(s: string): string { + return s.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); +} diff --git a/packages/plugins/analytics/package.json b/packages/plugins/analytics/package.json index 7668206e..b2d4e430 100644 --- a/packages/plugins/analytics/package.json +++ b/packages/plugins/analytics/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-analytics", - "version": "0.8.12", + "version": "0.8.13", "description": "Analytics injection plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/analytics/src/index.ts b/packages/plugins/analytics/src/index.ts index 67796205..665e91a3 100644 --- a/packages/plugins/analytics/src/index.ts +++ b/packages/plugins/analytics/src/index.ts @@ -21,7 +21,7 @@ import { scriptLiteral } from '@docmd/utils'; export const plugin: PluginDescriptor = { name: 'analytics', - version: '0.8.12', + version: '0.8.13', capabilities: ['head', 'body'] }; diff --git a/packages/plugins/git/package.json b/packages/plugins/git/package.json index aae27e4f..aca7e684 100644 --- a/packages/plugins/git/package.json +++ b/packages/plugins/git/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-git", - "version": "0.8.12", + "version": "0.8.13", "description": "Git integration plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/git/src/index.ts b/packages/plugins/git/src/index.ts index 0e410b83..69e28c1c 100644 --- a/packages/plugins/git/src/index.ts +++ b/packages/plugins/git/src/index.ts @@ -290,7 +290,7 @@ async function getGitFileInfo(filePath: string, maxCommits: number = 6): Promise export const plugin: PluginDescriptor = { name: 'git', - version: '0.8.12', + version: '0.8.13', capabilities: ['build', 'body', 'assets', 'translations', 'init', 'post-build'] }; diff --git a/packages/plugins/installer/package.json b/packages/plugins/installer/package.json index d7bb6b3c..08363566 100644 --- a/packages/plugins/installer/package.json +++ b/packages/plugins/installer/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-installer", - "version": "0.8.12", + "version": "0.8.13", "description": "Installer utility to add and remove plugins for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/llms/package.json b/packages/plugins/llms/package.json index e6dec222..9a17e881 100644 --- a/packages/plugins/llms/package.json +++ b/packages/plugins/llms/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-llms", - "version": "0.8.12", + "version": "0.8.13", "description": "Generate llms.txt context files for AI agents from your docmd site.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/llms/src/index.ts b/packages/plugins/llms/src/index.ts index 25271b67..21bf1c8b 100644 --- a/packages/plugins/llms/src/index.ts +++ b/packages/plugins/llms/src/index.ts @@ -19,7 +19,7 @@ import { outputPathToPathname, sanitizeUrl } from '@docmd/api'; export const plugin: PluginDescriptor = { name: 'llms', - version: '0.8.12', + version: '0.8.13', capabilities: ['post-build'] }; diff --git a/packages/plugins/math/package.json b/packages/plugins/math/package.json index afd0a9cf..5d3b60c5 100644 --- a/packages/plugins/math/package.json +++ b/packages/plugins/math/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-math", - "version": "0.8.12", + "version": "0.8.13", "description": "Mathematics (KaTeX/LaTeX) plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/math/src/index.ts b/packages/plugins/math/src/index.ts index 4ea6d579..72ff0813 100644 --- a/packages/plugins/math/src/index.ts +++ b/packages/plugins/math/src/index.ts @@ -18,7 +18,7 @@ import type { PluginDescriptor } from '@docmd/api'; export const plugin: PluginDescriptor = { name: 'math', - version: '0.8.12', + version: '0.8.13', capabilities: ['markdown', 'assets'] }; diff --git a/packages/plugins/mermaid/package.json b/packages/plugins/mermaid/package.json index 2f67eb27..f4e8ccd6 100644 --- a/packages/plugins/mermaid/package.json +++ b/packages/plugins/mermaid/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-mermaid", - "version": "0.8.12", + "version": "0.8.13", "description": "Mermaid diagram support plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/mermaid/src/index.ts b/packages/plugins/mermaid/src/index.ts index c01e5410..730a975d 100644 --- a/packages/plugins/mermaid/src/index.ts +++ b/packages/plugins/mermaid/src/index.ts @@ -21,7 +21,7 @@ const __dirname = path.dirname(__filename); export const plugin: PluginDescriptor = { name: 'mermaid', - version: '0.8.12', + version: '0.8.13', capabilities: ['markdown', 'assets'] }; diff --git a/packages/plugins/okf/package.json b/packages/plugins/okf/package.json index 64640ba9..cbb04580 100644 --- a/packages/plugins/okf/package.json +++ b/packages/plugins/okf/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-okf", - "version": "0.8.12", + "version": "0.8.13", "description": "Generate an Open Knowledge Format (OKF) bundle from your docmd site for AI agent consumption.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/okf/src/index.ts b/packages/plugins/okf/src/index.ts index e9c6f9fa..bf538ea6 100644 --- a/packages/plugins/okf/src/index.ts +++ b/packages/plugins/okf/src/index.ts @@ -45,7 +45,7 @@ import { GRAPH_CSS, GRAPH_JS, graphHtml } from './graph-assets.js'; export const plugin: PluginDescriptor = { name: 'okf', - version: '0.8.12', + version: '0.8.13', capabilities: ['post-build'] }; @@ -223,7 +223,7 @@ export async function onPostBuild({ config, pages, outputDir, log }: any) { for (const c of concepts) byType[c.type] = (byType[c.type] || 0) + 1; const manifest = { - okf_version: '0.8.12', + okf_version: '0.8.13', bundle: { name: bundleName, title: config.title || bundleName, description: config.description || '', url: config.url || '', generated_by: '@docmd/plugin-okf', generated_at: new Date().toISOString(), diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index 260c2f95..bb860080 100644 --- a/packages/plugins/openapi/package.json +++ b/packages/plugins/openapi/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-openapi", - "version": "0.8.12", + "version": "0.8.13", "description": "OpenAPI documentation generator plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/openapi/src/index.ts b/packages/plugins/openapi/src/index.ts index ec4be3f1..ad25e2b5 100644 --- a/packages/plugins/openapi/src/index.ts +++ b/packages/plugins/openapi/src/index.ts @@ -24,7 +24,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const plugin: PluginDescriptor = { name: 'openapi', - version: '0.8.12', + version: '0.8.13', capabilities: ['markdown', 'assets'] }; @@ -143,7 +143,7 @@ function resolveRef(ref: string, spec: OASpec): OASchema | null { return node as OASchema | null; } -function resolveSchema(schema: OASchema | undefined, spec: OASpec, depth = 0): OASchema { +function resolveSchema(schema: OASchema | undefined, spec: OASpec, _depth = 0): OASchema { if (!schema) return {}; if (schema.$ref) return resolveRef(schema.$ref, spec) || schema; return schema; @@ -195,7 +195,6 @@ function renderOperation(method: string, path_: string, op: OAOperation, spec: O let paramsHtml = ''; if (!summaryOnly && op.parameters && op.parameters.length > 0) { const rows = op.parameters.map(p => { - const r = resolveSchema(p.schema, spec); return `<tr> <td><code>${esc(p.name)}</code>${p.required ? ' <span class="oa-required">*</span>' : ''}</td> <td><span class="oa-param-in">${esc(p.in)}</span></td> @@ -274,7 +273,6 @@ function parseSpec(specPath: string): OASpec { // We avoid a full YAML dep by using JSON if possible, otherwise note the limitation try { // Try to require js-yaml if available (won't throw at import time since it's optional) - // eslint-disable-next-line @typescript-eslint/no-require-imports const yaml = require('js-yaml'); return yaml.load(raw) as OASpec; } catch { diff --git a/packages/plugins/pwa/package.json b/packages/plugins/pwa/package.json index e8fb16a0..9d5ff2ec 100644 --- a/packages/plugins/pwa/package.json +++ b/packages/plugins/pwa/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-pwa", - "version": "0.8.12", + "version": "0.8.13", "description": "Progressive Web App (PWA) plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/pwa/src/index.ts b/packages/plugins/pwa/src/index.ts index a684614a..c7f87238 100644 --- a/packages/plugins/pwa/src/index.ts +++ b/packages/plugins/pwa/src/index.ts @@ -19,7 +19,7 @@ import { attrEsc } from '@docmd/utils'; export const plugin: PluginDescriptor = { name: 'pwa', - version: '0.8.12', + version: '0.8.13', capabilities: ['post-build', 'head', 'body'] }; diff --git a/packages/plugins/search/package.json b/packages/plugins/search/package.json index 30f22780..0437e83e 100644 --- a/packages/plugins/search/package.json +++ b/packages/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-search", - "version": "0.8.12", + "version": "0.8.13", "description": "Offline full-text search for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/search/src/index.ts b/packages/plugins/search/src/index.ts index 03db95c1..a27050b5 100644 --- a/packages/plugins/search/src/index.ts +++ b/packages/plugins/search/src/index.ts @@ -28,7 +28,7 @@ const require = createRequire(import.meta.url); export const plugin: PluginDescriptor = { name: 'search', - version: '0.8.12', + version: '0.8.13', // `init` lets onConfigResolved run at config-parse time — that's where we // compute the single `searchConfig` object. The build pipeline reads // it from `config._searchConfig` everywhere else, so there's exactly diff --git a/packages/plugins/seo/package.json b/packages/plugins/seo/package.json index 748d142f..00968f4c 100644 --- a/packages/plugins/seo/package.json +++ b/packages/plugins/seo/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-seo", - "version": "0.8.12", + "version": "0.8.13", "description": "SEO meta tag generator for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/seo/src/index.ts b/packages/plugins/seo/src/index.ts index 72f46a94..646665bd 100644 --- a/packages/plugins/seo/src/index.ts +++ b/packages/plugins/seo/src/index.ts @@ -21,7 +21,7 @@ import { attrEsc } from '@docmd/utils'; export const plugin: PluginDescriptor = { name: 'seo', - version: '0.8.12', + version: '0.8.13', capabilities: ['head', 'post-build'] }; diff --git a/packages/plugins/sitemap/package.json b/packages/plugins/sitemap/package.json index d0253580..404d5f19 100644 --- a/packages/plugins/sitemap/package.json +++ b/packages/plugins/sitemap/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-sitemap", - "version": "0.8.12", + "version": "0.8.13", "description": "Sitemap generator plugin for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/plugins/sitemap/src/index.ts b/packages/plugins/sitemap/src/index.ts index 49b0f370..ccd1fef3 100644 --- a/packages/plugins/sitemap/src/index.ts +++ b/packages/plugins/sitemap/src/index.ts @@ -19,7 +19,7 @@ import { outputPathToPathname, sanitizeUrl } from '@docmd/api'; export const plugin: PluginDescriptor = { name: 'sitemap', - version: '0.8.12', + version: '0.8.13', capabilities: ['post-build'] }; diff --git a/packages/plugins/threads/package.json b/packages/plugins/threads/package.json index 687fc45e..bd7450ac 100644 --- a/packages/plugins/threads/package.json +++ b/packages/plugins/threads/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/plugin-threads", - "version": "0.8.12", + "version": "0.8.13", "type": "module", "description": "Inline discussion threads for docmd.", "main": "dist/index.js", diff --git a/packages/plugins/threads/src/index.ts b/packages/plugins/threads/src/index.ts index 5bc1cbc0..496b2f62 100644 --- a/packages/plugins/threads/src/index.ts +++ b/packages/plugins/threads/src/index.ts @@ -9,7 +9,7 @@ import type { PluginDescriptor } from '@docmd/api'; export const plugin: PluginDescriptor = { name: 'threads', - version: '0.8.12', + version: '0.8.13', capabilities: ['markdown', 'body', 'assets', 'actions', 'translations'] }; diff --git a/packages/templates/summer/package.json b/packages/templates/summer/package.json index 980e281d..ed8e1dac 100644 --- a/packages/templates/summer/package.json +++ b/packages/templates/summer/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/template-summer", - "version": "0.8.12", + "version": "0.8.13", "description": "Summer template for docmd. A bright, hopeful, summer-feel layout with a top search bar and halo accents.", "type": "module", "main": "dist/index.js", diff --git a/packages/templates/summer/src/index.ts b/packages/templates/summer/src/index.ts index af92ab28..e9efc883 100644 --- a/packages/templates/summer/src/index.ts +++ b/packages/templates/summer/src/index.ts @@ -42,7 +42,7 @@ const pathOf = (relPath: string): string => fileURLToPath(urlOf(relPath)); export const plugin: PluginDescriptor = { name: 'template-summer', - version: '0.8.12', + version: '0.8.13', capabilities: ['template'], }; diff --git a/packages/templates/summer/templates/layout.ejs b/packages/templates/summer/templates/layout.ejs index 489a938d..138f4f84 100644 --- a/packages/templates/summer/templates/layout.ejs +++ b/packages/templates/summer/templates/layout.ejs @@ -32,10 +32,6 @@ <meta name="theme-color" content="#13110d" media="(prefers-color-scheme: dark)"> <title><%= pageTitle %><% if (siteTitle && pageTitle !== siteTitle) { %> · <%= siteTitle %><% } %> - <% if (!locals.isOfflineMode && siteRootAbs && siteRootAbs !== '/') { %> - - <% } %> - diff --git a/packages/themes/package.json b/packages/themes/package.json index 98669b49..0a169193 100644 --- a/packages/themes/package.json +++ b/packages/themes/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/themes", - "version": "0.8.12", + "version": "0.8.13", "description": "Official themes for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/tui/package.json b/packages/tui/package.json index 872c031c..be865f1c 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/tui", - "version": "0.8.12", + "version": "0.8.13", "description": "Terminal User Interface (TUI) design system for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/ui/package.json b/packages/ui/package.json index 73153103..576df08f 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/ui", - "version": "0.8.12", + "version": "0.8.13", "description": "Base UI templates and assets for docmd.", "type": "module", "main": "dist/index.js", diff --git a/packages/ui/templates/layout.ejs b/packages/ui/templates/layout.ejs index 4ab487d1..80019a1b 100644 --- a/packages/ui/templates/layout.ejs +++ b/packages/ui/templates/layout.ejs @@ -46,9 +46,6 @@ <%= pageTitle %><% if (siteTitle && pageTitle !== siteTitle && !(frontmatter && frontmatter.titleAppend === false)) { %> : <%= siteTitle %><% } %> - <% if (!locals.isOfflineMode && siteRootAbs && siteRootAbs !== '/') { %> - - <% } %> <%- faviconLinkHtml || '' %> <% if (config.theme?.codeHighlight !==false) { const isDarkDefault=appearance==='dark' ; %> diff --git a/packages/utils/package.json b/packages/utils/package.json index 52adb563..70155ce8 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@docmd/utils", - "version": "0.8.12", + "version": "0.8.13", "description": "Zero-dependency shared utilities for docmd core.", "type": "module", "main": "dist/index.js", diff --git a/tests/cli-contracts/asset-base-url.test.js b/tests/cli-contracts/asset-base-url.test.js index 72c3ad1c..c79f022d 100644 --- a/tests/cli-contracts/asset-base-url.test.js +++ b/tests/cli-contracts/asset-base-url.test.js @@ -62,24 +62,24 @@ export const test = runTestFile({ emoji: '🔗', run: async () => { - // URL-1a: default layout emits a tag using the absolute - // siteRootAbs exposed by the renderer. Lock the requirement in by - // source so a future template edit can't silently break the - // no-trailing-slash case (e.g. serving `/search` resolves - // `./assets/...` to `/search/assets/...` instead of root). + // URL-1a: the tag is now centralised in the generator, NOT in + // the template. Templates must NOT emit a tag themselves — the + // generator strips any existing one and injects the canonical decision + // based on (isOfflineMode, siteRootAbs). This assertion guards that + // contract: the default layout must not contain a tag. { const layoutPath = path.resolve(import.meta.dirname, '..', '..', 'packages', 'ui', 'templates', 'layout.ejs'); const source = fs.readFileSync(layoutPath, 'utf8'); - assert(/"\s*>/.test(source), - 'URL-1a: default layout emits using the absolute site path'); + assert(!/ (generator owns it centrally)'); } - // URL-1b: same for the summer template (the user-reported 404 path). + // URL-1b: same contract for the summer template — no in template. { const layoutPath = path.resolve(import.meta.dirname, '..', '..', 'packages', 'templates', 'summer', 'templates', 'layout.ejs'); const source = fs.readFileSync(layoutPath, 'utf8'); - assert(/"\s*>/.test(source), - 'URL-1b: summer template emits for absolute path resolution'); + assert(!/ (generator owns it centrally)'); assert(/window\.DOCMD_SITE_ROOT\s*=\s*"<\%=\s*siteRootAbs\s*\%>"/.test(source), 'URL-1b: summer template sets window.DOCMD_SITE_ROOT to siteRootAbs so JS plugins (search semantic client) resolve ./ URLs correctly'); } diff --git a/tools/prep.js b/tools/prep.js index c211c545..dd65c3f6 100644 --- a/tools/prep.js +++ b/tools/prep.js @@ -133,6 +133,20 @@ function finishStep(s, status, summary) { ); } +// Same shape as finishStep() but prints a FRESH line below the streamed +// content instead of rewriting the [WAIT] line via cursor-up. Use this +// for steps whose child process has written lines of its own between +// startStep() and now, because the cursor is no longer on the WAIT +// line — finishStep()'s `\x1b[1A` would clobber an unrelated output line. +function writeVerdictLine(s, status, summary) { + const ms = Date.now() - s.startMs; + const t = ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(1)}s`; + const tag = status === 'done' + ? `${C.green}[ DONE ]${C.reset}` + : `${C.red}[ FAIL ]${C.reset}`; + console.log(`${s.bar} ${s.text.padEnd(52)}${tag} ${C.dim}${t}${C.reset} ${C.dim}${summary}${C.reset}`); +} + function run(cmd, opts = {}) { // opts.silent — when true (default), suppress output unless cmd failed. // opts.capture — return stdout/stderr as strings; never stream to the TUI. @@ -215,62 +229,6 @@ function runLint() { else if (warnings > 0) addIssue('warning', 'Lint', `${warnings} lint warning(s)`, details); } -// ── Collapsed-mode test runner ──────────────────────────────────────── -// Captures test output, parses pass/fail counts and any failure -// titles, then renders a one-line summary. Verbose mode bypasses -// the capture and streams raw output as it arrives instead. -function summariseTests(stdout) { - // tests/runner.js emits a single aggregate line at the end. - // Pattern: "Test summary: 367 passed, 0 failed across 9 files" - let m = stdout.match(/Test summary:\s+(\d+)\s+passed,\s+(\d+)\s+failed\s+across\s+(\d+)\s+files?/i); - if (m) { - return { - tests: parseInt(m[1]) + parseInt(m[2]), - pass: parseInt(m[1]), - fail: parseInt(m[2]), - units: parseInt(m[3]), - unitLabel: 'files', - failures: extractFailures(stdout), - }; - } - - // Per-package output (pnpm -r run test): each suite prints its own - // ℹ tests N / ℹ pass N / ℹ fail N block, so we sum them all up. - let tests = 0, pass = 0, fail = 0, pkgs = 0; - for (const t of stdout.matchAll(/ℹ\s+tests\s+(\d+)/g)) tests += parseInt(t[1]); - for (const p of stdout.matchAll(/ℹ\s+pass\s+(\d+)/g)) pass += parseInt(p[1]); - for (const f of stdout.matchAll(/ℹ\s+fail\s+(\d+)/g)) fail += parseInt(f[1]); - // Count distinct packages that reported a result. Look for the - // pnpm-recursive "Done" line which marks each package's end. - for (const _ of stdout.matchAll(/\bDone$/gm)) pkgs++; - // Fallback when no "Done" markers are present: count `ℹ tests` lines. - if (pkgs === 0) { - for (const _ of stdout.matchAll(/ℹ\s+tests\s+\d+/g)) pkgs++; - } - return { - tests, pass, fail, - units: pkgs, - unitLabel: pkgs === 1 ? 'package' : 'packages', - failures: extractFailures(stdout), - }; -} - -function extractFailures(stdout) { - // node:test prints "not ok N - " lines on failure. Trim - // surrounding ANSI noise and keep the title only — full diagnostics - // remain in --verbose output. - const out = []; - // Build the ANSI-stripping regex at runtime so the static linter - // doesn't flag the embedded ESC (\x1b) control character. - const ANSI_RE = new RegExp(`${String.fromCharCode(0x1b)}\\[[0-9;]*m`, 'g'); - for (const m of stdout.matchAll(/not ok \d+ - (.+)/g)) { - const t = m[1].replace(ANSI_RE, '').trim(); - if (t) out.push(t); - if (out.length >= 20) break; - } - return out; -} - function runTestStep(label, cmd, statLabel = label) { const s = startStep(label); @@ -287,27 +245,36 @@ function runTestStep(label, cmd, statLabel = label) { return; } - // Default (collapsed) mode: capture output, summarise, render one line. - const result = run(cmd, { capture: true }); - const sum = summariseTests(result.stdout + result.stderr); + // Default (collapsed) mode: STREAM LIVE so the operator sees the + // runner's own per-section TUI (each `┌─ ` is a new section + // starting, each `[ PASS ]` / `[ FAIL ]` is a section finishing). + // Previously this branch captured stdout into a buffer and printed a + // single summary line at the end — useful for clean logs but useless + // when a multi-minute test suite looks completely silent. Inheriting + // stdio lets the runner talk to the operator directly; the runner's + // own `Test summary: N passed, M failed across K files` line (printed + // inline at the end of its run) is now the canonical counts source. + // The cursor is no longer on the WAIT line after streaming, so we use + // writeVerdictLine() to print a fresh verdict line BELOW the streamed + // content instead of trying to rewrite the WAIT line in place. + let exitCode = 0; + try { + execSync(cmd, { stdio: 'inherit', maxBuffer: 64 * 1024 * 1024 }); + } catch (e) { + exitCode = e.status ?? 1; + } - if (result.ok && sum.fail === 0 && sum.tests > 0) { - finishStep(s, 'done'); - addStat(statLabel, `${sum.pass} passed across ${sum.units} ${sum.unitLabel}`, 'ok'); - } else if (result.ok && sum.tests === 0) { - // No tests ran at all (e.g. --only matched nothing). Be honest - // about that rather than printing a misleading "0 passed". - finishStep(s, 'warn'); - addStat(statLabel, 'no tests ran', 'warn'); + if (exitCode === 0) { + writeVerdictLine(s, 'done', 'all sections passed — see runner summary above'); + addStat(statLabel, 'passed (see runner output for counts)', 'ok'); } else { - const statValue = sum.fail > 0 - ? `${sum.fail} of ${sum.tests} failed across ${sum.units} ${sum.unitLabel}` - : `command exited with status ${result.status}`; - finishStep(s, 'fail'); - addStat(statLabel, statValue, 'fail'); - addIssue('error', label, - sum.fail > 0 ? `${sum.fail} test failure(s)` : 'test command failed', - sum.failures); + const statusLine = `runner exited with status ${exitCode}`; + writeVerdictLine(s, 'fail', statusLine); + addStat(statLabel, `failed (exit ${exitCode})`, 'fail'); + addIssue('error', label, 'test command failed', [ + statusLine, + 're-run with --verbose to see the full failure output inline', + ]); } } diff --git a/tools/simulate-consumer.mjs b/tools/simulate-consumer.mjs index da0cee32..c8e6f0c8 100644 --- a/tools/simulate-consumer.mjs +++ b/tools/simulate-consumer.mjs @@ -474,7 +474,9 @@ function cleanup() { } try { fs.rmSync(TMP, { recursive: true, force: true }); - } catch {} + } catch { + // intentional: best-effort temp cleanup, never fatal + } } async function main() { From d4ca3bf06d60ef5bbaef36be511cab785748004b Mon Sep 17 00:00:00 2001 From: Ghazi Date: Tue, 14 Jul 2026 02:00:17 +0530 Subject: [PATCH 3/5] feat(search): detect file:// and show helpful offline message Browsers block fetch() from file:// URLs (CORS). Previously the search modal showed a generic 'Failed to load search index.' error when a user opened site/index.html directly from the filesystem. Now the client detects window.location.protocol === 'file:' before attempting any fetch and shows a locale-aware message explaining that search requires a web server (e.g. 'npx serve site'). Added searchOffline string to en/zh/hi/ko i18n files. New data-search-offline attribute on the search modal HTML. No changes to docmd-main.js. --- packages/plugins/search/i18n/en.json | 1 + packages/plugins/search/i18n/hi.json | 1 + packages/plugins/search/i18n/ko.json | 1 + packages/plugins/search/i18n/zh.json | 1 + packages/plugins/search/src/client.ts | 13 ++++++++++++- packages/plugins/search/src/index.ts | 1 + 6 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/plugins/search/i18n/en.json b/packages/plugins/search/i18n/en.json index 130d77e0..997ef48c 100644 --- a/packages/plugins/search/i18n/en.json +++ b/packages/plugins/search/i18n/en.json @@ -2,6 +2,7 @@ "searchPlaceholder": "Search documentation...", "searchNoResults": "No results found.", "searchError": "Failed to load search index.", + "searchOffline": "Search requires a web server. Open this site via http://localhost instead of file:// to enable search.", "searchInitial": "Type to start searching...", "searchClose": "Close search", "searchNavigate": "to navigate", diff --git a/packages/plugins/search/i18n/hi.json b/packages/plugins/search/i18n/hi.json index 4332c5dd..59fccf5c 100644 --- a/packages/plugins/search/i18n/hi.json +++ b/packages/plugins/search/i18n/hi.json @@ -2,6 +2,7 @@ "searchPlaceholder": "दस्तावेज़ खोजें...", "searchNoResults": "कोई परिणाम नहीं मिला।", "searchError": "खोज अनुक्रमणिका लोड करने में विफल।", + "searchOffline": "खोज के लिए वेब सर्वर आवश्यक है। खोज सक्षम करने के लिए file:// के बजाय http://localhost से साइट खोलें।", "searchInitial": "खोजने के लिए टाइप करें...", "searchClose": "खोज बंद करें", "searchNavigate": "नेविगेट करें", diff --git a/packages/plugins/search/i18n/ko.json b/packages/plugins/search/i18n/ko.json index d6681834..8dd2fe0b 100644 --- a/packages/plugins/search/i18n/ko.json +++ b/packages/plugins/search/i18n/ko.json @@ -2,6 +2,7 @@ "searchPlaceholder": "문서 검색...", "searchNoResults": "검색 결과가 없습니다.", "searchError": "검색 색인을 불러오지 못했습니다.", + "searchOffline": "검색하려면 웹 서버가 필요합니다. file:// 대신 http://localhost로 사이트를 열어 검색을 활성화하세요.", "searchInitial": "검색어를 입력하세요...", "searchClose": "검색 닫기", "searchNavigate": "이동", diff --git a/packages/plugins/search/i18n/zh.json b/packages/plugins/search/i18n/zh.json index 17b4480b..de2582ae 100644 --- a/packages/plugins/search/i18n/zh.json +++ b/packages/plugins/search/i18n/zh.json @@ -2,6 +2,7 @@ "searchPlaceholder": "搜索文档...", "searchNoResults": "未找到结果。", "searchError": "无法加载搜索索引。", + "searchOffline": "搜索需要网页服务器。请通过 http://localhost 而非 file:// 打开站点以启用搜索。", "searchInitial": "输入开始搜索...", "searchClose": "关闭搜索", "searchNavigate": "导航", diff --git a/packages/plugins/search/src/client.ts b/packages/plugins/search/src/client.ts index 008cc001..c5b1ebb6 100644 --- a/packages/plugins/search/src/client.ts +++ b/packages/plugins/search/src/client.ts @@ -49,7 +49,8 @@ declare const MiniSearch: any; const strings = { initial: searchModal.dataset.searchInitial || 'Type to start searching...', noResults: searchModal.dataset.searchNoResults || 'No results found.', - error: searchModal.dataset.searchError || 'Failed to load search index.' + error: searchModal.dataset.searchError || 'Failed to load search index.', + offline: searchModal.dataset.searchOffline || 'Search requires a web server. Open this site via http://localhost instead of file:// to enable search.' }; // Use Site Root if available (for versioning), fallback to Context Root @@ -181,6 +182,16 @@ declare const MiniSearch: any; // 3. Index Loading - fetches locale-specific index async function loadIndex() { + // file:// detection: browsers block fetch() from file:// URLs for + // security (CORS). Show a helpful message instead of the generic + // "Failed to load" error. The user needs to serve the site via a + // local HTTP server (e.g. `npx serve site`) for search to work. + if (window.location.protocol === 'file:') { + const sanitized = `

`; + searchResults.innerHTML = sanitized; + return; + } + // Auto-detect semantic search at runtime. We check BOTH: // - The build-time hint (data-semantic="true") — set when the // build pipeline knew semantic was available at render time. diff --git a/packages/plugins/search/src/index.ts b/packages/plugins/search/src/index.ts index a27050b5..4e2dc6b3 100644 --- a/packages/plugins/search/src/index.ts +++ b/packages/plugins/search/src/index.ts @@ -975,6 +975,7 @@ export function generateScripts(config: any, options: any) { data-search-placeholder="${escape(strings.searchPlaceholder || 'Search documentation...')}" data-search-no-results="${escape(strings.searchNoResults || 'No results found.')}" data-search-error="${escape(strings.searchError || 'Failed to load search index.')}" + data-search-offline="${escape(strings.searchOffline || 'Search requires a web server. Open this site via http://localhost instead of file:// to enable search.')}" data-search-initial="${escape(strings.searchInitial || 'Type to start searching...')}" data-search-navigate="${escape(strings.searchNavigate || 'to navigate')}" data-search-escape="${escape(strings.searchEscape || 'to close')}"> From 7eeebd3836ab55060ad51a033cf825bc2a17a661 Mon Sep 17 00:00:00 2001 From: Ghazi Date: Tue, 14 Jul 2026 02:26:33 +0530 Subject: [PATCH 4/5] Update plugins.generated.json --- packages/api/registry/plugins.generated.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/registry/plugins.generated.json b/packages/api/registry/plugins.generated.json index 22834b9e..641292a8 100644 --- a/packages/api/registry/plugins.generated.json +++ b/packages/api/registry/plugins.generated.json @@ -1,6 +1,6 @@ { "$meta": { - "generatedAt": "2026-07-13T19:46:21.764Z", + "generatedAt": "2026-07-13T20:11:10.374Z", "generator": "scripts/build-plugin-registry.mjs", "packageCount": 15 }, From f94fefbfe44ac5fb660c7b2fc5510f9384c3c86d Mon Sep 17 00:00:00 2001 From: Ghazi Date: Tue, 14 Jul 2026 02:33:43 +0530 Subject: [PATCH 5/5] Update plugins.generated.json --- packages/api/registry/plugins.generated.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/registry/plugins.generated.json b/packages/api/registry/plugins.generated.json index 641292a8..01f7eaf4 100644 --- a/packages/api/registry/plugins.generated.json +++ b/packages/api/registry/plugins.generated.json @@ -1,6 +1,6 @@ { "$meta": { - "generatedAt": "2026-07-13T20:11:10.374Z", + "generatedAt": "2026-07-13T20:57:53.220Z", "generator": "scripts/build-plugin-registry.mjs", "packageCount": 15 },

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 TGp4I5D|wXHY=^AdQd<89i0(*I delta 111843 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