@omega.js/desktop 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -48
- package/dist/assets/css/core/_initialize.scss +1 -1
- package/dist/assets/js/core/app-shell.js +14 -15
- package/dist/assets/themes/_template/_theme.js +6 -6
- package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
- package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
- package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
- package/dist/assets/themes/base/_theme.js +4 -3
- package/dist/assets/themes/bootstrap/_theme.js +2 -2
- package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
- package/dist/assets/themes/classy/_theme.js +8 -6
- package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
- package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
- package/dist/assets/themes/neobrutalism/_theme.js +5 -5
- package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/assets/themes/newsflash/_theme.js +6 -6
- package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/build.js +87 -111
- package/dist/cli-run.js +4 -1
- package/dist/cli.js +3 -3
- package/dist/commands/build.js +2 -2
- package/dist/commands/cdp/capture.js +2 -2
- package/dist/commands/cdp/client.js +1 -1
- package/dist/commands/cdp/quit.js +2 -2
- package/dist/commands/cdp/relaunch.js +2 -2
- package/dist/commands/cdp/theme.js +1 -1
- package/dist/commands/cdp.js +1 -1
- package/dist/commands/clean.js +4 -5
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/dev.js +25 -0
- package/dist/commands/finalize-release.js +4 -4
- package/dist/commands/launch.js +2 -2
- package/dist/commands/lib/deploy-precheck.js +3 -3
- package/dist/commands/lib/ensure-target.js +18 -23
- package/dist/commands/lib/migrate.js +17 -0
- package/dist/commands/logs.js +1 -1
- package/dist/commands/package.js +2 -2
- package/dist/commands/publish.js +2 -2
- package/dist/commands/release.js +4 -4
- package/dist/commands/runner.js +11 -11
- package/dist/commands/sign-windows.js +5 -5
- package/dist/commands/test.js +8 -8
- package/dist/commands/update.js +7 -6
- package/dist/commands/validate-certs.js +4 -4
- package/dist/commands/version.js +3 -3
- package/dist/defaults/.github/workflows/build.yml +18 -18
- package/dist/defaults/_.gitignore +0 -2
- package/dist/defaults/_mas/README.md +3 -3
- package/dist/defaults/config/certs/README.md +1 -1
- package/dist/defaults/config/omega.json5 +43 -43
- package/dist/defaults/docs/README.md +3 -3
- package/dist/defaults/gulpfile.js +1 -1
- package/dist/defaults/hooks/build/post.js +2 -2
- package/dist/defaults/hooks/build/pre.js +2 -2
- package/dist/defaults/hooks/deploy/pre.js +1 -1
- package/dist/defaults/hooks/notarize/post.js +2 -2
- package/dist/defaults/hooks/release/post.js +2 -2
- package/dist/defaults/hooks/release/pre.js +2 -2
- package/dist/defaults/src/assets/js/components/about/index.js +3 -5
- package/dist/defaults/src/assets/js/components/main/index.js +3 -5
- package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
- package/dist/defaults/src/assets/scss/pages/about.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
- package/dist/defaults/src/integrations/context-menu/index.js +13 -13
- package/dist/defaults/src/integrations/menu/index.js +8 -8
- package/dist/defaults/src/integrations/tray/index.js +12 -12
- package/dist/defaults/src/main.js +5 -7
- package/dist/defaults/src/preload.js +4 -6
- package/dist/defaults/test/README.md +5 -5
- package/dist/defaults/test/_init.js +1 -1
- package/dist/gulp/main.js +9 -10
- package/dist/gulp/tasks/audit.js +11 -14
- package/dist/gulp/tasks/build-config.js +8 -8
- package/dist/gulp/tasks/bundle.js +16 -16
- package/dist/gulp/tasks/defaults.js +3 -3
- package/dist/gulp/tasks/distribute.js +2 -2
- package/dist/gulp/tasks/html.js +9 -9
- package/dist/gulp/tasks/package-quick.js +3 -3
- package/dist/gulp/tasks/package.js +3 -3
- package/dist/gulp/tasks/release.js +3 -3
- package/dist/gulp/tasks/sass.js +6 -6
- package/dist/gulp/tasks/serve.js +4 -4
- package/dist/hooks/notarize-artifacts.js +1 -1
- package/dist/hooks/notarize.js +1 -1
- package/dist/index.js +5 -8
- package/dist/lib/_environment-mixin.js +50 -0
- package/dist/lib/_lifecycle-mixin.js +45 -0
- package/dist/lib/analytics.js +33 -35
- package/dist/lib/app-state.js +14 -14
- package/dist/lib/auth-flow.js +18 -18
- package/dist/lib/auth-persistence.js +12 -12
- package/dist/lib/auth.js +421 -0
- package/dist/lib/auto-updater.js +49 -49
- package/dist/lib/context-menu.js +13 -13
- package/dist/lib/context.js +19 -19
- package/dist/lib/deep-link.js +34 -34
- package/dist/lib/fontawesome.js +5 -5
- package/dist/lib/ipc.js +4 -4
- package/dist/lib/menu.js +25 -25
- package/dist/lib/protocol.js +5 -5
- package/dist/lib/remote-config.js +22 -22
- package/dist/lib/remote-scripts.js +21 -21
- package/dist/lib/restart-manager/index.js +29 -29
- package/dist/lib/restart-manager/install.js +1 -1
- package/dist/lib/restart-manager/protocol.js +1 -1
- package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
- package/dist/lib/sign-helpers/sign-events.js +1 -1
- package/dist/lib/startup.js +18 -13
- package/dist/lib/storage.js +10 -10
- package/dist/lib/templating.js +16 -16
- package/dist/lib/theme.js +10 -10
- package/dist/lib/tray.js +27 -27
- package/dist/lib/usage.js +11 -11
- package/dist/lib/window-manager.js +26 -26
- package/dist/main.js +399 -483
- package/dist/preload.js +236 -176
- package/dist/renderer.js +417 -391
- package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
- package/dist/test/fixtures/consumer-app/src/main.js +5 -7
- package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
- package/dist/test/harness/boot-entry.js +22 -20
- package/dist/test/harness/main-entry.js +31 -30
- package/dist/test/harness/renderer-entry.js +5 -5
- package/dist/test/harness/renderer-preload.js +137 -141
- package/dist/test/index.js +10 -10
- package/dist/test/runner.js +2 -2
- package/dist/test/runners/boot.js +7 -6
- package/dist/test/runners/electron.js +3 -2
- package/dist/test/runners/render-event.js +2 -2
- package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
- package/dist/test/suites/boot/restart-manager.test.js +2 -2
- package/dist/test/suites/boot/storage-bundled.test.js +5 -5
- package/dist/test/suites/boot/theme.test.js +13 -13
- package/dist/test/suites/build/audit.test.js +21 -8
- package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
- package/dist/test/suites/build/boot-fixture.test.js +2 -2
- package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
- package/dist/test/suites/build/brand-scss.test.js +1 -1
- package/dist/test/suites/build/build-json-bake.test.js +1 -1
- package/dist/test/suites/build/build-workflow-jobs.test.js +2 -2
- package/dist/test/suites/build/cli.test.js +30 -2
- package/dist/test/suites/build/config-schema.test.js +5 -5
- package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +21 -7
- package/dist/test/suites/build/deploy-direct.test.js +7 -5
- package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
- package/dist/test/suites/build/deploy-hook.test.js +7 -5
- package/dist/test/suites/build/dev-verb.test.js +67 -0
- package/dist/test/suites/build/ensure-target.test.js +13 -5
- package/dist/test/suites/build/env-delivery.test.js +2 -2
- package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
- package/dist/test/suites/build/exports.test.js +9 -8
- package/dist/test/suites/build/get-config.test.js +4 -4
- package/dist/test/suites/build/manifest-deps.test.js +1 -1
- package/dist/test/suites/build/merge-line-files.test.js +7 -7
- package/dist/test/suites/build/migrate.test.js +29 -0
- package/dist/test/suites/build/omega-shell.test.js +34 -2
- package/dist/test/suites/build/omega.test.js +350 -0
- package/dist/test/suites/build/project-scripts-deps.test.js +6 -10
- package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
- package/dist/test/suites/build/runner-env-write.test.js +73 -0
- package/dist/test/suites/build/runner.test.js +11 -10
- package/dist/test/suites/build/sentry.test.js +2 -2
- package/dist/test/suites/build/setup-scripts.test.js +27 -0
- package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
- package/dist/test/suites/build/templating.test.js +3 -3
- package/dist/test/suites/build/test-stealth.test.js +7 -9
- package/dist/test/suites/build/url-helpers.test.js +55 -56
- package/dist/test/suites/build/validate-config.test.js +15 -4
- package/dist/test/suites/build/verb-logs.test.js +20 -0
- package/dist/test/suites/build/wave5-pins.test.js +2 -2
- package/dist/test/suites/main/analytics.test.js +59 -59
- package/dist/test/suites/main/app-state.test.js +66 -66
- package/dist/test/suites/main/auth-flow.test.js +41 -41
- package/dist/test/suites/main/auth-persistence.test.js +54 -43
- package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
- package/dist/test/suites/main/auth.test.js +336 -0
- package/dist/test/suites/main/auto-updater.test.js +134 -134
- package/dist/test/suites/main/boot-sequence.test.js +37 -49
- package/dist/test/suites/main/context-menu.test.js +51 -50
- package/dist/test/suites/main/context.test.js +25 -25
- package/dist/test/suites/main/deep-link.test.js +74 -74
- package/dist/test/suites/main/fontawesome.test.js +27 -27
- package/dist/test/suites/main/ipc.test.js +35 -35
- package/dist/test/suites/main/menu.test.js +101 -100
- package/dist/test/suites/main/protocol.test.js +19 -19
- package/dist/test/suites/main/remote-config.test.js +63 -63
- package/dist/test/suites/main/remote-scripts.test.js +103 -103
- package/dist/test/suites/main/request.test.js +71 -0
- package/dist/test/suites/main/restart-manager.test.js +33 -33
- package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
- package/dist/test/suites/main/startup.test.js +26 -26
- package/dist/test/suites/main/stealth-window.test.js +1 -1
- package/dist/test/suites/main/storage.test.js +25 -25
- package/dist/test/suites/main/theme.test.js +34 -34
- package/dist/test/suites/main/tray.test.js +79 -79
- package/dist/test/suites/main/url-helpers.test.js +133 -133
- package/dist/test/suites/main/usage.test.js +25 -25
- package/dist/test/suites/main/window-bounds.test.js +27 -27
- package/dist/test/suites/main/window-manager.test.js +44 -44
- package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
- package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
- package/dist/test/suites/renderer/round-trip.test.js +3 -3
- package/dist/test/suites/renderer/tooltips.test.js +15 -15
- package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +28 -8
- package/dist/test/utils/extended-mode-warning.js +1 -1
- package/dist/utils/boot-harness.js +56 -0
- package/dist/utils/build-pipeline.js +4 -4
- package/dist/utils/mode-helpers.js +2 -15
- package/dist/utils/runner-env.js +13 -28
- package/dist/utils/ship-keys.js +3 -3
- package/dist/utils/signing-status.js +51 -0
- package/dist/utils/test-events.js +7 -0
- package/dist/utils/test-stealth.js +6 -6
- package/dist/utils/url-helpers.js +52 -42
- package/dist/utils/user-agent.js +44 -0
- package/dist/vendor/account/engine.js +3 -3
- package/dist/vendor/account/index.js +14 -45
- package/dist/vendor/account/resolve-account.js +44 -0
- package/dist/vendor/account/schema.js +1 -1
- package/dist/vendor/account/user.js +99 -0
- package/dist/vendor/config/client-config.js +1 -1
- package/dist/vendor/config/company.js +46 -14
- package/dist/vendor/config/defaults.js +30 -7
- package/dist/vendor/config/edit.js +25 -3
- package/dist/vendor/config/env-delivery.js +1 -1
- package/dist/vendor/config/env-schema.js +3 -6
- package/dist/vendor/config/env.js +34 -22
- package/dist/vendor/config/environment.js +11 -30
- package/dist/vendor/config/index.js +21 -28
- package/dist/vendor/config/load.js +16 -9
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/repo.js +10 -27
- package/dist/vendor/config/schema-client.js +64 -0
- package/dist/vendor/config/schema-cloud.js +38 -0
- package/dist/vendor/config/schema-manager.js +118 -0
- package/dist/vendor/config/schema-overrides.js +68 -0
- package/dist/vendor/config/schema.js +104 -160
- package/dist/vendor/config/site-global.js +2 -3
- package/dist/vendor/config/validate.js +97 -78
- package/dist/vendor/config/winback.js +1 -1
- package/dist/vendor/devkit/actions-secrets.js +1 -1
- package/dist/vendor/devkit/agents-md.js +233 -0
- package/dist/vendor/devkit/attach-log-file.js +16 -2
- package/dist/vendor/devkit/build-json.js +1 -1
- package/dist/vendor/devkit/ci-workflows.js +30 -30
- package/dist/vendor/devkit/cli-router.js +16 -11
- package/dist/vendor/devkit/defaults-engine.js +15 -51
- package/dist/vendor/devkit/deploy-snapshot.js +44 -9
- package/dist/vendor/devkit/env-lines.js +183 -0
- package/dist/vendor/devkit/local.js +64 -10
- package/dist/vendor/devkit/lockfile.js +32 -13
- package/dist/vendor/devkit/logger.js +7 -2
- package/dist/vendor/devkit/merge-line-files.js +219 -177
- package/dist/vendor/devkit/omega-bin.js +208 -111
- package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
- package/dist/vendor/devkit/preludes/index.js +1 -0
- package/dist/vendor/devkit/target-picker.js +45 -0
- package/dist/vendor/devkit/test/dashed-files.js +37 -0
- package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
- package/dist/vendor/devkit/test/runner-core.js +6 -6
- package/dist/vendor/devkit/update.js +15 -15
- package/dist/vendor/devkit/verb-scripts.js +40 -0
- package/dist/vendor/devkit/verbs.js +170 -0
- package/dist/vendor/monitoring/env.js +2 -2
- package/dist/vendor/monitoring/index.js +1 -1
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/package.json +19 -26
- package/dist/commands/install.js +0 -37
- package/dist/defaults/AGENTS.md +0 -110
- package/dist/defaults/CLAUDE.md +0 -1
- package/dist/lib/client-bridge.js +0 -374
- package/dist/lib/logger.js +0 -4
- package/dist/test/suites/build/manager.test.js +0 -213
- package/dist/test/suites/main/client-bridge.test.js +0 -262
- package/dist/vendor/config/env-retired.js +0 -137
- package/dist/vendor/config/retired-keys.js +0 -635
- package/docs/analytics.md +0 -140
- package/docs/app-state.md +0 -92
- package/docs/audit.md +0 -69
- package/docs/auto-updater.md +0 -243
- package/docs/boot-sequence.md +0 -39
- package/docs/build-system.md +0 -169
- package/docs/cdp-debugging.md +0 -169
- package/docs/client-bridge.md +0 -269
- package/docs/common-mistakes.md +0 -21
- package/docs/config-schema.md +0 -120
- package/docs/context-menu.md +0 -112
- package/docs/context.md +0 -81
- package/docs/css.md +0 -90
- package/docs/deep-link.md +0 -186
- package/docs/environment-detection.md +0 -112
- package/docs/fontawesome.md +0 -107
- package/docs/hooks.md +0 -89
- package/docs/icons.md +0 -79
- package/docs/index.md +0 -317
- package/docs/installer-options.md +0 -165
- package/docs/ipc.md +0 -61
- package/docs/lib-modules.md +0 -53
- package/docs/logging.md +0 -229
- package/docs/menu.md +0 -160
- package/docs/releasing.md +0 -239
- package/docs/remote-config.md +0 -118
- package/docs/remote-scripts.md +0 -144
- package/docs/restart-manager.md +0 -144
- package/docs/runner.md +0 -290
- package/docs/sentry.md +0 -97
- package/docs/shared/agent-docs.md +0 -89
- package/docs/shared/analytics.md +0 -612
- package/docs/shared/brands.md +0 -57
- package/docs/shared/breaking-changes.md +0 -851
- package/docs/shared/config.md +0 -1952
- package/docs/shared/deploys.md +0 -341
- package/docs/shared/icons.md +0 -219
- package/docs/shared/local-dev.md +0 -167
- package/docs/shared/logging.md +0 -205
- package/docs/shared/monitoring.md +0 -167
- package/docs/shared/publishing.md +0 -187
- package/docs/shared/rulings.md +0 -34
- package/docs/shared/testing.md +0 -147
- package/docs/shared/theming.md +0 -629
- package/docs/shared/translation.md +0 -333
- package/docs/shared/updates.md +0 -61
- package/docs/signing.md +0 -293
- package/docs/startup.md +0 -142
- package/docs/storage.md +0 -59
- package/docs/templating.md +0 -101
- package/docs/test-boot-layer.md +0 -157
- package/docs/test-framework.md +0 -362
- package/docs/themes.md +0 -149
- package/docs/tooltips.md +0 -99
- package/docs/tray.md +0 -164
- package/docs/usage.md +0 -58
- package/docs/verts.md +0 -62
- package/docs/windows.md +0 -149
|
@@ -1,73 +1,87 @@
|
|
|
1
|
-
// Merge line-based files (.env, .gitignore, AGENTS.md)
|
|
2
|
-
// the OMEGA marker
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Convention (the ONE OMEGA marker grammar — `<comment> ========== <Label> ==========`,
|
|
10
|
-
// comment token per file type; the rules-file managed block is the `//` flavor of the
|
|
11
|
-
// same family, owned by @omega.js/backend — see _attic/plans/archive/marker-harmonization.md):
|
|
12
|
-
//
|
|
13
|
-
// # ========== Default Values ==========
|
|
14
|
-
// # framework-managed; overwritten on every setup
|
|
15
|
-
// KEY1=
|
|
16
|
-
// KEY2="value with spaces"
|
|
17
|
-
//
|
|
18
|
-
// # ========== Custom Values ==========
|
|
19
|
-
// # user's section; preserved verbatim across setups
|
|
20
|
-
// USER_SECRET="my-secret"
|
|
21
|
-
//
|
|
22
|
-
// Behavior:
|
|
23
|
-
// - The Default section is replaced with the new framework's defaults.
|
|
24
|
-
// - Keys that already had values (in either Default or Custom) keep those values
|
|
25
|
-
// in the same section they were in.
|
|
26
|
-
// - The Default section is COMPLETELY managed ([#926](https://github.com/Omega-JS-Stack/omega/issues/926)):
|
|
27
|
-
// a line the new framework block no longer carries LEAVES the consumer, so a
|
|
28
|
-
// rule the framework retires or rewrites actually takes effect everywhere. A
|
|
29
|
-
// retired framework line and a line a user typed inside the framework block
|
|
30
|
-
// cannot be told apart, and the block header already says it is overwritten on
|
|
31
|
-
// every setup, so `.gitignore` and `AGENTS.md` drop it. Lines a user owns
|
|
32
|
-
// belong under the Custom marker, which stays verbatim.
|
|
33
|
-
// - .env is the one exception: a retired key holding a NON-EMPTY value migrates
|
|
34
|
-
// to the Custom section (that value is data, not a rule), while an empty
|
|
35
|
-
// retired key (`KEY=` / `KEY=""`) drops like any other retired line.
|
|
36
|
-
// - .env values are normalized to **double-quoted** form on every merge:
|
|
37
|
-
// KEY=raw-value → KEY="raw-value"
|
|
38
|
-
// KEY="already-quoted" → KEY="already-quoted" (left alone)
|
|
39
|
-
// KEY= → KEY= (empty stays empty/unquoted)
|
|
40
|
-
// This protects values containing spaces, #, $, or other shell-meaningful chars.
|
|
41
|
-
// - .env COMMENTED PLACEHOLDERS (`# KEY=` in the template's Default section)
|
|
42
|
-
// mark keys the framework knows but ships no value for (the env cascade
|
|
43
|
-
// supplies values from stronger layers — dogfood friction #20). On merge:
|
|
44
|
-
// an existing NON-EMPTY value for that key (either section) keeps its line
|
|
45
|
-
// in Default; an existing EMPTY value (`KEY=` / `KEY=""`) converges to the
|
|
46
|
-
// commented placeholder instead of migrating to Custom.
|
|
47
|
-
// - .gitignore: same logic, line-based instead of key-based (no quoting).
|
|
48
|
-
// - AGENTS.md: same logic as .gitignore (line-based, no quoting). The markers
|
|
49
|
-
// render as visible H1 headings in markdown — that's intentional UX.
|
|
50
|
-
// - First setup (no existing file): the framework template lands as-is.
|
|
1
|
+
// Merge line-based files (.env, .gitignore, .gitattributes, AGENTS.md) through
|
|
2
|
+
// the OMEGA marker sections: the framework rewrites Default on every run, the
|
|
3
|
+
// consumer's Custom stays verbatim, and a file with no markers yet converges
|
|
4
|
+
// once, its consumer lines landing under Custom. The protocol (the grammar and its
|
|
5
|
+
// flavors, the .env value rules, placeholders, promotion, the first converge)
|
|
6
|
+
// lives in docs/devkit/index.md.
|
|
7
|
+
|
|
8
|
+
const { joinEnvUnits, envKey, normalizeEnvLine, findKeyLine, parsePlaceholderKey, isMachineComment, envValueIsEmpty } = require('./env-lines');
|
|
51
9
|
|
|
52
10
|
const DEFAULT_MARKER = '# ========== Default Values ==========';
|
|
53
11
|
const CUSTOM_MARKER = '# ========== Custom Values ==========';
|
|
54
12
|
|
|
13
|
+
// The markdown flavor of the one grammar: an HTML comment renders as nothing.
|
|
14
|
+
const MARKDOWN_DEFAULT_MARKER = '<!-- ========== Default Values ========== -->';
|
|
15
|
+
const MARKDOWN_CUSTOM_MARKER = '<!-- ========== Custom Values ========== -->';
|
|
16
|
+
|
|
17
|
+
// Framework text earlier generations wrote, one pattern per line, each block
|
|
18
|
+
// scoped to the file type that shipped it: Custom boilerplate (the retired
|
|
19
|
+
// per-framework AGENTS.md's included), and old .env headers and group notes,
|
|
20
|
+
// which only an unmarked .env's first converge strips.
|
|
21
|
+
const SHIPPED = [
|
|
22
|
+
{ file: '.gitignore', lines: [/^# Add your custom ignore patterns below this line$/, /^# \.\.\.$/] },
|
|
23
|
+
{ file: '.gitignore', lines: [/^# Add your own ignores below\. This section is preserved across (framework re-syncs|`npx omega setup` runs|`npx mgr setup` runs)\.$/] },
|
|
24
|
+
{ file: '.gitignore', lines: [/^# \.\.\.$/] },
|
|
25
|
+
{ file: 'AGENTS.md', lines: [/^## Project-specific notes$/, /^Add anything specific to THIS project here\. Edits below this line are preserved across (runs|framework re-syncs|`npx omega setup` runs)\.$/] },
|
|
26
|
+
{ file: 'AGENTS.md', lines: [/^<!-- Add your project-specific notes below this line -->$/] },
|
|
27
|
+
{
|
|
28
|
+
file: '.env',
|
|
29
|
+
lines: [
|
|
30
|
+
/^# .+(?: \u2014|:) brand secrets \(gitignored; loaded before every omega(?:-manager)? run\)\.$/,
|
|
31
|
+
/^# Uncomment and fill what this brand uses\. Services without their credentials$/,
|
|
32
|
+
/^# skip cleanly, so add these as the brand adopts each service\.$/,
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
file: '.env',
|
|
37
|
+
lines: [
|
|
38
|
+
/^# .+(?: \u2014|:) COMPANY secrets \(gitignored; loaded UNDER every (?:managed brand's own \.env|brand of this company)\)\.$/,
|
|
39
|
+
/^# Precedence: shell env > brand \.env > this file\. Put here only what every brand$/,
|
|
40
|
+
/^# shares(?: \u2014 anything|\. Anything) brand-specific belongs in that brand's \.env, never here\.$/,
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
file: '.env',
|
|
45
|
+
lines: [
|
|
46
|
+
/^# one per stream; disperse composes each target its own GOOGLE_ANALYTICS_SECRET\), and the$/,
|
|
47
|
+
/^# Auto-generated and persisted here on the first real run \u2014 leave unset:$/,
|
|
48
|
+
/^# ACCOUNT_PASSWORD_SEED, CSC_KEY_PASSWORD$/,
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
|
|
55
53
|
function mergeLineBasedFiles(existingContent, newContent, fileName) {
|
|
56
54
|
const isEnvFile = fileName === '.env';
|
|
55
|
+
const markers = sectionMarkers(fileName);
|
|
57
56
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
= splitSections(existingLines, isEnvFile);
|
|
57
|
+
const hasMarkers = hasSectionMarkers(existingContent, fileName);
|
|
58
|
+
// .env merges by logical line: a quoted value spanning lines is one unit
|
|
59
|
+
const toLines = (content) => (isEnvFile ? joinEnvUnits(content.split('\n')) : content.split('\n'));
|
|
60
|
+
const existingLines = toLines(existingContent);
|
|
61
|
+
const newLines = toLines(newContent);
|
|
64
62
|
|
|
65
63
|
// Parse new content. We only use its default section (custom is the user's domain).
|
|
66
|
-
const { defaultLines: newDefault
|
|
64
|
+
const { defaultLines: newDefault } = splitSections(newLines, markers);
|
|
65
|
+
const newDefaultKeys = new Set(isEnvFile ? newDefault.map((line) => envKey(line) || parsePlaceholderKey(line.trim())).filter(Boolean) : []);
|
|
66
|
+
|
|
67
|
+
let existingDefault = [];
|
|
68
|
+
let existingCustom = [];
|
|
69
|
+
if (hasMarkers) {
|
|
70
|
+
const sections = splitSections(existingLines, markers);
|
|
71
|
+
existingDefault = sections.defaultLines;
|
|
72
|
+
const shipped = !isEnvFile && isShippedBlock(sections.customLines, fileName);
|
|
73
|
+
existingCustom = withPreamble(sections.preamble, shipped ? [''] : sections.customLines);
|
|
74
|
+
} else if (isEnvFile) {
|
|
75
|
+
existingDefault = existingLines.filter((line) => !isMarkerLine(line, markers));
|
|
76
|
+
} else {
|
|
77
|
+
existingCustom = convergeUnmarked(existingLines, newDefault, markers, fileName);
|
|
78
|
+
}
|
|
79
|
+
const keysOf = (lines) => new Set(isEnvFile ? lines.map(envKey).filter(Boolean) : []);
|
|
80
|
+
const existingDefaultKeys = keysOf(existingDefault);
|
|
81
|
+
const existingCustomKeys = keysOf(existingCustom);
|
|
67
82
|
|
|
68
83
|
// Build the merged default section: walk new defaults in order, substituting the
|
|
69
84
|
// user's existing value for any key they had set in either section.
|
|
70
|
-
const newDefaultKeys = new Set();
|
|
71
85
|
const mergedDefault = [];
|
|
72
86
|
const emit = (line) => mergedDefault.push(isEnvFile ? normalizeEnvLine(line) : line);
|
|
73
87
|
|
|
@@ -75,9 +89,8 @@ function mergeLineBasedFiles(existingContent, newContent, fileName) {
|
|
|
75
89
|
const trimmed = line.trim();
|
|
76
90
|
|
|
77
91
|
if (isEnvFile && trimmed && !trimmed.startsWith('#')) {
|
|
78
|
-
const key =
|
|
92
|
+
const key = envKey(line);
|
|
79
93
|
if (key) {
|
|
80
|
-
newDefaultKeys.add(key);
|
|
81
94
|
if (existingDefaultKeys.has(key)) {
|
|
82
95
|
emit(findKeyLine(existingDefault, key));
|
|
83
96
|
continue;
|
|
@@ -95,13 +108,11 @@ function mergeLineBasedFiles(existingContent, newContent, fileName) {
|
|
|
95
108
|
// .gitignore: just keep the new line.
|
|
96
109
|
mergedDefault.push(line);
|
|
97
110
|
} else {
|
|
98
|
-
// Comment
|
|
111
|
+
// Comment or blank. For .env, a `# KEY=""` placeholder claims the key:
|
|
99
112
|
// an existing set value keeps its line, an empty one converges away.
|
|
100
113
|
const placeholderKey = isEnvFile ? parsePlaceholderKey(trimmed) : null;
|
|
101
114
|
|
|
102
115
|
if (placeholderKey) {
|
|
103
|
-
newDefaultKeys.add(placeholderKey);
|
|
104
|
-
|
|
105
116
|
const existingLine = existingDefaultKeys.has(placeholderKey)
|
|
106
117
|
? findKeyLine(existingDefault, placeholderKey)
|
|
107
118
|
: existingCustomKeys.has(placeholderKey)
|
|
@@ -118,159 +129,175 @@ function mergeLineBasedFiles(existingContent, newContent, fileName) {
|
|
|
118
129
|
}
|
|
119
130
|
}
|
|
120
131
|
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const key = trimmed.split('=')[0].trim();
|
|
135
|
-
if (key && !newDefaultKeys.has(key) && !existingCustomKeys.has(key) && !envValueIsEmpty(trimmed)) {
|
|
136
|
-
migratedToCustom.push(normalizeEnvLine(line));
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// The user's Custom section is preserved — except (a) .env values get normalized
|
|
142
|
-
// to double-quoted form for consistent quoting, and (b) any key that was promoted
|
|
143
|
-
// UP into the Default section above is dropped here so it isn't duplicated. Keys
|
|
144
|
-
// present in BOTH sections are NOT dropped (the Default copy's value won there,
|
|
145
|
-
// so removing the Custom copy would silently change dotenv's effective value).
|
|
132
|
+
// A line the new framework block does not carry drops, except an .env key
|
|
133
|
+
// holding a value: the consumer's data, so it moves under Custom. An unmarked
|
|
134
|
+
// .env's first converge also carries every consumer comment there.
|
|
135
|
+
const known = new Set([...newDefaultKeys, ...existingCustomKeys]);
|
|
136
|
+
const migratedToCustom = !isEnvFile
|
|
137
|
+
? []
|
|
138
|
+
: hasMarkers
|
|
139
|
+
? existingDefault.filter((line) => isValuedUnknown(line, known)).map(normalizeEnvLine)
|
|
140
|
+
: convergeUnmarkedEnv(existingDefault, newDefault, known);
|
|
141
|
+
|
|
142
|
+
// Custom stays verbatim but for .env quoting and dropping a key promoted UP
|
|
143
|
+
// into Default. A key set in both sections keeps both lines: dotenv reads the
|
|
144
|
+
// last one, the Custom line, so dropping it would change the value.
|
|
146
145
|
const finalCustom = isEnvFile
|
|
147
146
|
? existingCustom
|
|
148
147
|
.filter((line) => {
|
|
149
148
|
const trimmed = line.trim();
|
|
150
149
|
if (!trimmed || trimmed.startsWith('#')) return true;
|
|
151
|
-
const key =
|
|
150
|
+
const key = envKey(line);
|
|
152
151
|
return !(key && newDefaultKeys.has(key) && !existingDefaultKeys.has(key));
|
|
153
152
|
})
|
|
154
153
|
.map((line) => normalizeEnvLine(line))
|
|
155
154
|
: existingCustom;
|
|
156
155
|
|
|
157
156
|
const result = [];
|
|
158
|
-
result.push(
|
|
157
|
+
result.push(markers.defaultMarker);
|
|
159
158
|
result.push(...mergedDefault);
|
|
160
159
|
// Insert a single blank line before CUSTOM_MARKER, but only if the merged default
|
|
161
160
|
// doesn't already end with one (otherwise we'd accumulate an extra blank line on
|
|
162
|
-
// every merge
|
|
161
|
+
// every merge, breaking idempotency on the first re-run after a fresh `jetpack.copy`).
|
|
163
162
|
if (mergedDefault.length === 0 || mergedDefault[mergedDefault.length - 1].trim() !== '') {
|
|
164
163
|
result.push('');
|
|
165
164
|
}
|
|
166
|
-
result.push(
|
|
165
|
+
result.push(markers.customMarker);
|
|
167
166
|
if (migratedToCustom.length > 0) {
|
|
168
167
|
result.push(...migratedToCustom);
|
|
169
168
|
}
|
|
170
169
|
result.push(...finalCustom);
|
|
170
|
+
// A converged file ends on a newline like every marked one
|
|
171
|
+
if (!hasMarkers && result[result.length - 1] !== '') {
|
|
172
|
+
result.push('');
|
|
173
|
+
}
|
|
171
174
|
|
|
172
175
|
return result.join('\n');
|
|
173
176
|
}
|
|
174
177
|
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
178
|
+
// Split a file on its marker lines: the lines above the first marker, the
|
|
179
|
+
// Default section and the Custom section.
|
|
180
|
+
function splitSections(lines, markers) {
|
|
181
|
+
const sections = { preamble: [], defaultLines: [], customLines: [] };
|
|
182
|
+
let into = sections.preamble;
|
|
183
|
+
for (const line of lines) {
|
|
184
|
+
const trimmed = line.trim();
|
|
185
|
+
if (trimmed === markers.defaultMarker) { into = sections.defaultLines; continue; }
|
|
186
|
+
if (trimmed === markers.customMarker) { into = sections.customLines; continue; }
|
|
187
|
+
into.push(line);
|
|
188
|
+
}
|
|
189
|
+
return sections;
|
|
190
|
+
}
|
|
183
191
|
|
|
184
|
-
|
|
192
|
+
function isMarkerLine(line, markers) {
|
|
185
193
|
const trimmed = line.trim();
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// Capture leading whitespace so we don't lose indentation.
|
|
189
|
-
const leadingMatch = line.match(/^(\s*)/);
|
|
190
|
-
const leading = leadingMatch ? leadingMatch[1] : '';
|
|
194
|
+
return trimmed === markers.defaultMarker || trimmed === markers.customMarker;
|
|
195
|
+
}
|
|
191
196
|
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
// Blank lines at either end dropped, a run of blanks inside collapsed to one.
|
|
198
|
+
function tidyParagraphs(lines) {
|
|
199
|
+
const tidy = [];
|
|
200
|
+
for (const line of lines) {
|
|
201
|
+
if (!line.trim() && (tidy.length === 0 || !tidy[tidy.length - 1].trim())) continue;
|
|
202
|
+
tidy.push(line);
|
|
203
|
+
}
|
|
204
|
+
if (tidy.length > 0 && !tidy[tidy.length - 1].trim()) tidy.pop();
|
|
205
|
+
return tidy;
|
|
206
|
+
}
|
|
194
207
|
|
|
195
|
-
|
|
196
|
-
|
|
208
|
+
// A marked file's lines above its Default marker open its Custom section.
|
|
209
|
+
function withPreamble(preamble, custom) {
|
|
210
|
+
const lead = tidyParagraphs(preamble);
|
|
211
|
+
if (lead.length === 0) return custom;
|
|
212
|
+
const start = custom.findIndex((line) => line.trim());
|
|
213
|
+
return start < 0 ? [...lead, ''] : [...lead, '', ...custom.slice(start)];
|
|
214
|
+
}
|
|
197
215
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
216
|
+
// A marker-less file's first converge: paragraph by paragraph, a line the new
|
|
217
|
+
// framework block carries is the framework's, a paragraph whose every entry is
|
|
218
|
+
// one goes whole (its comments were a framework header), and the rest land
|
|
219
|
+
// under Custom in order, one blank line between paragraphs.
|
|
220
|
+
function convergeUnmarked(lines, newDefault, markers, fileName) {
|
|
221
|
+
const framework = new Set(newDefault.map((line) => line.trim()).filter(Boolean));
|
|
222
|
+
// The grammar's comment token opens every marker: `#`, or `<!--` in markdown
|
|
223
|
+
const commentToken = markers.defaultMarker.split(' ')[0];
|
|
224
|
+
const paragraphs = [[]];
|
|
225
|
+
for (const line of lines) {
|
|
226
|
+
const trimmed = line.trim();
|
|
227
|
+
if (isMarkerLine(line, markers)) continue;
|
|
228
|
+
if (trimmed) paragraphs[paragraphs.length - 1].push(line);
|
|
229
|
+
else if (paragraphs[paragraphs.length - 1].length > 0) paragraphs.push([]);
|
|
202
230
|
}
|
|
203
231
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
232
|
+
const custom = [];
|
|
233
|
+
for (const paragraph of paragraphs) {
|
|
234
|
+
const entries = paragraph.filter((line) => !line.trim().startsWith(commentToken));
|
|
235
|
+
if (entries.length > 0 && entries.every((line) => framework.has(line.trim()))) continue;
|
|
208
236
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
237
|
+
const kept = paragraph.filter((line) => !framework.has(line.trim()) && !isShipped(line, fileName));
|
|
238
|
+
if (kept.length === 0) continue;
|
|
239
|
+
if (custom.length > 0) custom.push('');
|
|
240
|
+
custom.push(...kept);
|
|
213
241
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return `${leading}${key}="${escapeForDoubleQuote(value)}"`;
|
|
242
|
+
custom.push('');
|
|
243
|
+
return custom;
|
|
217
244
|
}
|
|
218
245
|
|
|
219
|
-
|
|
220
|
-
|
|
246
|
+
// An .env key the framework block does not know, holding a value.
|
|
247
|
+
function isValuedUnknown(line, known) {
|
|
248
|
+
const key = envKey(line);
|
|
249
|
+
return Boolean(key) && !known.has(key) && !envValueIsEmpty(line.trim());
|
|
221
250
|
}
|
|
222
251
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
let
|
|
252
|
+
// An unmarked .env's first converge, in file order with its paragraphs: every
|
|
253
|
+
// comment but the framework's own and a run directly above a known key or its
|
|
254
|
+
// placeholder, and every valued key the framework block does not know.
|
|
255
|
+
function convergeUnmarkedEnv(lines, newDefault, known) {
|
|
256
|
+
const framework = new Set(newDefault.map((line) => line.trim()).filter(Boolean));
|
|
257
|
+
const kept = [];
|
|
258
|
+
let run = [];
|
|
230
259
|
for (const line of lines) {
|
|
231
260
|
const trimmed = line.trim();
|
|
232
|
-
if (trimmed
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
// Lines before any marker are treated as default (legacy / fresh files).
|
|
236
|
-
if (mode === 'custom') {
|
|
237
|
-
customLines.push(line);
|
|
238
|
-
if (isEnvFile && trimmed && !trimmed.startsWith('#')) {
|
|
239
|
-
const key = trimmed.split('=')[0].trim();
|
|
240
|
-
if (key) existingCustomKeys.add(key);
|
|
241
|
-
}
|
|
242
|
-
} else {
|
|
243
|
-
defaultLines.push(line);
|
|
244
|
-
if (isEnvFile && trimmed && !trimmed.startsWith('#')) {
|
|
245
|
-
const key = trimmed.split('=')[0].trim();
|
|
246
|
-
if (key) existingDefaultKeys.add(key);
|
|
247
|
-
}
|
|
261
|
+
if (trimmed.startsWith('#') && !isMachineComment(trimmed) && !framework.has(trimmed)) {
|
|
262
|
+
if (!isShipped(line, '.env')) run.push(line);
|
|
263
|
+
continue;
|
|
248
264
|
}
|
|
265
|
+
const key = envKey(line) || parsePlaceholderKey(trimmed);
|
|
266
|
+
if (!key || !known.has(key)) kept.push(...run);
|
|
267
|
+
if (isValuedUnknown(line, known)) kept.push(normalizeEnvLine(line));
|
|
268
|
+
if (!trimmed) kept.push('');
|
|
269
|
+
run = [];
|
|
249
270
|
}
|
|
250
|
-
|
|
251
|
-
return
|
|
271
|
+
kept.push(...run);
|
|
272
|
+
return tidyParagraphs(kept);
|
|
252
273
|
}
|
|
253
274
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Is this line framework text an earlier generation shipped in this file type?
|
|
277
|
+
* @param {string} line
|
|
278
|
+
* @param {string} fileName - The file's name (e.g. `.gitignore`, `AGENTS.md`, `.env`)
|
|
279
|
+
* @returns {boolean}
|
|
280
|
+
*/
|
|
281
|
+
function isShipped(line, fileName) {
|
|
282
|
+
return SHIPPED.some((entry) => entry.file === fileName && entry.lines.some((shipped) => shipped.test(line.trim())));
|
|
260
283
|
}
|
|
261
284
|
|
|
262
|
-
//
|
|
263
|
-
function
|
|
264
|
-
const
|
|
265
|
-
return
|
|
285
|
+
// Is this Custom section exactly one block this file type shipped?
|
|
286
|
+
function isShippedBlock(lines, fileName) {
|
|
287
|
+
const body = lines.map((line) => line.trim()).filter(Boolean);
|
|
288
|
+
return SHIPPED.some((entry) => entry.file === fileName && entry.lines.length === body.length && entry.lines.every((shipped, i) => shipped.test(body[i])));
|
|
266
289
|
}
|
|
267
290
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
291
|
+
/**
|
|
292
|
+
* The marker pair a file speaks, by file type: markdown takes the HTML-comment
|
|
293
|
+
* flavor of the one grammar, every other line file the `#` flavor.
|
|
294
|
+
* @param {string} [fileName] - The file's name (e.g. `AGENTS.md`, `.gitignore`)
|
|
295
|
+
* @returns {{ defaultMarker: string, customMarker: string }}
|
|
296
|
+
*/
|
|
297
|
+
function sectionMarkers(fileName) {
|
|
298
|
+
return typeof fileName === 'string' && fileName.endsWith('.md')
|
|
299
|
+
? { defaultMarker: MARKDOWN_DEFAULT_MARKER, customMarker: MARKDOWN_CUSTOM_MARKER }
|
|
300
|
+
: { defaultMarker: DEFAULT_MARKER, customMarker: CUSTOM_MARKER };
|
|
274
301
|
}
|
|
275
302
|
|
|
276
303
|
/**
|
|
@@ -278,26 +305,41 @@ function envValueIsEmpty(line) {
|
|
|
278
305
|
* through the merge protocol at least once). Setup validators use this to
|
|
279
306
|
* distinguish legacy/no-marker files from protocol-managed ones.
|
|
280
307
|
* @param {string} content
|
|
308
|
+
* @param {string} [fileName] - Selects the marker flavor (default: the `#` flavor)
|
|
281
309
|
* @returns {boolean}
|
|
282
310
|
*/
|
|
283
|
-
function hasSectionMarkers(content) {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
311
|
+
function hasSectionMarkers(content, fileName) {
|
|
312
|
+
if (typeof content !== 'string') return false;
|
|
313
|
+
const { defaultMarker, customMarker } = sectionMarkers(fileName);
|
|
314
|
+
const lines = content.split('\n').map((line) => line.trim());
|
|
315
|
+
const at = lines.indexOf(defaultMarker);
|
|
316
|
+
return at >= 0 && lines.indexOf(customMarker, at + 1) > at;
|
|
287
317
|
}
|
|
288
318
|
|
|
289
319
|
/**
|
|
290
320
|
* Extract the consumer-owned Custom section of a marker file (everything after
|
|
291
|
-
* the Custom marker), or '' when there is no marker. The defaults engine's
|
|
321
|
+
* the Custom marker line), or '' when there is no marker. The defaults engine's
|
|
292
322
|
* `retire` rule uses this to judge whether a per-target doc carries consumer
|
|
293
323
|
* content or is framework-owned-only.
|
|
294
324
|
* @param {string} content
|
|
325
|
+
* @param {string} [fileName] - Selects the marker flavor (default: the `#` flavor)
|
|
295
326
|
* @returns {string}
|
|
296
327
|
*/
|
|
297
|
-
function getCustomSection(content) {
|
|
328
|
+
function getCustomSection(content, fileName) {
|
|
298
329
|
if (typeof content !== 'string') return '';
|
|
299
|
-
const
|
|
300
|
-
|
|
330
|
+
const { customMarker } = sectionMarkers(fileName);
|
|
331
|
+
const lines = content.split('\n');
|
|
332
|
+
const at = lines.findIndex((line) => line.trim() === customMarker);
|
|
333
|
+
return at < 0 ? '' : ['', ...lines.slice(at + 1)].join('\n');
|
|
301
334
|
}
|
|
302
335
|
|
|
303
|
-
module.exports = {
|
|
336
|
+
module.exports = {
|
|
337
|
+
mergeLineBasedFiles,
|
|
338
|
+
normalizeEnvLine,
|
|
339
|
+
hasSectionMarkers,
|
|
340
|
+
getCustomSection,
|
|
341
|
+
sectionMarkers,
|
|
342
|
+
isShipped,
|
|
343
|
+
DEFAULT_MARKER,
|
|
344
|
+
CUSTOM_MARKER,
|
|
345
|
+
};
|