@mdfriday/foundry 25.11.12 → 25.11.13
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/dist/index.d.ts +0 -1
- package/dist/index.js +2 -12
- package/dist/internal/application/incremental-build-coordinator.d.ts +3 -32
- package/dist/internal/application/incremental-ssg.d.ts +0 -5
- package/dist/internal/application/ssg.d.ts +7 -23
- package/dist/internal/domain/config/entity/config.d.ts +1 -36
- package/dist/internal/domain/config/entity/dir.d.ts +0 -1
- package/dist/internal/domain/config/entity/language.d.ts +0 -52
- package/dist/internal/domain/config/entity/module.d.ts +0 -37
- package/dist/internal/domain/config/entity/root.d.ts +0 -40
- package/dist/internal/domain/config/entity/service.d.ts +0 -37
- package/dist/internal/domain/config/entity/social.d.ts +0 -44
- package/dist/internal/domain/config/entity/taxonomy.d.ts +0 -40
- package/dist/internal/domain/config/factory/config.d.ts +1 -5
- package/dist/internal/domain/config/factory/loader.d.ts +0 -25
- package/dist/internal/domain/config/factory/provider.d.ts +0 -11
- package/dist/internal/domain/config/factory/sourcedescriptor.d.ts +1 -14
- package/dist/internal/domain/config/index.d.ts +0 -1
- package/dist/internal/domain/config/tests/mock-fs.d.ts +1 -2
- package/dist/internal/domain/config/type.d.ts +0 -49
- package/dist/internal/domain/config/vo/language.d.ts +0 -7
- package/dist/internal/domain/config/vo/module.d.ts +0 -10
- package/dist/internal/domain/config/vo/root.d.ts +0 -7
- package/dist/internal/domain/config/vo/service.d.ts +0 -7
- package/dist/internal/domain/config/vo/social.d.ts +0 -17
- package/dist/internal/domain/config/vo/taxonomy.d.ts +0 -13
- package/dist/internal/domain/content/entity/content.d.ts +1 -38
- package/dist/internal/domain/content/entity/converter.d.ts +2 -3
- package/dist/internal/domain/content/entity/index.d.ts +0 -1
- package/dist/internal/domain/content/entity/page.d.ts +8 -13
- package/dist/internal/domain/content/entity/pagebuilder.d.ts +0 -84
- package/dist/internal/domain/content/entity/pagecollector.d.ts +1 -5
- package/dist/internal/domain/content/entity/pagecontent.d.ts +1 -16
- package/dist/internal/domain/content/entity/pagelayout.d.ts +0 -1
- package/dist/internal/domain/content/entity/pagemap.d.ts +1 -71
- package/dist/internal/domain/content/entity/pagemeta.d.ts +1 -2
- package/dist/internal/domain/content/entity/pageoutput.d.ts +3 -4
- package/dist/internal/domain/content/entity/pagesource.d.ts +0 -38
- package/dist/internal/domain/content/entity/pagetrees.d.ts +1 -14
- package/dist/internal/domain/content/entity/paginator.d.ts +1 -21
- package/dist/internal/domain/content/entity/section.d.ts +1 -17
- package/dist/internal/domain/content/entity/shifter.d.ts +1 -2
- package/dist/internal/domain/content/entity/shifterpage.d.ts +1 -2
- package/dist/internal/domain/content/entity/shifterpagesource.d.ts +1 -2
- package/dist/internal/domain/content/entity/shortcode.d.ts +1 -41
- package/dist/internal/domain/content/entity/standalone.d.ts +1 -11
- package/dist/internal/domain/content/entity/taxonomy.d.ts +1 -17
- package/dist/internal/domain/content/entity/term.d.ts +1 -8
- package/dist/internal/domain/content/entity/translator.d.ts +0 -23
- package/dist/internal/domain/content/factory/hub.d.ts +0 -1
- package/dist/internal/domain/content/index.d.ts +0 -1
- package/dist/internal/domain/content/type.d.ts +4 -11
- package/dist/internal/domain/content/vo/classifier.d.ts +0 -25
- package/dist/internal/domain/content/vo/fileinfo.d.ts +2 -3
- package/dist/internal/domain/content/vo/frontmatter.d.ts +0 -66
- package/dist/internal/domain/content/vo/identity.d.ts +0 -1
- package/dist/internal/domain/content/vo/kind.d.ts +0 -11
- package/dist/internal/domain/content/vo/sort.d.ts +0 -13
- package/dist/internal/domain/fs/entity/basefs.d.ts +0 -24
- package/dist/internal/domain/fs/entity/fs.d.ts +1 -15
- package/dist/internal/domain/fs/entity/originfs.d.ts +0 -7
- package/dist/internal/domain/fs/entity/overlaydir.d.ts +0 -45
- package/dist/internal/domain/fs/entity/overlayfs.d.ts +1 -81
- package/dist/internal/domain/fs/entity/service.d.ts +0 -16
- package/dist/internal/domain/fs/factory/fs.d.ts +0 -5
- package/dist/internal/domain/fs/index.d.ts +0 -1
- package/dist/internal/domain/fs/type.d.ts +0 -96
- package/dist/internal/domain/fs/vo/dir.d.ts +0 -42
- package/dist/internal/domain/fs/vo/file.d.ts +0 -29
- package/dist/internal/domain/fs/vo/fileinfo.d.ts +0 -24
- package/dist/internal/domain/fs/vo/filemeta.d.ts +0 -46
- package/dist/internal/domain/fs/vo/filesystemscollector.d.ts +0 -18
- package/dist/internal/domain/fs/vo/filevitural.d.ts +1 -10
- package/dist/internal/domain/fs/vo/incremental-file-collector.d.ts +0 -1
- package/dist/internal/domain/fs/vo/osfs.d.ts +0 -13
- package/dist/internal/domain/fs/vo/overlay-factory.d.ts +1 -6
- package/dist/internal/domain/fs/vo/overlayfs-factory.d.ts +0 -43
- package/dist/internal/domain/fs/vo/overlayoptions.d.ts +0 -45
- package/dist/internal/domain/fs/vo/static-copier.d.ts +0 -23
- package/dist/internal/domain/fs/vo/walkway.d.ts +0 -23
- package/dist/internal/domain/markdown/entity/markdown.d.ts +0 -36
- package/dist/internal/domain/markdown/factory/markdown.d.ts +0 -1
- package/dist/internal/domain/markdown/index.d.ts +0 -1
- package/dist/internal/domain/markdown/type.d.ts +1 -161
- package/dist/internal/domain/markdown/vo/config.d.ts +0 -49
- package/dist/internal/domain/markdown/vo/content.d.ts +3 -96
- package/dist/internal/domain/markdown/vo/context.d.ts +0 -10
- package/dist/internal/domain/markdown/vo/highlight.d.ts +0 -16
- package/dist/internal/domain/markdown/vo/pageparser.d.ts +2 -12
- package/dist/internal/domain/markdown/vo/parseinfo.d.ts +2 -39
- package/dist/internal/domain/markdown/vo/parserresult.d.ts +0 -7
- package/dist/internal/domain/markdown/vo/shortcode.d.ts +3 -31
- package/dist/internal/domain/markdown/vo/tableofcontents.d.ts +0 -22
- package/dist/internal/domain/module/entity/lang.d.ts +0 -13
- package/dist/internal/domain/module/entity/module.d.ts +0 -74
- package/dist/internal/domain/module/factory/module.d.ts +0 -7
- package/dist/internal/domain/module/index.d.ts +0 -1
- package/dist/internal/domain/module/type.d.ts +0 -59
- package/dist/internal/domain/module/vo/cache.d.ts +0 -49
- package/dist/internal/domain/module/vo/httpclient.d.ts +0 -15
- package/dist/internal/domain/module/vo/module.d.ts +0 -77
- package/dist/internal/domain/module/vo/mount.d.ts +0 -40
- package/dist/internal/domain/module/vo/themes.d.ts +0 -39
- package/dist/internal/domain/module/vo/zipextractor.d.ts +1 -33
- package/dist/internal/domain/paths/entity/path.d.ts +0 -29
- package/dist/internal/domain/paths/factory/pathfactory.d.ts +0 -83
- package/dist/internal/domain/paths/index.d.ts +0 -1
- package/dist/internal/domain/paths/type.d.ts +0 -133
- package/dist/internal/domain/paths/vo/pathcomponents.d.ts +0 -95
- package/dist/internal/domain/paths/vo/pathparser.d.ts +0 -76
- package/dist/internal/domain/resources/entity/http.d.ts +0 -12
- package/dist/internal/domain/resources/entity/integrity.d.ts +0 -5
- package/dist/internal/domain/resources/entity/minifier.d.ts +0 -5
- package/dist/internal/domain/resources/entity/publisher.d.ts +0 -25
- package/dist/internal/domain/resources/entity/resource.d.ts +3 -8
- package/dist/internal/domain/resources/entity/resources.d.ts +0 -41
- package/dist/internal/domain/resources/entity/template.d.ts +0 -5
- package/dist/internal/domain/resources/factory/resource.d.ts +0 -5
- package/dist/internal/domain/resources/index.d.ts +0 -1
- package/dist/internal/domain/resources/type.d.ts +2 -3
- package/dist/internal/domain/resources/valueobject/resourcemetadata.d.ts +0 -1
- package/dist/internal/domain/resources/valueobject/resourcepaths.d.ts +0 -1
- package/dist/internal/domain/resources/valueobject/transformation.d.ts +0 -1
- package/dist/internal/domain/site/entity/language.d.ts +0 -56
- package/dist/internal/domain/site/entity/menu-builder.d.ts +1 -52
- package/dist/internal/domain/site/entity/navigation.d.ts +0 -9
- package/dist/internal/domain/site/entity/page.d.ts +9 -55
- package/dist/internal/domain/site/entity/pager.d.ts +2 -9
- package/dist/internal/domain/site/entity/publisher.d.ts +0 -27
- package/dist/internal/domain/site/entity/ref.d.ts +0 -28
- package/dist/internal/domain/site/entity/site.d.ts +2 -117
- package/dist/internal/domain/site/entity/taxonomies-builder.d.ts +1 -2
- package/dist/internal/domain/site/entity/url.d.ts +0 -1
- package/dist/internal/domain/site/factory/navigation-factory.d.ts +0 -7
- package/dist/internal/domain/site/factory/site.d.ts +0 -5
- package/dist/internal/domain/site/type.d.ts +0 -101
- package/dist/internal/domain/site/valueobject/author.d.ts +1 -18
- package/dist/internal/domain/site/valueobject/baseurl.d.ts +0 -40
- package/dist/internal/domain/site/valueobject/menu.d.ts +0 -50
- package/dist/internal/domain/site/valueobject/organization.d.ts +3 -41
- package/dist/internal/domain/site/valueobject/version.d.ts +0 -15
- package/dist/internal/domain/template/entity/executor.d.ts +0 -23
- package/dist/internal/domain/template/entity/lookup.d.ts +0 -56
- package/dist/internal/domain/template/entity/parser.d.ts +1 -42
- package/dist/internal/domain/template/entity/template.d.ts +0 -88
- package/dist/internal/domain/template/factory/template.d.ts +0 -62
- package/dist/internal/domain/template/index.d.ts +0 -1
- package/dist/internal/domain/template/type.d.ts +1 -111
- package/dist/internal/domain/template/vo/baseof.d.ts +0 -48
- package/dist/internal/domain/template/vo/info.d.ts +0 -29
- package/dist/internal/domain/template/vo/namespace.d.ts +0 -92
- package/dist/internal/domain/template/vo/registry.d.ts +0 -161
- package/dist/pkg/cahce/cache.d.ts +0 -57
- package/dist/pkg/cast/cast.d.ts +0 -1
- package/dist/pkg/cast/index.d.ts +0 -1
- package/dist/pkg/doctree/dimensions.d.ts +0 -1
- package/dist/pkg/doctree/index.d.ts +0 -1
- package/dist/pkg/doctree/nodeshifttree.d.ts +0 -1
- package/dist/pkg/doctree/simpletree.d.ts +0 -1
- package/dist/pkg/doctree/support.d.ts +0 -1
- package/dist/pkg/doctree/treeshifttree.d.ts +0 -1
- package/dist/pkg/lang/data.d.ts +0 -22
- package/dist/pkg/lang/index.d.ts +0 -47
- package/dist/pkg/lang/service.d.ts +0 -50
- package/dist/pkg/lang/types.d.ts +0 -30
- package/dist/pkg/log/http.d.ts +0 -17
- package/dist/pkg/log/index.d.ts +0 -1
- package/dist/pkg/log/logger.d.ts +0 -1
- package/dist/pkg/log/manager.d.ts +0 -58
- package/dist/pkg/log/types.d.ts +0 -1
- package/dist/pkg/maps/scratch.d.ts +0 -26
- package/dist/pkg/md/parser/item.d.ts +3 -4
- package/dist/pkg/md/parser/pagelexer.d.ts +0 -1
- package/dist/pkg/md/parser/pageparser.d.ts +0 -1
- package/dist/pkg/media/buildin.d.ts +0 -1
- package/dist/pkg/media/type.d.ts +0 -20
- package/dist/pkg/paths/index.d.ts +0 -10
- package/dist/pkg/radix/index.d.ts +0 -1
- package/dist/pkg/radix/radix.d.ts +0 -1
- package/dist/pkg/string/index.d.ts +0 -1
- package/dist/pkg/string/string.d.ts +0 -1
- package/dist/pkg/text/index.d.ts +0 -5
- package/dist/pkg/types/index.d.ts +0 -1
- package/dist/pkg/types/types.d.ts +0 -1
- package/dist/pkg/web/server/electron-livereload-server.d.ts +0 -1
- package/dist/pkg/web/server/index.d.ts +0 -1
- package/dist/pkg/web/server/livereload-server.d.ts +0 -8
- package/dist/pkg/web/server/types.d.ts +0 -1
- package/dist/pkg/web/watcher/content-file-watcher.d.ts +0 -1
- package/dist/pkg/web/watcher/types.d.ts +0 -1
- package/package.json +7 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/application/incremental-build-coordinator.d.ts.map +0 -1
- package/dist/internal/application/incremental-build-coordinator.js +0 -194
- package/dist/internal/application/incremental-build-coordinator.js.map +0 -1
- package/dist/internal/application/incremental-ssg.d.ts.map +0 -1
- package/dist/internal/application/incremental-ssg.js +0 -23
- package/dist/internal/application/incremental-ssg.js.map +0 -1
- package/dist/internal/application/ssg.d.ts.map +0 -1
- package/dist/internal/application/ssg.js +0 -611
- package/dist/internal/application/ssg.js.map +0 -1
- package/dist/internal/domain/config/entity/config.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/config.js +0 -110
- package/dist/internal/domain/config/entity/config.js.map +0 -1
- package/dist/internal/domain/config/entity/dir.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/dir.js +0 -37
- package/dist/internal/domain/config/entity/dir.js.map +0 -1
- package/dist/internal/domain/config/entity/language.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/language.js +0 -154
- package/dist/internal/domain/config/entity/language.js.map +0 -1
- package/dist/internal/domain/config/entity/module.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/module.js +0 -83
- package/dist/internal/domain/config/entity/module.js.map +0 -1
- package/dist/internal/domain/config/entity/root.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/root.js +0 -107
- package/dist/internal/domain/config/entity/root.js.map +0 -1
- package/dist/internal/domain/config/entity/service.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/service.js +0 -92
- package/dist/internal/domain/config/entity/service.js.map +0 -1
- package/dist/internal/domain/config/entity/social.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/social.js +0 -127
- package/dist/internal/domain/config/entity/social.js.map +0 -1
- package/dist/internal/domain/config/entity/taxonomy.d.ts.map +0 -1
- package/dist/internal/domain/config/entity/taxonomy.js +0 -104
- package/dist/internal/domain/config/entity/taxonomy.js.map +0 -1
- package/dist/internal/domain/config/factory/config.d.ts.map +0 -1
- package/dist/internal/domain/config/factory/config.js +0 -96
- package/dist/internal/domain/config/factory/config.js.map +0 -1
- package/dist/internal/domain/config/factory/loader.d.ts.map +0 -1
- package/dist/internal/domain/config/factory/loader.js +0 -207
- package/dist/internal/domain/config/factory/loader.js.map +0 -1
- package/dist/internal/domain/config/factory/provider.d.ts.map +0 -1
- package/dist/internal/domain/config/factory/provider.js +0 -208
- package/dist/internal/domain/config/factory/provider.js.map +0 -1
- package/dist/internal/domain/config/factory/sourcedescriptor.d.ts.map +0 -1
- package/dist/internal/domain/config/factory/sourcedescriptor.js +0 -27
- package/dist/internal/domain/config/factory/sourcedescriptor.js.map +0 -1
- package/dist/internal/domain/config/index.d.ts.map +0 -1
- package/dist/internal/domain/config/index.js +0 -52
- package/dist/internal/domain/config/index.js.map +0 -1
- package/dist/internal/domain/config/tests/entity-config.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/entity-config.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/entity-config.test.js +0 -201
- package/dist/internal/domain/config/tests/entity-config.test.js.map +0 -1
- package/dist/internal/domain/config/tests/entity-root.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/entity-root.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/entity-root.test.js +0 -235
- package/dist/internal/domain/config/tests/entity-root.test.js.map +0 -1
- package/dist/internal/domain/config/tests/factory-config.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/factory-config.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/factory-config.test.js +0 -84
- package/dist/internal/domain/config/tests/factory-config.test.js.map +0 -1
- package/dist/internal/domain/config/tests/index.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/index.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/index.test.js +0 -195
- package/dist/internal/domain/config/tests/index.test.js.map +0 -1
- package/dist/internal/domain/config/tests/mock-fs.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/mock-fs.js +0 -281
- package/dist/internal/domain/config/tests/mock-fs.js.map +0 -1
- package/dist/internal/domain/config/tests/social.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/social.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/social.test.js +0 -164
- package/dist/internal/domain/config/tests/social.test.js.map +0 -1
- package/dist/internal/domain/config/tests/type.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/type.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/type.test.js +0 -276
- package/dist/internal/domain/config/tests/type.test.js.map +0 -1
- package/dist/internal/domain/config/tests/vo-module.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/vo-module.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/vo-module.test.js +0 -267
- package/dist/internal/domain/config/tests/vo-module.test.js.map +0 -1
- package/dist/internal/domain/config/tests/vo-root.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/vo-root.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/vo-root.test.js +0 -165
- package/dist/internal/domain/config/tests/vo-root.test.js.map +0 -1
- package/dist/internal/domain/config/tests/vo-service.test.d.ts +0 -2
- package/dist/internal/domain/config/tests/vo-service.test.d.ts.map +0 -1
- package/dist/internal/domain/config/tests/vo-service.test.js +0 -216
- package/dist/internal/domain/config/tests/vo-service.test.js.map +0 -1
- package/dist/internal/domain/config/type.d.ts.map +0 -1
- package/dist/internal/domain/config/type.js +0 -24
- package/dist/internal/domain/config/type.js.map +0 -1
- package/dist/internal/domain/config/vo/language.d.ts.map +0 -1
- package/dist/internal/domain/config/vo/language.js +0 -53
- package/dist/internal/domain/config/vo/language.js.map +0 -1
- package/dist/internal/domain/config/vo/module.d.ts.map +0 -1
- package/dist/internal/domain/config/vo/module.js +0 -44
- package/dist/internal/domain/config/vo/module.js.map +0 -1
- package/dist/internal/domain/config/vo/root.d.ts.map +0 -1
- package/dist/internal/domain/config/vo/root.js +0 -72
- package/dist/internal/domain/config/vo/root.js.map +0 -1
- package/dist/internal/domain/config/vo/service.d.ts.map +0 -1
- package/dist/internal/domain/config/vo/service.js +0 -52
- package/dist/internal/domain/config/vo/service.js.map +0 -1
- package/dist/internal/domain/config/vo/social.d.ts.map +0 -1
- package/dist/internal/domain/config/vo/social.js +0 -212
- package/dist/internal/domain/config/vo/social.js.map +0 -1
- package/dist/internal/domain/config/vo/taxonomy.d.ts.map +0 -1
- package/dist/internal/domain/config/vo/taxonomy.js +0 -68
- package/dist/internal/domain/config/vo/taxonomy.js.map +0 -1
- package/dist/internal/domain/content/entity/content.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/content.js +0 -313
- package/dist/internal/domain/content/entity/content.js.map +0 -1
- package/dist/internal/domain/content/entity/converter.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/converter.js +0 -23
- package/dist/internal/domain/content/entity/converter.js.map +0 -1
- package/dist/internal/domain/content/entity/index.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/index.js +0 -21
- package/dist/internal/domain/content/entity/index.js.map +0 -1
- package/dist/internal/domain/content/entity/page.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/page.js +0 -433
- package/dist/internal/domain/content/entity/page.js.map +0 -1
- package/dist/internal/domain/content/entity/pagebuilder.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagebuilder.js +0 -557
- package/dist/internal/domain/content/entity/pagebuilder.js.map +0 -1
- package/dist/internal/domain/content/entity/pagecollector.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagecollector.js +0 -111
- package/dist/internal/domain/content/entity/pagecollector.js.map +0 -1
- package/dist/internal/domain/content/entity/pagecontent.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagecontent.js +0 -75
- package/dist/internal/domain/content/entity/pagecontent.js.map +0 -1
- package/dist/internal/domain/content/entity/pagelayout.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagelayout.js +0 -73
- package/dist/internal/domain/content/entity/pagelayout.js.map +0 -1
- package/dist/internal/domain/content/entity/pagemap.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagemap.js +0 -496
- package/dist/internal/domain/content/entity/pagemap.js.map +0 -1
- package/dist/internal/domain/content/entity/pagemeta.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagemeta.js +0 -74
- package/dist/internal/domain/content/entity/pagemeta.js.map +0 -1
- package/dist/internal/domain/content/entity/pageoutput.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pageoutput.js +0 -136
- package/dist/internal/domain/content/entity/pageoutput.js.map +0 -1
- package/dist/internal/domain/content/entity/pagesource.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagesource.js +0 -168
- package/dist/internal/domain/content/entity/pagesource.js.map +0 -1
- package/dist/internal/domain/content/entity/pagetrees.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/pagetrees.js +0 -265
- package/dist/internal/domain/content/entity/pagetrees.js.map +0 -1
- package/dist/internal/domain/content/entity/paginator.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/paginator.js +0 -270
- package/dist/internal/domain/content/entity/paginator.js.map +0 -1
- package/dist/internal/domain/content/entity/section.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/section.js +0 -120
- package/dist/internal/domain/content/entity/section.js.map +0 -1
- package/dist/internal/domain/content/entity/shifter.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/shifter.js +0 -36
- package/dist/internal/domain/content/entity/shifter.js.map +0 -1
- package/dist/internal/domain/content/entity/shifterpage.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/shifterpage.js +0 -20
- package/dist/internal/domain/content/entity/shifterpage.js.map +0 -1
- package/dist/internal/domain/content/entity/shifterpagesource.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/shifterpagesource.js +0 -21
- package/dist/internal/domain/content/entity/shifterpagesource.js.map +0 -1
- package/dist/internal/domain/content/entity/shortcode.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/shortcode.js +0 -165
- package/dist/internal/domain/content/entity/shortcode.js.map +0 -1
- package/dist/internal/domain/content/entity/standalone.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/standalone.js +0 -39
- package/dist/internal/domain/content/entity/standalone.js.map +0 -1
- package/dist/internal/domain/content/entity/taxonomy.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/taxonomy.js +0 -131
- package/dist/internal/domain/content/entity/taxonomy.js.map +0 -1
- package/dist/internal/domain/content/entity/term.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/term.js +0 -150
- package/dist/internal/domain/content/entity/term.js.map +0 -1
- package/dist/internal/domain/content/entity/translator.d.ts.map +0 -1
- package/dist/internal/domain/content/entity/translator.js +0 -191
- package/dist/internal/domain/content/entity/translator.js.map +0 -1
- package/dist/internal/domain/content/factory/hub.d.ts.map +0 -1
- package/dist/internal/domain/content/factory/hub.js +0 -46
- package/dist/internal/domain/content/factory/hub.js.map +0 -1
- package/dist/internal/domain/content/index.d.ts.map +0 -1
- package/dist/internal/domain/content/index.js +0 -38
- package/dist/internal/domain/content/index.js.map +0 -1
- package/dist/internal/domain/content/type.d.ts.map +0 -1
- package/dist/internal/domain/content/type.js +0 -16
- package/dist/internal/domain/content/type.js.map +0 -1
- package/dist/internal/domain/content/vo/classifier.d.ts.map +0 -1
- package/dist/internal/domain/content/vo/classifier.js +0 -110
- package/dist/internal/domain/content/vo/classifier.js.map +0 -1
- package/dist/internal/domain/content/vo/fileinfo.d.ts.map +0 -1
- package/dist/internal/domain/content/vo/fileinfo.js +0 -224
- package/dist/internal/domain/content/vo/fileinfo.js.map +0 -1
- package/dist/internal/domain/content/vo/frontmatter.d.ts.map +0 -1
- package/dist/internal/domain/content/vo/frontmatter.js +0 -484
- package/dist/internal/domain/content/vo/frontmatter.js.map +0 -1
- package/dist/internal/domain/content/vo/identity.d.ts.map +0 -1
- package/dist/internal/domain/content/vo/identity.js +0 -47
- package/dist/internal/domain/content/vo/identity.js.map +0 -1
- package/dist/internal/domain/content/vo/kind.d.ts.map +0 -1
- package/dist/internal/domain/content/vo/kind.js +0 -52
- package/dist/internal/domain/content/vo/kind.js.map +0 -1
- package/dist/internal/domain/content/vo/sort.d.ts.map +0 -1
- package/dist/internal/domain/content/vo/sort.js +0 -151
- package/dist/internal/domain/content/vo/sort.js.map +0 -1
- package/dist/internal/domain/fs/entity/basefs.d.ts.map +0 -1
- package/dist/internal/domain/fs/entity/basefs.js +0 -212
- package/dist/internal/domain/fs/entity/basefs.js.map +0 -1
- package/dist/internal/domain/fs/entity/fs.d.ts.map +0 -1
- package/dist/internal/domain/fs/entity/fs.js +0 -115
- package/dist/internal/domain/fs/entity/fs.js.map +0 -1
- package/dist/internal/domain/fs/entity/originfs.d.ts.map +0 -1
- package/dist/internal/domain/fs/entity/originfs.js +0 -30
- package/dist/internal/domain/fs/entity/originfs.js.map +0 -1
- package/dist/internal/domain/fs/entity/overlaydir.d.ts.map +0 -1
- package/dist/internal/domain/fs/entity/overlaydir.js +0 -256
- package/dist/internal/domain/fs/entity/overlaydir.js.map +0 -1
- package/dist/internal/domain/fs/entity/overlayfs.d.ts.map +0 -1
- package/dist/internal/domain/fs/entity/overlayfs.js +0 -310
- package/dist/internal/domain/fs/entity/overlayfs.js.map +0 -1
- package/dist/internal/domain/fs/entity/service.d.ts.map +0 -1
- package/dist/internal/domain/fs/entity/service.js +0 -35
- package/dist/internal/domain/fs/entity/service.js.map +0 -1
- package/dist/internal/domain/fs/factory/fs.d.ts.map +0 -1
- package/dist/internal/domain/fs/factory/fs.js +0 -21
- package/dist/internal/domain/fs/factory/fs.js.map +0 -1
- package/dist/internal/domain/fs/index.d.ts.map +0 -1
- package/dist/internal/domain/fs/index.js +0 -104
- package/dist/internal/domain/fs/index.js.map +0 -1
- package/dist/internal/domain/fs/tests/entity-basefs.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/entity-basefs.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/entity-basefs.test.js +0 -279
- package/dist/internal/domain/fs/tests/entity-basefs.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/entity-fs.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/entity-fs.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/entity-fs.test.js +0 -232
- package/dist/internal/domain/fs/tests/entity-fs.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/entity-originfs.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/entity-originfs.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/entity-originfs.test.js +0 -47
- package/dist/internal/domain/fs/tests/entity-originfs.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/entity-overlaydir.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/entity-overlaydir.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/entity-overlaydir.test.js +0 -293
- package/dist/internal/domain/fs/tests/entity-overlaydir.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/entity-overlayfs.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/entity-overlayfs.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/entity-overlayfs.test.js +0 -281
- package/dist/internal/domain/fs/tests/entity-overlayfs.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/entity-service.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/entity-service.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/entity-service.test.js +0 -43
- package/dist/internal/domain/fs/tests/entity-service.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/factory-fs.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/factory-fs.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/factory-fs.test.js +0 -105
- package/dist/internal/domain/fs/tests/factory-fs.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/type.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/type.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/type.test.js +0 -113
- package/dist/internal/domain/fs/tests/type.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-dir.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-dir.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-dir.test.js +0 -211
- package/dist/internal/domain/fs/tests/vo-dir.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-file.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-file.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-file.test.js +0 -256
- package/dist/internal/domain/fs/tests/vo-file.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-fileinfo.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-fileinfo.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-fileinfo.test.js +0 -165
- package/dist/internal/domain/fs/tests/vo-fileinfo.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-filemeta.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-filemeta.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-filemeta.test.js +0 -171
- package/dist/internal/domain/fs/tests/vo-filemeta.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-filesystemscollector.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-filesystemscollector.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-filesystemscollector.test.js +0 -305
- package/dist/internal/domain/fs/tests/vo-filesystemscollector.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-filevitural.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-filevitural.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-filevitural.test.js +0 -167
- package/dist/internal/domain/fs/tests/vo-filevitural.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-incremental-file-collector.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-incremental-file-collector.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-incremental-file-collector.test.js +0 -396
- package/dist/internal/domain/fs/tests/vo-incremental-file-collector.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-osfs.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-osfs.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-osfs.test.js +0 -363
- package/dist/internal/domain/fs/tests/vo-osfs.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-overlayfs-factory.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-overlayfs-factory.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-overlayfs-factory.test.js +0 -430
- package/dist/internal/domain/fs/tests/vo-overlayfs-factory.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-overlayoptions.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-overlayoptions.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-overlayoptions.test.js +0 -402
- package/dist/internal/domain/fs/tests/vo-overlayoptions.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-static-copier.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-static-copier.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-static-copier.test.js +0 -320
- package/dist/internal/domain/fs/tests/vo-static-copier.test.js.map +0 -1
- package/dist/internal/domain/fs/tests/vo-walkway.test.d.ts +0 -2
- package/dist/internal/domain/fs/tests/vo-walkway.test.d.ts.map +0 -1
- package/dist/internal/domain/fs/tests/vo-walkway.test.js +0 -295
- package/dist/internal/domain/fs/tests/vo-walkway.test.js.map +0 -1
- package/dist/internal/domain/fs/type.d.ts.map +0 -1
- package/dist/internal/domain/fs/type.js +0 -54
- package/dist/internal/domain/fs/type.js.map +0 -1
- package/dist/internal/domain/fs/vo/dir.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/dir.js +0 -101
- package/dist/internal/domain/fs/vo/dir.js.map +0 -1
- package/dist/internal/domain/fs/vo/file.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/file.js +0 -204
- package/dist/internal/domain/fs/vo/file.js.map +0 -1
- package/dist/internal/domain/fs/vo/fileinfo.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/fileinfo.js +0 -109
- package/dist/internal/domain/fs/vo/fileinfo.js.map +0 -1
- package/dist/internal/domain/fs/vo/filemeta.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/filemeta.js +0 -123
- package/dist/internal/domain/fs/vo/filemeta.js.map +0 -1
- package/dist/internal/domain/fs/vo/filesystemscollector.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/filesystemscollector.js +0 -195
- package/dist/internal/domain/fs/vo/filesystemscollector.js.map +0 -1
- package/dist/internal/domain/fs/vo/filevitural.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/filevitural.js +0 -142
- package/dist/internal/domain/fs/vo/filevitural.js.map +0 -1
- package/dist/internal/domain/fs/vo/incremental-file-collector.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/incremental-file-collector.js +0 -43
- package/dist/internal/domain/fs/vo/incremental-file-collector.js.map +0 -1
- package/dist/internal/domain/fs/vo/osfs.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/osfs.js +0 -300
- package/dist/internal/domain/fs/vo/osfs.js.map +0 -1
- package/dist/internal/domain/fs/vo/overlay-factory.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/overlay-factory.js +0 -23
- package/dist/internal/domain/fs/vo/overlay-factory.js.map +0 -1
- package/dist/internal/domain/fs/vo/overlayfs-factory.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/overlayfs-factory.js +0 -125
- package/dist/internal/domain/fs/vo/overlayfs-factory.js.map +0 -1
- package/dist/internal/domain/fs/vo/overlayoptions.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/overlayoptions.js +0 -141
- package/dist/internal/domain/fs/vo/overlayoptions.js.map +0 -1
- package/dist/internal/domain/fs/vo/static-copier.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/static-copier.js +0 -175
- package/dist/internal/domain/fs/vo/static-copier.js.map +0 -1
- package/dist/internal/domain/fs/vo/walkway.d.ts.map +0 -1
- package/dist/internal/domain/fs/vo/walkway.js +0 -220
- package/dist/internal/domain/fs/vo/walkway.js.map +0 -1
- package/dist/internal/domain/markdown/entity/markdown.d.ts.map +0 -1
- package/dist/internal/domain/markdown/entity/markdown.js +0 -350
- package/dist/internal/domain/markdown/entity/markdown.js.map +0 -1
- package/dist/internal/domain/markdown/factory/markdown.d.ts.map +0 -1
- package/dist/internal/domain/markdown/factory/markdown.js +0 -10
- package/dist/internal/domain/markdown/factory/markdown.js.map +0 -1
- package/dist/internal/domain/markdown/index.d.ts.map +0 -1
- package/dist/internal/domain/markdown/index.js +0 -35
- package/dist/internal/domain/markdown/index.js.map +0 -1
- package/dist/internal/domain/markdown/type.d.ts.map +0 -1
- package/dist/internal/domain/markdown/type.js +0 -19
- package/dist/internal/domain/markdown/type.js.map +0 -1
- package/dist/internal/domain/markdown/vo/config.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/config.js +0 -89
- package/dist/internal/domain/markdown/vo/config.js.map +0 -1
- package/dist/internal/domain/markdown/vo/content.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/content.js +0 -368
- package/dist/internal/domain/markdown/vo/content.js.map +0 -1
- package/dist/internal/domain/markdown/vo/context.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/context.js +0 -119
- package/dist/internal/domain/markdown/vo/context.js.map +0 -1
- package/dist/internal/domain/markdown/vo/highlight.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/highlight.js +0 -164
- package/dist/internal/domain/markdown/vo/highlight.js.map +0 -1
- package/dist/internal/domain/markdown/vo/pageparser.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/pageparser.js +0 -87
- package/dist/internal/domain/markdown/vo/pageparser.js.map +0 -1
- package/dist/internal/domain/markdown/vo/parseinfo.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/parseinfo.js +0 -134
- package/dist/internal/domain/markdown/vo/parseinfo.js.map +0 -1
- package/dist/internal/domain/markdown/vo/parserresult.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/parserresult.js +0 -44
- package/dist/internal/domain/markdown/vo/parserresult.js.map +0 -1
- package/dist/internal/domain/markdown/vo/shortcode.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/shortcode.js +0 -319
- package/dist/internal/domain/markdown/vo/shortcode.js.map +0 -1
- package/dist/internal/domain/markdown/vo/tableofcontents.d.ts.map +0 -1
- package/dist/internal/domain/markdown/vo/tableofcontents.js +0 -239
- package/dist/internal/domain/markdown/vo/tableofcontents.js.map +0 -1
- package/dist/internal/domain/module/entity/lang.d.ts.map +0 -1
- package/dist/internal/domain/module/entity/lang.js +0 -43
- package/dist/internal/domain/module/entity/lang.js.map +0 -1
- package/dist/internal/domain/module/entity/module.d.ts.map +0 -1
- package/dist/internal/domain/module/entity/module.js +0 -556
- package/dist/internal/domain/module/entity/module.js.map +0 -1
- package/dist/internal/domain/module/factory/module.d.ts.map +0 -1
- package/dist/internal/domain/module/factory/module.js +0 -51
- package/dist/internal/domain/module/factory/module.js.map +0 -1
- package/dist/internal/domain/module/index.d.ts.map +0 -1
- package/dist/internal/domain/module/index.js +0 -69
- package/dist/internal/domain/module/index.js.map +0 -1
- package/dist/internal/domain/module/type.d.ts.map +0 -1
- package/dist/internal/domain/module/type.js +0 -53
- package/dist/internal/domain/module/type.js.map +0 -1
- package/dist/internal/domain/module/vo/cache.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/cache.js +0 -266
- package/dist/internal/domain/module/vo/cache.js.map +0 -1
- package/dist/internal/domain/module/vo/httpclient.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/httpclient.js +0 -258
- package/dist/internal/domain/module/vo/httpclient.js.map +0 -1
- package/dist/internal/domain/module/vo/module.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/module.js +0 -305
- package/dist/internal/domain/module/vo/module.js.map +0 -1
- package/dist/internal/domain/module/vo/mount.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/mount.js +0 -143
- package/dist/internal/domain/module/vo/mount.js.map +0 -1
- package/dist/internal/domain/module/vo/themes.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/themes.js +0 -93
- package/dist/internal/domain/module/vo/themes.js.map +0 -1
- package/dist/internal/domain/module/vo/themes.test.d.ts +0 -2
- package/dist/internal/domain/module/vo/themes.test.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/themes.test.js +0 -113
- package/dist/internal/domain/module/vo/themes.test.js.map +0 -1
- package/dist/internal/domain/module/vo/zipextractor.d.ts.map +0 -1
- package/dist/internal/domain/module/vo/zipextractor.js +0 -251
- package/dist/internal/domain/module/vo/zipextractor.js.map +0 -1
- package/dist/internal/domain/paths/entity/path.d.ts.map +0 -1
- package/dist/internal/domain/paths/entity/path.js +0 -452
- package/dist/internal/domain/paths/entity/path.js.map +0 -1
- package/dist/internal/domain/paths/factory/pathfactory.d.ts.map +0 -1
- package/dist/internal/domain/paths/factory/pathfactory.js +0 -250
- package/dist/internal/domain/paths/factory/pathfactory.js.map +0 -1
- package/dist/internal/domain/paths/index.d.ts.map +0 -1
- package/dist/internal/domain/paths/index.js +0 -94
- package/dist/internal/domain/paths/index.js.map +0 -1
- package/dist/internal/domain/paths/test/factory.test.d.ts +0 -2
- package/dist/internal/domain/paths/test/factory.test.d.ts.map +0 -1
- package/dist/internal/domain/paths/test/factory.test.js +0 -352
- package/dist/internal/domain/paths/test/factory.test.js.map +0 -1
- package/dist/internal/domain/paths/test/integration.test.d.ts +0 -2
- package/dist/internal/domain/paths/test/integration.test.d.ts.map +0 -1
- package/dist/internal/domain/paths/test/integration.test.js +0 -328
- package/dist/internal/domain/paths/test/integration.test.js.map +0 -1
- package/dist/internal/domain/paths/test/pathoperations.test.d.ts +0 -2
- package/dist/internal/domain/paths/test/pathoperations.test.d.ts.map +0 -1
- package/dist/internal/domain/paths/test/pathoperations.test.js +0 -413
- package/dist/internal/domain/paths/test/pathoperations.test.js.map +0 -1
- package/dist/internal/domain/paths/test/pathparser.test.d.ts +0 -2
- package/dist/internal/domain/paths/test/pathparser.test.d.ts.map +0 -1
- package/dist/internal/domain/paths/test/pathparser.test.js +0 -403
- package/dist/internal/domain/paths/test/pathparser.test.js.map +0 -1
- package/dist/internal/domain/paths/type.d.ts.map +0 -1
- package/dist/internal/domain/paths/type.js +0 -85
- package/dist/internal/domain/paths/type.js.map +0 -1
- package/dist/internal/domain/paths/vo/pathcomponents.d.ts.map +0 -1
- package/dist/internal/domain/paths/vo/pathcomponents.js +0 -236
- package/dist/internal/domain/paths/vo/pathcomponents.js.map +0 -1
- package/dist/internal/domain/paths/vo/pathparser.d.ts.map +0 -1
- package/dist/internal/domain/paths/vo/pathparser.js +0 -360
- package/dist/internal/domain/paths/vo/pathparser.js.map +0 -1
- package/dist/internal/domain/resources/entity/http.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/http.js +0 -129
- package/dist/internal/domain/resources/entity/http.js.map +0 -1
- package/dist/internal/domain/resources/entity/integrity.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/integrity.js +0 -114
- package/dist/internal/domain/resources/entity/integrity.js.map +0 -1
- package/dist/internal/domain/resources/entity/minifier.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/minifier.js +0 -121
- package/dist/internal/domain/resources/entity/minifier.js.map +0 -1
- package/dist/internal/domain/resources/entity/publisher.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/publisher.js +0 -162
- package/dist/internal/domain/resources/entity/publisher.js.map +0 -1
- package/dist/internal/domain/resources/entity/resource.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/resource.js +0 -364
- package/dist/internal/domain/resources/entity/resource.js.map +0 -1
- package/dist/internal/domain/resources/entity/resources.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/resources.js +0 -390
- package/dist/internal/domain/resources/entity/resources.js.map +0 -1
- package/dist/internal/domain/resources/entity/template.d.ts.map +0 -1
- package/dist/internal/domain/resources/entity/template.js +0 -139
- package/dist/internal/domain/resources/entity/template.js.map +0 -1
- package/dist/internal/domain/resources/factory/resource.d.ts.map +0 -1
- package/dist/internal/domain/resources/factory/resource.js +0 -12
- package/dist/internal/domain/resources/factory/resource.js.map +0 -1
- package/dist/internal/domain/resources/index.d.ts.map +0 -1
- package/dist/internal/domain/resources/index.js +0 -42
- package/dist/internal/domain/resources/index.js.map +0 -1
- package/dist/internal/domain/resources/type.d.ts.map +0 -1
- package/dist/internal/domain/resources/type.js +0 -3
- package/dist/internal/domain/resources/type.js.map +0 -1
- package/dist/internal/domain/resources/valueobject/resourcemetadata.d.ts.map +0 -1
- package/dist/internal/domain/resources/valueobject/resourcemetadata.js +0 -26
- package/dist/internal/domain/resources/valueobject/resourcemetadata.js.map +0 -1
- package/dist/internal/domain/resources/valueobject/resourcepaths.d.ts.map +0 -1
- package/dist/internal/domain/resources/valueobject/resourcepaths.js +0 -146
- package/dist/internal/domain/resources/valueobject/resourcepaths.js.map +0 -1
- package/dist/internal/domain/resources/valueobject/resourcepaths.test.d.ts +0 -2
- package/dist/internal/domain/resources/valueobject/resourcepaths.test.d.ts.map +0 -1
- package/dist/internal/domain/resources/valueobject/resourcepaths.test.js +0 -53
- package/dist/internal/domain/resources/valueobject/resourcepaths.test.js.map +0 -1
- package/dist/internal/domain/resources/valueobject/transformation.d.ts.map +0 -1
- package/dist/internal/domain/resources/valueobject/transformation.js +0 -43
- package/dist/internal/domain/resources/valueobject/transformation.js.map +0 -1
- package/dist/internal/domain/site/entity/language.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/language.js +0 -177
- package/dist/internal/domain/site/entity/language.js.map +0 -1
- package/dist/internal/domain/site/entity/menu-builder.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/menu-builder.js +0 -351
- package/dist/internal/domain/site/entity/menu-builder.js.map +0 -1
- package/dist/internal/domain/site/entity/navigation.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/navigation.js +0 -90
- package/dist/internal/domain/site/entity/navigation.js.map +0 -1
- package/dist/internal/domain/site/entity/page.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/page.js +0 -637
- package/dist/internal/domain/site/entity/page.js.map +0 -1
- package/dist/internal/domain/site/entity/pager.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/pager.js +0 -117
- package/dist/internal/domain/site/entity/pager.js.map +0 -1
- package/dist/internal/domain/site/entity/publisher.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/publisher.js +0 -142
- package/dist/internal/domain/site/entity/publisher.js.map +0 -1
- package/dist/internal/domain/site/entity/ref.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/ref.js +0 -132
- package/dist/internal/domain/site/entity/ref.js.map +0 -1
- package/dist/internal/domain/site/entity/site.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/site.js +0 -536
- package/dist/internal/domain/site/entity/site.js.map +0 -1
- package/dist/internal/domain/site/entity/taxonomies-builder.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/taxonomies-builder.js +0 -243
- package/dist/internal/domain/site/entity/taxonomies-builder.js.map +0 -1
- package/dist/internal/domain/site/entity/url.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/url.js +0 -209
- package/dist/internal/domain/site/entity/url.js.map +0 -1
- package/dist/internal/domain/site/entity/url.test.d.ts +0 -2
- package/dist/internal/domain/site/entity/url.test.d.ts.map +0 -1
- package/dist/internal/domain/site/entity/url.test.js +0 -98
- package/dist/internal/domain/site/entity/url.test.js.map +0 -1
- package/dist/internal/domain/site/factory/navigation-factory.d.ts.map +0 -1
- package/dist/internal/domain/site/factory/navigation-factory.js +0 -48
- package/dist/internal/domain/site/factory/navigation-factory.js.map +0 -1
- package/dist/internal/domain/site/factory/site.d.ts.map +0 -1
- package/dist/internal/domain/site/factory/site.js +0 -56
- package/dist/internal/domain/site/factory/site.js.map +0 -1
- package/dist/internal/domain/site/type.d.ts.map +0 -1
- package/dist/internal/domain/site/type.js +0 -3
- package/dist/internal/domain/site/type.js.map +0 -1
- package/dist/internal/domain/site/valueobject/author.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/author.js +0 -69
- package/dist/internal/domain/site/valueobject/author.js.map +0 -1
- package/dist/internal/domain/site/valueobject/baseurl.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/baseurl.js +0 -207
- package/dist/internal/domain/site/valueobject/baseurl.js.map +0 -1
- package/dist/internal/domain/site/valueobject/baseurl.test.d.ts +0 -2
- package/dist/internal/domain/site/valueobject/baseurl.test.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/baseurl.test.js +0 -138
- package/dist/internal/domain/site/valueobject/baseurl.test.js.map +0 -1
- package/dist/internal/domain/site/valueobject/menu.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/menu.js +0 -178
- package/dist/internal/domain/site/valueobject/menu.js.map +0 -1
- package/dist/internal/domain/site/valueobject/organization.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/organization.js +0 -123
- package/dist/internal/domain/site/valueobject/organization.js.map +0 -1
- package/dist/internal/domain/site/valueobject/organization.test.d.ts +0 -2
- package/dist/internal/domain/site/valueobject/organization.test.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/organization.test.js +0 -78
- package/dist/internal/domain/site/valueobject/organization.test.js.map +0 -1
- package/dist/internal/domain/site/valueobject/version.d.ts.map +0 -1
- package/dist/internal/domain/site/valueobject/version.js +0 -35
- package/dist/internal/domain/site/valueobject/version.js.map +0 -1
- package/dist/internal/domain/template/entity/executor.d.ts.map +0 -1
- package/dist/internal/domain/template/entity/executor.js +0 -147
- package/dist/internal/domain/template/entity/executor.js.map +0 -1
- package/dist/internal/domain/template/entity/lookup.d.ts.map +0 -1
- package/dist/internal/domain/template/entity/lookup.js +0 -194
- package/dist/internal/domain/template/entity/lookup.js.map +0 -1
- package/dist/internal/domain/template/entity/parser.d.ts.map +0 -1
- package/dist/internal/domain/template/entity/parser.js +0 -336
- package/dist/internal/domain/template/entity/parser.js.map +0 -1
- package/dist/internal/domain/template/entity/template.d.ts.map +0 -1
- package/dist/internal/domain/template/entity/template.js +0 -369
- package/dist/internal/domain/template/entity/template.js.map +0 -1
- package/dist/internal/domain/template/factory/template.d.ts.map +0 -1
- package/dist/internal/domain/template/factory/template.js +0 -213
- package/dist/internal/domain/template/factory/template.js.map +0 -1
- package/dist/internal/domain/template/index.d.ts.map +0 -1
- package/dist/internal/domain/template/index.js +0 -74
- package/dist/internal/domain/template/index.js.map +0 -1
- package/dist/internal/domain/template/type.d.ts.map +0 -1
- package/dist/internal/domain/template/type.js +0 -35
- package/dist/internal/domain/template/type.js.map +0 -1
- package/dist/internal/domain/template/vo/baseof.d.ts.map +0 -1
- package/dist/internal/domain/template/vo/baseof.js +0 -182
- package/dist/internal/domain/template/vo/baseof.js.map +0 -1
- package/dist/internal/domain/template/vo/info.d.ts.map +0 -1
- package/dist/internal/domain/template/vo/info.js +0 -127
- package/dist/internal/domain/template/vo/info.js.map +0 -1
- package/dist/internal/domain/template/vo/namespace.d.ts.map +0 -1
- package/dist/internal/domain/template/vo/namespace.js +0 -262
- package/dist/internal/domain/template/vo/namespace.js.map +0 -1
- package/dist/internal/domain/template/vo/registry.d.ts.map +0 -1
- package/dist/internal/domain/template/vo/registry.js +0 -2835
- package/dist/internal/domain/template/vo/registry.js.map +0 -1
- package/dist/pkg/cahce/cache.d.ts.map +0 -1
- package/dist/pkg/cahce/cache.js +0 -175
- package/dist/pkg/cahce/cache.js.map +0 -1
- package/dist/pkg/cahce/cache.test.d.ts +0 -2
- package/dist/pkg/cahce/cache.test.d.ts.map +0 -1
- package/dist/pkg/cahce/cache.test.js +0 -356
- package/dist/pkg/cahce/cache.test.js.map +0 -1
- package/dist/pkg/cast/cast.d.ts.map +0 -1
- package/dist/pkg/cast/cast.js +0 -42
- package/dist/pkg/cast/cast.js.map +0 -1
- package/dist/pkg/cast/index.d.ts.map +0 -1
- package/dist/pkg/cast/index.js +0 -18
- package/dist/pkg/cast/index.js.map +0 -1
- package/dist/pkg/doctree/dimensions.d.ts.map +0 -1
- package/dist/pkg/doctree/dimensions.js +0 -50
- package/dist/pkg/doctree/dimensions.js.map +0 -1
- package/dist/pkg/doctree/doctree.test.d.ts +0 -2
- package/dist/pkg/doctree/doctree.test.d.ts.map +0 -1
- package/dist/pkg/doctree/doctree.test.js +0 -162
- package/dist/pkg/doctree/doctree.test.js.map +0 -1
- package/dist/pkg/doctree/index.d.ts.map +0 -1
- package/dist/pkg/doctree/index.js +0 -30
- package/dist/pkg/doctree/index.js.map +0 -1
- package/dist/pkg/doctree/nodeshifttree.d.ts.map +0 -1
- package/dist/pkg/doctree/nodeshifttree.js +0 -384
- package/dist/pkg/doctree/nodeshifttree.js.map +0 -1
- package/dist/pkg/doctree/simpletree.d.ts.map +0 -1
- package/dist/pkg/doctree/simpletree.js +0 -119
- package/dist/pkg/doctree/simpletree.js.map +0 -1
- package/dist/pkg/doctree/support.d.ts.map +0 -1
- package/dist/pkg/doctree/support.js +0 -198
- package/dist/pkg/doctree/support.js.map +0 -1
- package/dist/pkg/doctree/treeshifttree.d.ts.map +0 -1
- package/dist/pkg/doctree/treeshifttree.js +0 -87
- package/dist/pkg/doctree/treeshifttree.js.map +0 -1
- package/dist/pkg/lang/data.d.ts.map +0 -1
- package/dist/pkg/lang/data.js +0 -151
- package/dist/pkg/lang/data.js.map +0 -1
- package/dist/pkg/lang/index.d.ts.map +0 -1
- package/dist/pkg/lang/index.js +0 -79
- package/dist/pkg/lang/index.js.map +0 -1
- package/dist/pkg/lang/service.d.ts.map +0 -1
- package/dist/pkg/lang/service.js +0 -115
- package/dist/pkg/lang/service.js.map +0 -1
- package/dist/pkg/lang/types.d.ts.map +0 -1
- package/dist/pkg/lang/types.js +0 -7
- package/dist/pkg/lang/types.js.map +0 -1
- package/dist/pkg/log/http.d.ts.map +0 -1
- package/dist/pkg/log/http.js +0 -60
- package/dist/pkg/log/http.js.map +0 -1
- package/dist/pkg/log/index.d.ts.map +0 -1
- package/dist/pkg/log/index.js +0 -53
- package/dist/pkg/log/index.js.map +0 -1
- package/dist/pkg/log/logger.d.ts.map +0 -1
- package/dist/pkg/log/logger.js +0 -185
- package/dist/pkg/log/logger.js.map +0 -1
- package/dist/pkg/log/manager.d.ts.map +0 -1
- package/dist/pkg/log/manager.js +0 -155
- package/dist/pkg/log/manager.js.map +0 -1
- package/dist/pkg/log/types.d.ts.map +0 -1
- package/dist/pkg/log/types.js +0 -12
- package/dist/pkg/log/types.js.map +0 -1
- package/dist/pkg/maps/scratch.d.ts.map +0 -1
- package/dist/pkg/maps/scratch.js +0 -94
- package/dist/pkg/maps/scratch.js.map +0 -1
- package/dist/pkg/md/parser/item.d.ts.map +0 -1
- package/dist/pkg/md/parser/item.js +0 -195
- package/dist/pkg/md/parser/item.js.map +0 -1
- package/dist/pkg/md/parser/item.test.d.ts +0 -2
- package/dist/pkg/md/parser/item.test.d.ts.map +0 -1
- package/dist/pkg/md/parser/item.test.js +0 -81
- package/dist/pkg/md/parser/item.test.js.map +0 -1
- package/dist/pkg/md/parser/pagelexer.d.ts.map +0 -1
- package/dist/pkg/md/parser/pagelexer.js +0 -1321
- package/dist/pkg/md/parser/pagelexer.js.map +0 -1
- package/dist/pkg/md/parser/pageparser.d.ts.map +0 -1
- package/dist/pkg/md/parser/pageparser.js +0 -177
- package/dist/pkg/md/parser/pageparser.js.map +0 -1
- package/dist/pkg/md/parser/pageparser.shortcode.test.d.ts +0 -2
- package/dist/pkg/md/parser/pageparser.shortcode.test.d.ts.map +0 -1
- package/dist/pkg/md/parser/pageparser.shortcode.test.js +0 -182
- package/dist/pkg/md/parser/pageparser.shortcode.test.js.map +0 -1
- package/dist/pkg/md/parser/pageparser.test.d.ts +0 -2
- package/dist/pkg/md/parser/pageparser.test.d.ts.map +0 -1
- package/dist/pkg/md/parser/pageparser.test.js +0 -97
- package/dist/pkg/md/parser/pageparser.test.js.map +0 -1
- package/dist/pkg/md/parser/pageparser_intro.test.d.ts +0 -2
- package/dist/pkg/md/parser/pageparser_intro.test.d.ts.map +0 -1
- package/dist/pkg/md/parser/pageparser_intro.test.js +0 -156
- package/dist/pkg/md/parser/pageparser_intro.test.js.map +0 -1
- package/dist/pkg/media/buildin.d.ts.map +0 -1
- package/dist/pkg/media/buildin.js +0 -23
- package/dist/pkg/media/buildin.js.map +0 -1
- package/dist/pkg/media/type.d.ts.map +0 -1
- package/dist/pkg/media/type.js +0 -63
- package/dist/pkg/media/type.js.map +0 -1
- package/dist/pkg/paths/index.d.ts.map +0 -1
- package/dist/pkg/paths/index.js +0 -65
- package/dist/pkg/paths/index.js.map +0 -1
- package/dist/pkg/radix/index.d.ts.map +0 -1
- package/dist/pkg/radix/index.js +0 -8
- package/dist/pkg/radix/index.js.map +0 -1
- package/dist/pkg/radix/radix.d.ts.map +0 -1
- package/dist/pkg/radix/radix.js +0 -492
- package/dist/pkg/radix/radix.js.map +0 -1
- package/dist/pkg/radix/radix.test.d.ts +0 -2
- package/dist/pkg/radix/radix.test.d.ts.map +0 -1
- package/dist/pkg/radix/radix.test.js +0 -350
- package/dist/pkg/radix/radix.test.js.map +0 -1
- package/dist/pkg/string/index.d.ts.map +0 -1
- package/dist/pkg/string/index.js +0 -18
- package/dist/pkg/string/index.js.map +0 -1
- package/dist/pkg/string/string.d.ts.map +0 -1
- package/dist/pkg/string/string.js +0 -10
- package/dist/pkg/string/string.js.map +0 -1
- package/dist/pkg/text/index.d.ts.map +0 -1
- package/dist/pkg/text/index.js +0 -11
- package/dist/pkg/text/index.js.map +0 -1
- package/dist/pkg/types/index.d.ts.map +0 -1
- package/dist/pkg/types/index.js +0 -18
- package/dist/pkg/types/index.js.map +0 -1
- package/dist/pkg/types/types.d.ts.map +0 -1
- package/dist/pkg/types/types.js +0 -19
- package/dist/pkg/types/types.js.map +0 -1
- package/dist/pkg/web/server/electron-livereload-server.d.ts.map +0 -1
- package/dist/pkg/web/server/electron-livereload-server.js +0 -408
- package/dist/pkg/web/server/electron-livereload-server.js.map +0 -1
- package/dist/pkg/web/server/electron-livereload-server.test.d.ts +0 -2
- package/dist/pkg/web/server/electron-livereload-server.test.d.ts.map +0 -1
- package/dist/pkg/web/server/electron-livereload-server.test.js +0 -174
- package/dist/pkg/web/server/electron-livereload-server.test.js.map +0 -1
- package/dist/pkg/web/server/index.d.ts.map +0 -1
- package/dist/pkg/web/server/index.js +0 -61
- package/dist/pkg/web/server/index.js.map +0 -1
- package/dist/pkg/web/server/livereload-server.d.ts.map +0 -1
- package/dist/pkg/web/server/livereload-server.js +0 -400
- package/dist/pkg/web/server/livereload-server.js.map +0 -1
- package/dist/pkg/web/server/livereload-server.test.d.ts +0 -2
- package/dist/pkg/web/server/livereload-server.test.d.ts.map +0 -1
- package/dist/pkg/web/server/livereload-server.test.js +0 -188
- package/dist/pkg/web/server/livereload-server.test.js.map +0 -1
- package/dist/pkg/web/server/types.d.ts.map +0 -1
- package/dist/pkg/web/server/types.js +0 -3
- package/dist/pkg/web/server/types.js.map +0 -1
- package/dist/pkg/web/watcher/content-file-watcher.d.ts.map +0 -1
- package/dist/pkg/web/watcher/content-file-watcher.js +0 -169
- package/dist/pkg/web/watcher/content-file-watcher.js.map +0 -1
- package/dist/pkg/web/watcher/types.d.ts.map +0 -1
- package/dist/pkg/web/watcher/types.js +0 -3
- package/dist/pkg/web/watcher/types.js.map +0 -1
- package/dist/tests/setup.d.ts +0 -2
- package/dist/tests/setup.d.ts.map +0 -1
- package/dist/tests/setup.js +0 -3
- package/dist/tests/setup.js.map +0 -1
|
@@ -1,2835 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Template functions registry
|
|
4
|
-
* Centralized management of template functions following DDD principles
|
|
5
|
-
* TypeScript equivalent of Go's valueobject/nsreg.go
|
|
6
|
-
*/
|
|
7
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
-
if (k2 === undefined) k2 = k;
|
|
9
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
-
}
|
|
13
|
-
Object.defineProperty(o, k2, desc);
|
|
14
|
-
}) : (function(o, m, k, k2) {
|
|
15
|
-
if (k2 === undefined) k2 = k;
|
|
16
|
-
o[k2] = m[k];
|
|
17
|
-
}));
|
|
18
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
-
}) : function(o, v) {
|
|
21
|
-
o["default"] = v;
|
|
22
|
-
});
|
|
23
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
-
var ownKeys = function(o) {
|
|
25
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
-
var ar = [];
|
|
27
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
-
return ar;
|
|
29
|
-
};
|
|
30
|
-
return ownKeys(o);
|
|
31
|
-
};
|
|
32
|
-
return function (mod) {
|
|
33
|
-
if (mod && mod.__esModule) return mod;
|
|
34
|
-
var result = {};
|
|
35
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
-
__setModuleDefault(result, mod);
|
|
37
|
-
return result;
|
|
38
|
-
};
|
|
39
|
-
})();
|
|
40
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.DefaultTemplateRegistry = void 0;
|
|
42
|
-
exports.newTemplateRegistry = newTemplateRegistry;
|
|
43
|
-
exports.createCoreFuncMap = createCoreFuncMap;
|
|
44
|
-
exports.createStandardFuncMap = createStandardFuncMap;
|
|
45
|
-
exports.updateEngineDependentFunctions = updateEngineDependentFunctions;
|
|
46
|
-
const log_1 = require("../../../../pkg/log");
|
|
47
|
-
const crypto = __importStar(require("crypto"));
|
|
48
|
-
// Create domain-specific logger for template operations
|
|
49
|
-
const log = (0, log_1.getDomainLogger)('template', { component: 'registry' });
|
|
50
|
-
const engineDependentFunctions = [];
|
|
51
|
-
/**
|
|
52
|
-
* Partial function implementation that depends on TemplateEngine
|
|
53
|
-
*/
|
|
54
|
-
class PartialFunction {
|
|
55
|
-
engine = null;
|
|
56
|
-
getFunctionName() {
|
|
57
|
-
return 'partial';
|
|
58
|
-
}
|
|
59
|
-
updateEngine(engine) {
|
|
60
|
-
this.engine = engine;
|
|
61
|
-
}
|
|
62
|
-
execute = async (name, context) => {
|
|
63
|
-
if (!this.engine) {
|
|
64
|
-
log.error(`Partial function called but engine not set: ${name}`);
|
|
65
|
-
return `<!-- Partial function called but engine not ready: ${name} -->`;
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
// Ensure name has partials/ prefix if not already present
|
|
69
|
-
const templateName = name.startsWith('partials/') ? name : `partials/${name}`;
|
|
70
|
-
// Execute partial synchronously using engine's internal components
|
|
71
|
-
return await this.executePartial(templateName, context);
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
log.error(`Partial execution failed for "${name}":`, error);
|
|
75
|
-
return `<!-- Partial execution failed: ${name} - ${error.message} -->`;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* Execute partial synchronously by directly accessing template engine internals
|
|
80
|
-
*/
|
|
81
|
-
async executePartial(templateName, context) {
|
|
82
|
-
if (!this.engine) {
|
|
83
|
-
return `<!-- Template engine not available: ${templateName} -->`;
|
|
84
|
-
}
|
|
85
|
-
try {
|
|
86
|
-
// Use the new getPartial method which routes to PartialNamespace
|
|
87
|
-
const [templateObj, found, err] = await this.engine.getPartial(templateName);
|
|
88
|
-
if (err) {
|
|
89
|
-
log.error(`Error getting partial template:`, err);
|
|
90
|
-
return `<!-- Error getting partial template: ${templateName} - ${err.message} -->`;
|
|
91
|
-
}
|
|
92
|
-
if (!found || !templateObj) {
|
|
93
|
-
log.warn(`Template not found: ${templateName}`);
|
|
94
|
-
return `<!-- Template not found: ${templateName} -->`;
|
|
95
|
-
}
|
|
96
|
-
// Execute the template directly
|
|
97
|
-
const [result, execErr] = await templateObj.Execute(context);
|
|
98
|
-
if (execErr) {
|
|
99
|
-
log.error(`Template execution error:`, execErr);
|
|
100
|
-
return `<!-- Template execution error: ${templateName} - ${execErr.message} -->`;
|
|
101
|
-
}
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
catch (error) {
|
|
105
|
-
log.error(`Sync partial execution failed:`, error);
|
|
106
|
-
return `<!-- Partial sync execution failed: ${templateName} - ${error.message} -->`;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Template functions registry implementation
|
|
112
|
-
* Following DDD principles - encapsulates template function management logic
|
|
113
|
-
*/
|
|
114
|
-
class DefaultTemplateRegistry {
|
|
115
|
-
/**
|
|
116
|
-
* Register core template functions that don't require external services
|
|
117
|
-
* Equivalent to Go's RegisterNamespaces()
|
|
118
|
-
*/
|
|
119
|
-
registerCoreFunctions(funcMap) {
|
|
120
|
-
// Crypto functions
|
|
121
|
-
this.registerCryptoFunctions(funcMap);
|
|
122
|
-
// String manipulation functions
|
|
123
|
-
this.registerStringFunctions(funcMap);
|
|
124
|
-
// Math functions
|
|
125
|
-
this.registerMathFunctions(funcMap);
|
|
126
|
-
// Date/time functions
|
|
127
|
-
this.registerTimeFunctions(funcMap);
|
|
128
|
-
// Collection functions
|
|
129
|
-
this.registerCollectionFunctions(funcMap);
|
|
130
|
-
// Safe functions
|
|
131
|
-
this.registerSafeFunctions(funcMap);
|
|
132
|
-
// Reflect functions
|
|
133
|
-
this.registerReflectFunctions(funcMap);
|
|
134
|
-
// Format functions (printf, errorf, etc.)
|
|
135
|
-
this.registerFmtFunctions(funcMap);
|
|
136
|
-
// Path functions
|
|
137
|
-
this.registerPathFunctions(funcMap);
|
|
138
|
-
// Transform functions (unmarshal, etc.)
|
|
139
|
-
this.registerTransformFunctions(funcMap);
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Register cryptographic hash functions
|
|
143
|
-
* Equivalent to Go's crypto packages
|
|
144
|
-
*/
|
|
145
|
-
registerCryptoFunctions(funcMap) {
|
|
146
|
-
// MD5 hash function
|
|
147
|
-
funcMap.set('md5', (input) => {
|
|
148
|
-
if (!input)
|
|
149
|
-
return '';
|
|
150
|
-
return crypto.createHash('md5').update(input).digest('hex');
|
|
151
|
-
});
|
|
152
|
-
// AES-256-GCM encryption function
|
|
153
|
-
funcMap.set("encryptAESGCM", (password, content) => {
|
|
154
|
-
if (!password || !content)
|
|
155
|
-
return "";
|
|
156
|
-
const salt = crypto.randomBytes(16);
|
|
157
|
-
const iv = crypto.randomBytes(12);
|
|
158
|
-
// 派生 key:PBKDF2(SHA256)
|
|
159
|
-
const key = crypto.pbkdf2Sync(password, salt, 100000, 32, // 256-bit
|
|
160
|
-
"sha256");
|
|
161
|
-
// AES-GCM 加密
|
|
162
|
-
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
|
|
163
|
-
const encrypted = Buffer.concat([
|
|
164
|
-
cipher.update(content, "utf8"),
|
|
165
|
-
cipher.final(),
|
|
166
|
-
]);
|
|
167
|
-
const tag = cipher.getAuthTag();
|
|
168
|
-
// 输出格式:salt | iv | tag | ciphertext
|
|
169
|
-
const combined = Buffer.concat([salt, iv, tag, encrypted]);
|
|
170
|
-
return combined.toString("base64");
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Register extended template functions that require external services
|
|
175
|
-
* Equivalent to Go's RegisterExtendedNamespaces()
|
|
176
|
-
*/
|
|
177
|
-
registerExtendedFunctions(funcMap, services) {
|
|
178
|
-
// URL functions - require URL service
|
|
179
|
-
this.registerURLFunctions(funcMap, services);
|
|
180
|
-
// Site functions - require site service
|
|
181
|
-
this.registerSiteFunctions(funcMap, services);
|
|
182
|
-
this.registerResourcesFunctions(funcMap, services);
|
|
183
|
-
// Hugo functions - require hugo info service
|
|
184
|
-
this.registerHugoFunctions(funcMap, services);
|
|
185
|
-
// Language functions - require language service
|
|
186
|
-
this.registerLanguageFunctions(funcMap, services);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Register all available functions with services
|
|
190
|
-
* This is the main entry point for function registration
|
|
191
|
-
*/
|
|
192
|
-
registerAllFunctions(funcMap, services) {
|
|
193
|
-
this.registerCoreFunctions(funcMap);
|
|
194
|
-
this.registerStringFunctions(funcMap);
|
|
195
|
-
this.registerMathFunctions(funcMap);
|
|
196
|
-
this.registerTimeFunctions(funcMap);
|
|
197
|
-
this.registerCollectionFunctions(funcMap);
|
|
198
|
-
// Register engine-dependent functions (with placeholder implementations)
|
|
199
|
-
this.registerEngineDependentFunctions(funcMap);
|
|
200
|
-
// Register service-based functions if services are provided
|
|
201
|
-
if (services) {
|
|
202
|
-
this.registerURLFunctions(funcMap, services);
|
|
203
|
-
this.registerExtendedFunctions(funcMap, services);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Register functions that depend on TemplateEngine
|
|
208
|
-
* These functions are registered with placeholder implementations initially
|
|
209
|
-
*/
|
|
210
|
-
registerEngineDependentFunctions(funcMap) {
|
|
211
|
-
// Register partial function
|
|
212
|
-
const partialFunction = new PartialFunction();
|
|
213
|
-
engineDependentFunctions.push(partialFunction);
|
|
214
|
-
funcMap.set(partialFunction.getFunctionName(), partialFunction.execute);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Register URL template functions using URLService
|
|
218
|
-
* Equivalent to Go's registerUrls()
|
|
219
|
-
*/
|
|
220
|
-
registerURLFunctions(funcMap, services) {
|
|
221
|
-
// URLs namespace functions
|
|
222
|
-
funcMap.set('urls', () => ({
|
|
223
|
-
// Parse parses raw URL string into a URL structure
|
|
224
|
-
Parse: (rawurl) => {
|
|
225
|
-
try {
|
|
226
|
-
const u = new URL(rawurl);
|
|
227
|
-
return {
|
|
228
|
-
Host: u.host,
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
catch {
|
|
232
|
-
return {
|
|
233
|
-
Host: '',
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
// JoinPath joins path elements into a single path
|
|
238
|
-
JoinPath: (...elements) => {
|
|
239
|
-
// Remove empty elements and handle trailing slashes
|
|
240
|
-
const cleanElements = elements
|
|
241
|
-
.filter(e => e !== '')
|
|
242
|
-
.map(e => e.replace(/^\/+|\/+$/g, ''));
|
|
243
|
-
return cleanElements.join('/');
|
|
244
|
-
},
|
|
245
|
-
// URLize returns a URL-like string from the given text
|
|
246
|
-
URLize: (text) => services.urlize(text),
|
|
247
|
-
// Abs returns an absolute URL string
|
|
248
|
-
Abs: (url) => services.absURL(url),
|
|
249
|
-
// Rel returns a relative URL string
|
|
250
|
-
Rel: (url) => services.relURL(url),
|
|
251
|
-
// AbsLangURL returns an absolute URL modified with the language prefix
|
|
252
|
-
AbsLangURL: (url) => services.absURL(url), // TODO: Add language support
|
|
253
|
-
// RelLangURL returns a relative URL modified with the language prefix
|
|
254
|
-
RelLangURL: (url) => services.relURL(url), // TODO: Add language support
|
|
255
|
-
// Sanitize returns a sanitized string of the URL
|
|
256
|
-
Sanitize: (url) => {
|
|
257
|
-
try {
|
|
258
|
-
const parsed = new URL(url);
|
|
259
|
-
return parsed.toString();
|
|
260
|
-
}
|
|
261
|
-
catch {
|
|
262
|
-
// If not a valid URL, at least remove dangerous characters
|
|
263
|
-
return url.replace(/[<>"'%{}|\\^`]/g, '');
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
// PathEscape escapes special characters in a URL path
|
|
267
|
-
PathEscape: (path) => {
|
|
268
|
-
return encodeURIComponent(path)
|
|
269
|
-
.replace(/%2F/g, '/') // Keep forward slashes
|
|
270
|
-
.replace(/[!'()*]/g, c => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
271
|
-
},
|
|
272
|
-
// QueryEscape escapes special characters in a URL query
|
|
273
|
-
QueryEscape: (query) => {
|
|
274
|
-
return encodeURIComponent(query);
|
|
275
|
-
},
|
|
276
|
-
// QueryUnescape unescapes special characters in a URL query
|
|
277
|
-
QueryUnescape: (query) => {
|
|
278
|
-
try {
|
|
279
|
-
return decodeURIComponent(query);
|
|
280
|
-
}
|
|
281
|
-
catch {
|
|
282
|
-
return query;
|
|
283
|
-
}
|
|
284
|
-
},
|
|
285
|
-
// IsAbs reports whether the URL is absolute
|
|
286
|
-
IsAbs: (urlStr) => {
|
|
287
|
-
try {
|
|
288
|
-
const url = new URL(urlStr);
|
|
289
|
-
return url.protocol !== '';
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
},
|
|
295
|
-
// IsRelative reports whether the URL is relative
|
|
296
|
-
IsRelative: (urlStr) => {
|
|
297
|
-
try {
|
|
298
|
-
new URL(urlStr);
|
|
299
|
-
return false;
|
|
300
|
-
}
|
|
301
|
-
catch {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}));
|
|
306
|
-
// Individual URL functions for backward compatibility
|
|
307
|
-
funcMap.set('absURL', (input) => services.absURL(input));
|
|
308
|
-
funcMap.set('relURL', (input) => services.relURL(input));
|
|
309
|
-
funcMap.set('urlize', (input) => services.urlize(input));
|
|
310
|
-
// Reference functions
|
|
311
|
-
funcMap.set('relref', (page, ref) => {
|
|
312
|
-
// If ref starts with http:// or https://, return as is
|
|
313
|
-
if (/^https?:\/\//.test(ref)) {
|
|
314
|
-
return ref;
|
|
315
|
-
}
|
|
316
|
-
// Remove anchor if present and store it
|
|
317
|
-
let anchor = '';
|
|
318
|
-
const hashIndex = ref.indexOf('#');
|
|
319
|
-
if (hashIndex !== -1) {
|
|
320
|
-
anchor = ref.slice(hashIndex);
|
|
321
|
-
ref = ref.slice(0, hashIndex);
|
|
322
|
-
}
|
|
323
|
-
// Remove leading and trailing slashes
|
|
324
|
-
ref = ref.replace(/^\/+|\/+$/g, '');
|
|
325
|
-
// If it's a relative path starting with ./ or ../, use relURL
|
|
326
|
-
if (ref.startsWith('./') || ref.startsWith('../')) {
|
|
327
|
-
return services.relURL(ref + anchor);
|
|
328
|
-
}
|
|
329
|
-
// Handle absolute paths
|
|
330
|
-
if (ref.startsWith('/')) {
|
|
331
|
-
return services.relURL(ref + anchor);
|
|
332
|
-
}
|
|
333
|
-
// For other cases, treat as relative path
|
|
334
|
-
return services.relURL('/' + ref + anchor);
|
|
335
|
-
});
|
|
336
|
-
funcMap.set('ref', (page, ref) => {
|
|
337
|
-
// Similar to relref but returns absolute URL
|
|
338
|
-
// If ref starts with http:// or https://, return as is
|
|
339
|
-
if (/^https?:\/\//.test(ref)) {
|
|
340
|
-
return ref;
|
|
341
|
-
}
|
|
342
|
-
// Remove anchor if present and store it
|
|
343
|
-
let anchor = '';
|
|
344
|
-
const hashIndex = ref.indexOf('#');
|
|
345
|
-
if (hashIndex !== -1) {
|
|
346
|
-
anchor = ref.slice(hashIndex);
|
|
347
|
-
ref = ref.slice(0, hashIndex);
|
|
348
|
-
}
|
|
349
|
-
// Remove leading and trailing slashes
|
|
350
|
-
ref = ref.replace(/^\/+|\/+$/g, '');
|
|
351
|
-
// If it's a relative path starting with ./ or ../, use absURL
|
|
352
|
-
if (ref.startsWith('./') || ref.startsWith('../')) {
|
|
353
|
-
return services.absURL(ref + anchor);
|
|
354
|
-
}
|
|
355
|
-
// Handle absolute paths
|
|
356
|
-
if (ref.startsWith('/')) {
|
|
357
|
-
return services.absURL(ref + anchor);
|
|
358
|
-
}
|
|
359
|
-
// For other cases, treat as relative path
|
|
360
|
-
return services.absURL('/' + ref + anchor);
|
|
361
|
-
});
|
|
362
|
-
// Language-aware URL functions
|
|
363
|
-
funcMap.set('absLangURL', (input) => {
|
|
364
|
-
// For now, delegate to absURL - can be enhanced for multi-language support
|
|
365
|
-
return services.absURL(input);
|
|
366
|
-
});
|
|
367
|
-
funcMap.set('relLangURL', (input) => {
|
|
368
|
-
// For now, delegate to relURL - can be enhanced for multi-language support
|
|
369
|
-
return services.relURL(input);
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Register site template functions using SiteService
|
|
374
|
-
* Equivalent to Go's registerSite()
|
|
375
|
-
*/
|
|
376
|
-
registerSiteFunctions(funcMap, services) {
|
|
377
|
-
// Site global object - register as a function that returns the site data
|
|
378
|
-
funcMap.set('Site', () => ({
|
|
379
|
-
Title: services.title(),
|
|
380
|
-
BaseURL: services.baseURL(),
|
|
381
|
-
Params: services.params(),
|
|
382
|
-
Menus: services.menus(),
|
|
383
|
-
IsMultiLingual: services.isMultiLanguage(),
|
|
384
|
-
LanguageCode: services.defaultLanguage()
|
|
385
|
-
}));
|
|
386
|
-
}
|
|
387
|
-
registerResourcesFunctions(funcMap, services) {
|
|
388
|
-
funcMap.set('resources', () => ({
|
|
389
|
-
Get: async (filename) => await services.Get(filename),
|
|
390
|
-
GetRemote: async (uri) => await services.GetRemote(uri),
|
|
391
|
-
Minify: async (resource) => await services.Minify(resource),
|
|
392
|
-
Fingerprint: async (resource) => await services.Fingerprint(resource),
|
|
393
|
-
ExecuteAsTemplate: async (targetPath, data, resource) => await services.ExecuteAsTemplate(targetPath, data, resource)
|
|
394
|
-
}));
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Register Hugo template functions using HugoInfoService
|
|
398
|
-
* Equivalent to Go's registerHugo()
|
|
399
|
-
*/
|
|
400
|
-
registerHugoFunctions(funcMap, services) {
|
|
401
|
-
funcMap.set('hugo', () => ({
|
|
402
|
-
Version: services.version(),
|
|
403
|
-
Environment: services.environment(),
|
|
404
|
-
Generator: services.generator()
|
|
405
|
-
}));
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Register language template functions using LanguageService
|
|
409
|
-
* Equivalent to Go's registerLang()
|
|
410
|
-
*/
|
|
411
|
-
registerLanguageFunctions(funcMap, services) {
|
|
412
|
-
// Import language service
|
|
413
|
-
const { lang } = require('../../../../pkg/lang');
|
|
414
|
-
// Language namespace functions
|
|
415
|
-
funcMap.set('lang', () => ({
|
|
416
|
-
// Get all language codes
|
|
417
|
-
getAllCodes: () => lang.getAllCodes(),
|
|
418
|
-
// Get all language names
|
|
419
|
-
getAllNames: () => lang.getAllNames(),
|
|
420
|
-
// Get language codes by direction
|
|
421
|
-
getCodesByDirection: (direction) => lang.getCodesByDirection(direction),
|
|
422
|
-
// Get language names by direction
|
|
423
|
-
getNamesByDirection: (direction) => lang.getNamesByDirection(direction),
|
|
424
|
-
// Get code-name mapping
|
|
425
|
-
getCodeNameMap: () => lang.getCodeNameMap(),
|
|
426
|
-
// Get code-name mapping by direction
|
|
427
|
-
getCodeNameMapByDirection: (direction) => lang.getCodeNameMapByDirection(direction),
|
|
428
|
-
// Get language name by code
|
|
429
|
-
getNameByCode: (code) => lang.getNameByCode(code),
|
|
430
|
-
// Get language info by code
|
|
431
|
-
getLanguageInfo: (code) => lang.getLanguageInfo(code),
|
|
432
|
-
// Check if language is supported
|
|
433
|
-
isSupported: (code) => lang.isSupported(code),
|
|
434
|
-
// Get language direction
|
|
435
|
-
getDirection: (code) => lang.getDirection(code),
|
|
436
|
-
// Check if language is LTR
|
|
437
|
-
isLTR: (code) => lang.isLTR(code),
|
|
438
|
-
// Check if language is RTL
|
|
439
|
-
isRTL: (code) => lang.isRTL(code)
|
|
440
|
-
}));
|
|
441
|
-
// Standalone functions for convenience
|
|
442
|
-
funcMap.set('langName', (code) => lang.getNameByCode(code) || code);
|
|
443
|
-
funcMap.set('langDirection', (code) => lang.getDirection(code) || 'ltr');
|
|
444
|
-
funcMap.set('isLTR', (code) => lang.isLTR(code));
|
|
445
|
-
funcMap.set('isRTL', (code) => lang.isRTL(code));
|
|
446
|
-
// i18n placeholder (can be extended later)
|
|
447
|
-
funcMap.set('i18n', (key) => {
|
|
448
|
-
return services.translate(key);
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
/**
|
|
452
|
-
* Register string manipulation functions
|
|
453
|
-
* Equivalent to Go's registerStrings()
|
|
454
|
-
*/
|
|
455
|
-
registerStringFunctions(funcMap) {
|
|
456
|
-
// Humanize converts ID-style strings to human readable format
|
|
457
|
-
funcMap.set('humanize', (str) => {
|
|
458
|
-
if (!str)
|
|
459
|
-
return '';
|
|
460
|
-
// Convert from camelCase or PascalCase
|
|
461
|
-
str = str.replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
462
|
-
// Convert from snake_case or kebab-case
|
|
463
|
-
str = str.replace(/[_-]+/g, ' ');
|
|
464
|
-
// Remove file extensions
|
|
465
|
-
str = str.replace(/\.[^/.]+$/, '');
|
|
466
|
-
// Capitalize first letter, rest lowercase
|
|
467
|
-
str = str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
468
|
-
// Trim spaces
|
|
469
|
-
return str.trim();
|
|
470
|
-
});
|
|
471
|
-
funcMap.set('upper', (str) => str.toUpperCase());
|
|
472
|
-
funcMap.set('lower', (str) => str.toLowerCase());
|
|
473
|
-
funcMap.set('title', (str) => str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()));
|
|
474
|
-
funcMap.set('trim', (str) => str.trim());
|
|
475
|
-
funcMap.set('replace', (...args) => {
|
|
476
|
-
if (args.length < 3) {
|
|
477
|
-
throw new Error('replace requires at least 3 arguments: string, old, new');
|
|
478
|
-
}
|
|
479
|
-
const str = String(args[0]);
|
|
480
|
-
const old = String(args[1]);
|
|
481
|
-
const newStr = String(args[2]);
|
|
482
|
-
// Handle optional limit parameter like Go's implementation
|
|
483
|
-
if (args.length >= 4) {
|
|
484
|
-
const limit = Number(args[3]);
|
|
485
|
-
if (isNaN(limit)) {
|
|
486
|
-
throw new Error('replace limit must be a number');
|
|
487
|
-
}
|
|
488
|
-
// Implement limited replacement like Go's strings.Replace
|
|
489
|
-
let result = str;
|
|
490
|
-
let count = 0;
|
|
491
|
-
let startIndex = 0;
|
|
492
|
-
while (count < limit && startIndex < result.length) {
|
|
493
|
-
const index = result.indexOf(old, startIndex);
|
|
494
|
-
if (index === -1)
|
|
495
|
-
break;
|
|
496
|
-
result = result.substring(0, index) + newStr + result.substring(index + old.length);
|
|
497
|
-
startIndex = index + newStr.length;
|
|
498
|
-
count++;
|
|
499
|
-
}
|
|
500
|
-
return result;
|
|
501
|
-
}
|
|
502
|
-
// Default behavior: replace all occurrences (like Go's strings.ReplaceAll)
|
|
503
|
-
return str.split(old).join(newStr);
|
|
504
|
-
});
|
|
505
|
-
// ReplaceRE function - global alias following Go pattern
|
|
506
|
-
// Usage: {{ replaceRE "a+b" "X" "aabbaabbab" }} -> "XbXbX"
|
|
507
|
-
// Usage: {{ replaceRE "a+b" "X" "aabbaabbab" 1 }} -> "Xbaabbab"
|
|
508
|
-
funcMap.set('replaceRE', (...args) => {
|
|
509
|
-
if (args.length < 3) {
|
|
510
|
-
throw new Error('replaceRE requires at least 3 arguments: pattern, replacement, string');
|
|
511
|
-
}
|
|
512
|
-
const pattern = args[0];
|
|
513
|
-
const repl = args[1];
|
|
514
|
-
const s = args[2];
|
|
515
|
-
const n = args.length >= 4 ? args[3] : undefined;
|
|
516
|
-
// Use the strings namespace ReplaceRE implementation
|
|
517
|
-
const stringsNs = funcMap.get('strings')();
|
|
518
|
-
return stringsNs.ReplaceRE(pattern, repl, s, n);
|
|
519
|
-
});
|
|
520
|
-
// Split function - ensure first parameter is the string to split
|
|
521
|
-
funcMap.set('split', (str, sep) => {
|
|
522
|
-
// Handle null and undefined cases first
|
|
523
|
-
if (str === null || str === undefined) {
|
|
524
|
-
log.warn('split function: first argument is null or undefined');
|
|
525
|
-
return [];
|
|
526
|
-
}
|
|
527
|
-
if (typeof str !== 'string') {
|
|
528
|
-
log.warn('split function: first argument must be a string, got:', typeof str, 'value:', str);
|
|
529
|
-
// If it's an array, try to join it or return as is
|
|
530
|
-
if (Array.isArray(str)) {
|
|
531
|
-
return str;
|
|
532
|
-
}
|
|
533
|
-
// Try to convert to string
|
|
534
|
-
const stringValue = String(str);
|
|
535
|
-
return stringValue.split(sep);
|
|
536
|
-
}
|
|
537
|
-
return str.split(sep);
|
|
538
|
-
});
|
|
539
|
-
// SplitRegex function - split string using regex pattern
|
|
540
|
-
funcMap.set('splitRegex', (str, regexPattern) => {
|
|
541
|
-
// Handle null and undefined cases first
|
|
542
|
-
if (str === null || str === undefined) {
|
|
543
|
-
log.warn('splitRegex function: first argument is null or undefined');
|
|
544
|
-
return [];
|
|
545
|
-
}
|
|
546
|
-
if (typeof str !== 'string') {
|
|
547
|
-
log.warn('splitRegex function: first argument must be a string, got:', typeof str, 'value:', str);
|
|
548
|
-
// If it's an array, try to join it or return as is
|
|
549
|
-
if (Array.isArray(str)) {
|
|
550
|
-
return str;
|
|
551
|
-
}
|
|
552
|
-
// Try to convert to string
|
|
553
|
-
const stringValue = String(str);
|
|
554
|
-
try {
|
|
555
|
-
const regex = new RegExp(regexPattern);
|
|
556
|
-
return stringValue.split(regex);
|
|
557
|
-
}
|
|
558
|
-
catch (error) {
|
|
559
|
-
log.warn('splitRegex function: invalid regex pattern:', regexPattern, 'error:', error);
|
|
560
|
-
return [stringValue];
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
try {
|
|
564
|
-
const regex = new RegExp(regexPattern);
|
|
565
|
-
return str.split(regex);
|
|
566
|
-
}
|
|
567
|
-
catch (error) {
|
|
568
|
-
log.warn('splitRegex function: invalid regex pattern:', regexPattern, 'error:', error);
|
|
569
|
-
return [str];
|
|
570
|
-
}
|
|
571
|
-
});
|
|
572
|
-
// Join function
|
|
573
|
-
funcMap.set('delimit', (arr, sep) => {
|
|
574
|
-
if (Array.isArray(arr)) {
|
|
575
|
-
return arr.join(sep);
|
|
576
|
-
}
|
|
577
|
-
return String(arr);
|
|
578
|
-
});
|
|
579
|
-
// Contains function
|
|
580
|
-
funcMap.set('in', (matchValue, item) => {
|
|
581
|
-
if (Array.isArray(matchValue)) {
|
|
582
|
-
return matchValue.includes(item);
|
|
583
|
-
}
|
|
584
|
-
if (typeof matchValue === 'string' && typeof item === 'string') {
|
|
585
|
-
return matchValue.includes(item);
|
|
586
|
-
}
|
|
587
|
-
return false;
|
|
588
|
-
});
|
|
589
|
-
// HasPrefix function
|
|
590
|
-
funcMap.set('hasPrefix', (str, prefix) => str.startsWith(prefix));
|
|
591
|
-
// HasSuffix function
|
|
592
|
-
funcMap.set('hasSuffix', (str, suffix) => str.endsWith(suffix));
|
|
593
|
-
// Strings namespace - following Go's strings namespace pattern
|
|
594
|
-
funcMap.set('strings', () => ({
|
|
595
|
-
// Basic string operations
|
|
596
|
-
ToLower: (s) => String(s).toLowerCase(),
|
|
597
|
-
ToUpper: (s) => String(s).toUpperCase(),
|
|
598
|
-
Title: (s) => String(s).replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()),
|
|
599
|
-
// Trimming functions
|
|
600
|
-
Trim: (s, cutset) => String(s).split('').filter(c => !cutset.includes(c)).join(''),
|
|
601
|
-
TrimSpace: (s) => String(s).trim(),
|
|
602
|
-
TrimLeft: (cutset, s) => {
|
|
603
|
-
const str = String(s);
|
|
604
|
-
let i = 0;
|
|
605
|
-
while (i < str.length && cutset.includes(str[i])) {
|
|
606
|
-
i++;
|
|
607
|
-
}
|
|
608
|
-
return str.slice(i);
|
|
609
|
-
},
|
|
610
|
-
TrimRight: (cutset, s) => {
|
|
611
|
-
const str = String(s);
|
|
612
|
-
let i = str.length - 1;
|
|
613
|
-
while (i >= 0 && cutset.includes(str[i])) {
|
|
614
|
-
i--;
|
|
615
|
-
}
|
|
616
|
-
return str.slice(0, i + 1);
|
|
617
|
-
},
|
|
618
|
-
TrimPrefix: (prefix, s) => {
|
|
619
|
-
const str = String(s);
|
|
620
|
-
return str.startsWith(prefix) ? str.slice(prefix.length) : str;
|
|
621
|
-
},
|
|
622
|
-
TrimSuffix: (suffix, s) => {
|
|
623
|
-
const str = String(s);
|
|
624
|
-
return str.endsWith(suffix) ? str.slice(0, -suffix.length) : str;
|
|
625
|
-
},
|
|
626
|
-
// Testing functions
|
|
627
|
-
Contains: (s, substr) => String(s).includes(substr),
|
|
628
|
-
ContainsAny: (s, chars) => {
|
|
629
|
-
const str = String(s);
|
|
630
|
-
return chars.split('').some(char => str.includes(char));
|
|
631
|
-
},
|
|
632
|
-
HasPrefix: (s, prefix) => String(s).startsWith(prefix),
|
|
633
|
-
HasSuffix: (s, suffix) => String(s).endsWith(suffix),
|
|
634
|
-
// Replacement functions
|
|
635
|
-
Replace: (s, old, newStr, limit) => {
|
|
636
|
-
const str = String(s);
|
|
637
|
-
if (limit === undefined) {
|
|
638
|
-
// Replace all occurrences (like Go's strings.ReplaceAll)
|
|
639
|
-
return str.split(old).join(newStr);
|
|
640
|
-
}
|
|
641
|
-
// Implement limited replacement like Go's strings.Replace
|
|
642
|
-
let result = str;
|
|
643
|
-
let count = 0;
|
|
644
|
-
let startIndex = 0;
|
|
645
|
-
while (count < limit && startIndex < result.length) {
|
|
646
|
-
const index = result.indexOf(old, startIndex);
|
|
647
|
-
if (index === -1)
|
|
648
|
-
break;
|
|
649
|
-
result = result.substring(0, index) + newStr + result.substring(index + old.length);
|
|
650
|
-
startIndex = index + newStr.length;
|
|
651
|
-
count++;
|
|
652
|
-
}
|
|
653
|
-
return result;
|
|
654
|
-
},
|
|
655
|
-
// ReplaceRE returns a copy of s, replacing all matches of the regular
|
|
656
|
-
// expression pattern with the replacement text repl. The number of replacements
|
|
657
|
-
// can be limited with an optional fourth parameter.
|
|
658
|
-
// Follows Go's implementation strictly
|
|
659
|
-
ReplaceRE: (pattern, repl, s, n) => {
|
|
660
|
-
// Convert all parameters to strings (following Go's cast.ToStringE behavior)
|
|
661
|
-
const sp = String(pattern);
|
|
662
|
-
const sr = String(repl);
|
|
663
|
-
const ss = String(s);
|
|
664
|
-
// Handle optional limit parameter (following Go's cast.ToIntE behavior)
|
|
665
|
-
let nn = -1; // -1 means replace all (Go default)
|
|
666
|
-
if (n !== undefined) {
|
|
667
|
-
const parsed = parseInt(String(n), 10);
|
|
668
|
-
if (isNaN(parsed)) {
|
|
669
|
-
throw new Error('limit argument must be integer');
|
|
670
|
-
}
|
|
671
|
-
nn = parsed;
|
|
672
|
-
}
|
|
673
|
-
let re;
|
|
674
|
-
try {
|
|
675
|
-
// Create regex with global flag for multiple replacements
|
|
676
|
-
re = new RegExp(sp, 'g');
|
|
677
|
-
}
|
|
678
|
-
catch (err) {
|
|
679
|
-
throw new Error(`invalid regular expression: ${sp}`);
|
|
680
|
-
}
|
|
681
|
-
// Follow Go's ReplaceAllStringFunc implementation with counter
|
|
682
|
-
let replacementCount = 0;
|
|
683
|
-
return ss.replace(re, (match) => {
|
|
684
|
-
// If we've reached the limit, return the original match
|
|
685
|
-
if (nn >= 0 && replacementCount >= nn) {
|
|
686
|
-
return match;
|
|
687
|
-
}
|
|
688
|
-
replacementCount++;
|
|
689
|
-
return sr;
|
|
690
|
-
});
|
|
691
|
-
},
|
|
692
|
-
// Splitting and slicing
|
|
693
|
-
Split: (s, delimiter) => String(s).split(delimiter),
|
|
694
|
-
SliceString: (s, start, end) => {
|
|
695
|
-
const str = String(s);
|
|
696
|
-
return end !== undefined ? str.slice(start, end) : str.slice(start);
|
|
697
|
-
},
|
|
698
|
-
Substr: (s, start, length) => {
|
|
699
|
-
const str = String(s);
|
|
700
|
-
if (start < 0)
|
|
701
|
-
start = str.length + start;
|
|
702
|
-
if (start < 0)
|
|
703
|
-
start = 0;
|
|
704
|
-
if (start >= str.length)
|
|
705
|
-
return '';
|
|
706
|
-
if (length === undefined)
|
|
707
|
-
return str.slice(start);
|
|
708
|
-
if (length <= 0)
|
|
709
|
-
return '';
|
|
710
|
-
return str.slice(start, start + length);
|
|
711
|
-
},
|
|
712
|
-
// Utility functions
|
|
713
|
-
Count: (substr, s) => {
|
|
714
|
-
const str = String(s);
|
|
715
|
-
if (!substr)
|
|
716
|
-
return str.length + 1;
|
|
717
|
-
return (str.match(new RegExp(substr.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g')) || []).length;
|
|
718
|
-
},
|
|
719
|
-
CountWords: (s) => {
|
|
720
|
-
const str = String(s).trim();
|
|
721
|
-
return str ? str.split(/\s+/).length : 0;
|
|
722
|
-
},
|
|
723
|
-
CountRunes: (s) => {
|
|
724
|
-
const str = String(s);
|
|
725
|
-
return str.replace(/\s/g, '').length;
|
|
726
|
-
},
|
|
727
|
-
RuneCount: (s) => String(s).length,
|
|
728
|
-
// Repeat function
|
|
729
|
-
Repeat: (n, s) => {
|
|
730
|
-
if (n < 0)
|
|
731
|
-
throw new Error('strings: negative Repeat count');
|
|
732
|
-
return String(s).repeat(n);
|
|
733
|
-
},
|
|
734
|
-
// First letter upper
|
|
735
|
-
FirstUpper: (s) => {
|
|
736
|
-
const str = String(s);
|
|
737
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
738
|
-
}
|
|
739
|
-
}));
|
|
740
|
-
// Substr extracts parts of a string, beginning at the character at the specified
|
|
741
|
-
// position, and returns the specified number of characters.
|
|
742
|
-
// It normally takes two parameters: start and length.
|
|
743
|
-
// It can also take one parameter: start, i.e. length is omitted, in which case
|
|
744
|
-
// the substring starting from start until the end of the string will be returned.
|
|
745
|
-
// To extract characters from the end of the string, use a negative start number.
|
|
746
|
-
// If length is given and is negative, then that many characters will be omitted from
|
|
747
|
-
// the end of string.
|
|
748
|
-
// Equivalent to Go's Substr function in strings namespace
|
|
749
|
-
// Usage: {{ substr "hello world" 0 5 }} -> "hello"
|
|
750
|
-
// Usage: {{ substr "hello world" 6 }} -> "world"
|
|
751
|
-
// Usage: {{ substr "hello world" -5 }} -> "world"
|
|
752
|
-
// Usage: {{ substr "hello world" 0 -6 }} -> "hello"
|
|
753
|
-
funcMap.set('substr', (a, ...nums) => {
|
|
754
|
-
// Convert input to string
|
|
755
|
-
const s = String(a);
|
|
756
|
-
// Convert string to array of characters to handle Unicode properly
|
|
757
|
-
const chars = Array.from(s);
|
|
758
|
-
const rlen = chars.length;
|
|
759
|
-
let start;
|
|
760
|
-
let length;
|
|
761
|
-
// Parse arguments
|
|
762
|
-
switch (nums.length) {
|
|
763
|
-
case 0:
|
|
764
|
-
throw new Error('too few arguments');
|
|
765
|
-
case 1:
|
|
766
|
-
// Only start parameter provided
|
|
767
|
-
const startNum = Number(nums[0]);
|
|
768
|
-
if (isNaN(startNum) || !Number.isInteger(startNum)) {
|
|
769
|
-
throw new Error('start argument must be an integer');
|
|
770
|
-
}
|
|
771
|
-
start = startNum;
|
|
772
|
-
length = rlen;
|
|
773
|
-
break;
|
|
774
|
-
case 2:
|
|
775
|
-
// Both start and length parameters provided
|
|
776
|
-
const startNum2 = Number(nums[0]);
|
|
777
|
-
const lengthNum = Number(nums[1]);
|
|
778
|
-
if (isNaN(startNum2) || !Number.isInteger(startNum2)) {
|
|
779
|
-
throw new Error('start argument must be an integer');
|
|
780
|
-
}
|
|
781
|
-
if (isNaN(lengthNum) || !Number.isInteger(lengthNum)) {
|
|
782
|
-
throw new Error('length argument must be an integer');
|
|
783
|
-
}
|
|
784
|
-
start = startNum2;
|
|
785
|
-
length = lengthNum;
|
|
786
|
-
break;
|
|
787
|
-
default:
|
|
788
|
-
throw new Error('too many arguments');
|
|
789
|
-
}
|
|
790
|
-
// Handle empty string
|
|
791
|
-
if (rlen === 0) {
|
|
792
|
-
return '';
|
|
793
|
-
}
|
|
794
|
-
// Handle negative start (count from end)
|
|
795
|
-
if (start < 0) {
|
|
796
|
-
start += rlen;
|
|
797
|
-
}
|
|
798
|
-
// If start was originally negative beyond rlen, set to 0
|
|
799
|
-
if (start < 0) {
|
|
800
|
-
start = 0;
|
|
801
|
-
}
|
|
802
|
-
// If start is beyond the string length, return empty
|
|
803
|
-
if (start > rlen - 1) {
|
|
804
|
-
return '';
|
|
805
|
-
}
|
|
806
|
-
let end = rlen;
|
|
807
|
-
// Handle different length cases
|
|
808
|
-
if (length === 0) {
|
|
809
|
-
return '';
|
|
810
|
-
}
|
|
811
|
-
else if (length < 0) {
|
|
812
|
-
// Negative length: omit that many characters from end
|
|
813
|
-
end += length;
|
|
814
|
-
}
|
|
815
|
-
else if (length > 0) {
|
|
816
|
-
// Positive length: take that many characters from start
|
|
817
|
-
end = start + length;
|
|
818
|
-
}
|
|
819
|
-
// Validate bounds
|
|
820
|
-
if (start >= end) {
|
|
821
|
-
return '';
|
|
822
|
-
}
|
|
823
|
-
if (end < 0) {
|
|
824
|
-
return '';
|
|
825
|
-
}
|
|
826
|
-
// Clamp end to string length
|
|
827
|
-
if (end > rlen) {
|
|
828
|
-
end = rlen;
|
|
829
|
-
}
|
|
830
|
-
// Extract substring
|
|
831
|
-
return chars.slice(start, end).join('');
|
|
832
|
-
});
|
|
833
|
-
// Truncate truncates the string to the specified length
|
|
834
|
-
// Equivalent to Go's Truncate function in strings namespace
|
|
835
|
-
// Usage: {{ truncate 10 "hello world" }} -> "hello …"
|
|
836
|
-
// Usage: {{ truncate 10 "..." "hello world" }} -> "hello..."
|
|
837
|
-
// Supports HTML-aware truncation
|
|
838
|
-
funcMap.set('truncate', (lengthParam, ...options) => {
|
|
839
|
-
// Parse length parameter
|
|
840
|
-
const length = Number(lengthParam);
|
|
841
|
-
if (isNaN(length) || !Number.isInteger(length)) {
|
|
842
|
-
throw new Error('truncate length must be an integer');
|
|
843
|
-
}
|
|
844
|
-
let textParam;
|
|
845
|
-
let ellipsis = ' …';
|
|
846
|
-
// Parse options
|
|
847
|
-
switch (options.length) {
|
|
848
|
-
case 0:
|
|
849
|
-
throw new Error('truncate requires a length and a string');
|
|
850
|
-
case 1:
|
|
851
|
-
textParam = options[0];
|
|
852
|
-
ellipsis = ' …';
|
|
853
|
-
break;
|
|
854
|
-
case 2:
|
|
855
|
-
ellipsis = String(options[0]);
|
|
856
|
-
textParam = options[1];
|
|
857
|
-
break;
|
|
858
|
-
default:
|
|
859
|
-
throw new Error('too many arguments passed to truncate');
|
|
860
|
-
}
|
|
861
|
-
// Convert text to string
|
|
862
|
-
const text = String(textParam);
|
|
863
|
-
// Check if input is HTML (simple heuristic: contains HTML tags)
|
|
864
|
-
const isHTML = /<[^>]+>/.test(text);
|
|
865
|
-
// Convert to array of characters for proper Unicode handling
|
|
866
|
-
const chars = Array.from(text);
|
|
867
|
-
// If text is already shorter than or equal to length, return as-is
|
|
868
|
-
if (chars.length <= length) {
|
|
869
|
-
if (isHTML) {
|
|
870
|
-
return text; // Return as HTML
|
|
871
|
-
}
|
|
872
|
-
return this.escapeHTML(text);
|
|
873
|
-
}
|
|
874
|
-
if (isHTML) {
|
|
875
|
-
return this.truncateHTML(text, length, ellipsis);
|
|
876
|
-
}
|
|
877
|
-
else {
|
|
878
|
-
return this.truncateText(text, length, ellipsis);
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
/**
|
|
883
|
-
* HTML escape utility function
|
|
884
|
-
*/
|
|
885
|
-
escapeHTML(text) {
|
|
886
|
-
return text
|
|
887
|
-
.replace(/&/g, '&')
|
|
888
|
-
.replace(/</g, '<')
|
|
889
|
-
.replace(/>/g, '>')
|
|
890
|
-
.replace(/"/g, '"')
|
|
891
|
-
.replace(/'/g, ''');
|
|
892
|
-
}
|
|
893
|
-
/**
|
|
894
|
-
* Truncate plain text, breaking at word boundaries when possible
|
|
895
|
-
*/
|
|
896
|
-
truncateText(text, length, ellipsis) {
|
|
897
|
-
const chars = Array.from(text);
|
|
898
|
-
if (chars.length <= length) {
|
|
899
|
-
return this.escapeHTML(text);
|
|
900
|
-
}
|
|
901
|
-
let lastWordIndex = 0;
|
|
902
|
-
let currentLen = 0;
|
|
903
|
-
// Find the best truncation point (word boundary)
|
|
904
|
-
for (let i = 0; i < chars.length && currentLen < length; i++) {
|
|
905
|
-
const char = chars[i];
|
|
906
|
-
currentLen++;
|
|
907
|
-
if (/\s/.test(char)) {
|
|
908
|
-
lastWordIndex = i;
|
|
909
|
-
}
|
|
910
|
-
// For CJK characters, each character can be a word boundary
|
|
911
|
-
if (/[\u4e00-\u9fff\u3400-\u4dbf\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(char)) {
|
|
912
|
-
lastWordIndex = i;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
// Determine truncation point
|
|
916
|
-
let endPos = currentLen >= length ? (lastWordIndex > 0 ? lastWordIndex : length) : chars.length;
|
|
917
|
-
const truncated = chars.slice(0, endPos).join('');
|
|
918
|
-
return this.escapeHTML(truncated) + ellipsis;
|
|
919
|
-
}
|
|
920
|
-
/**
|
|
921
|
-
* Truncate HTML text while preserving tag structure
|
|
922
|
-
*/
|
|
923
|
-
truncateHTML(text, length, ellipsis) {
|
|
924
|
-
const tagRegex = /^<(\/)?([^ ]+?)(?:(\s*\/)| .*?)?>/;
|
|
925
|
-
const htmlSinglets = new Set(['br', 'col', 'link', 'base', 'img', 'param', 'area', 'hr', 'input']);
|
|
926
|
-
const tags = [];
|
|
927
|
-
let lastWordIndex = 0;
|
|
928
|
-
let lastNonSpace = 0;
|
|
929
|
-
let currentLen = 0;
|
|
930
|
-
let endTextPos = 0;
|
|
931
|
-
let i = 0;
|
|
932
|
-
const chars = Array.from(text);
|
|
933
|
-
while (i < chars.length) {
|
|
934
|
-
const currentChar = chars[i];
|
|
935
|
-
// Check for HTML tag
|
|
936
|
-
if (currentChar === '<') {
|
|
937
|
-
const remainingText = chars.slice(i).join('');
|
|
938
|
-
const match = remainingText.match(tagRegex);
|
|
939
|
-
if (match) {
|
|
940
|
-
const fullMatch = match[0];
|
|
941
|
-
const isClosing = match[1] === '/';
|
|
942
|
-
const tagName = match[2].toLowerCase();
|
|
943
|
-
const isSelfClosing = match[3] === '/';
|
|
944
|
-
// Skip the entire tag
|
|
945
|
-
i += fullMatch.length;
|
|
946
|
-
lastWordIndex = lastNonSpace;
|
|
947
|
-
// Track non-singlet tags for proper closing
|
|
948
|
-
const isSinglet = htmlSinglets.has(tagName);
|
|
949
|
-
if (!isSinglet && !isSelfClosing) {
|
|
950
|
-
tags.push({
|
|
951
|
-
name: tagName,
|
|
952
|
-
pos: i - fullMatch.length,
|
|
953
|
-
openTag: !isClosing
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
continue;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
// Count actual text characters
|
|
960
|
-
currentLen++;
|
|
961
|
-
if (/\s/.test(currentChar)) {
|
|
962
|
-
lastWordIndex = lastNonSpace;
|
|
963
|
-
}
|
|
964
|
-
else if (/[\u4e00-\u9fff\u3400-\u4dbf\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(currentChar)) {
|
|
965
|
-
// CJK characters can break at any character
|
|
966
|
-
lastWordIndex = i;
|
|
967
|
-
}
|
|
968
|
-
else {
|
|
969
|
-
lastNonSpace = i + 1;
|
|
970
|
-
}
|
|
971
|
-
if (currentLen > length) {
|
|
972
|
-
endTextPos = lastWordIndex > 0 ? lastWordIndex : i;
|
|
973
|
-
break;
|
|
974
|
-
}
|
|
975
|
-
i++;
|
|
976
|
-
}
|
|
977
|
-
if (currentLen <= length) {
|
|
978
|
-
return text; // No truncation needed
|
|
979
|
-
}
|
|
980
|
-
let output = chars.slice(0, endTextPos).join('') + ellipsis;
|
|
981
|
-
// Close any open HTML tags
|
|
982
|
-
let currentTag = null;
|
|
983
|
-
for (let j = tags.length - 1; j >= 0; j--) {
|
|
984
|
-
const tag = tags[j];
|
|
985
|
-
if (tag.pos >= endTextPos || currentTag !== null) {
|
|
986
|
-
if (currentTag !== null && currentTag.name === tag.name) {
|
|
987
|
-
currentTag = null;
|
|
988
|
-
}
|
|
989
|
-
continue;
|
|
990
|
-
}
|
|
991
|
-
if (tag.openTag) {
|
|
992
|
-
output += `</${tag.name}>`;
|
|
993
|
-
}
|
|
994
|
-
else {
|
|
995
|
-
currentTag = tag;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
return output;
|
|
999
|
-
}
|
|
1000
|
-
/**
|
|
1001
|
-
* Register math functions
|
|
1002
|
-
* Equivalent to Go's registerMath()
|
|
1003
|
-
*/
|
|
1004
|
-
registerMathFunctions(funcMap) {
|
|
1005
|
-
// Basic arithmetic functions
|
|
1006
|
-
funcMap.set('add', (a, b) => a + b);
|
|
1007
|
-
funcMap.set('sub', (a, b) => a - b);
|
|
1008
|
-
funcMap.set('mul', (a, b) => a * b);
|
|
1009
|
-
funcMap.set('div', (a, b) => b !== 0 ? a / b : 0);
|
|
1010
|
-
funcMap.set('mod', (a, b) => b !== 0 ? a % b : 0);
|
|
1011
|
-
// Math namespace functions - following Go's math package
|
|
1012
|
-
funcMap.set('math', () => ({
|
|
1013
|
-
// Abs returns the absolute value of n
|
|
1014
|
-
Abs: (n) => {
|
|
1015
|
-
const num = Number(n);
|
|
1016
|
-
if (isNaN(num)) {
|
|
1017
|
-
throw new Error('the math.Abs function requires a numeric argument');
|
|
1018
|
-
}
|
|
1019
|
-
return Math.abs(num);
|
|
1020
|
-
},
|
|
1021
|
-
// Add adds the multivalued addends
|
|
1022
|
-
Add: (...inputs) => {
|
|
1023
|
-
if (inputs.length < 2) {
|
|
1024
|
-
throw new Error('must provide at least two numbers');
|
|
1025
|
-
}
|
|
1026
|
-
return inputs.reduce((sum, val) => {
|
|
1027
|
-
const num = Number(val);
|
|
1028
|
-
if (isNaN(num)) {
|
|
1029
|
-
throw new Error('Add operator can\'t be used with non-numeric values');
|
|
1030
|
-
}
|
|
1031
|
-
return sum + num;
|
|
1032
|
-
}, 0);
|
|
1033
|
-
},
|
|
1034
|
-
// Ceil returns the least integer value greater than or equal to n
|
|
1035
|
-
Ceil: (n) => {
|
|
1036
|
-
const num = Number(n);
|
|
1037
|
-
if (isNaN(num)) {
|
|
1038
|
-
throw new Error('Ceil operator can\'t be used with non-numeric value');
|
|
1039
|
-
}
|
|
1040
|
-
return Math.ceil(num);
|
|
1041
|
-
},
|
|
1042
|
-
// Div divides n1 by n2
|
|
1043
|
-
Div: (...inputs) => {
|
|
1044
|
-
if (inputs.length < 2) {
|
|
1045
|
-
throw new Error('must provide at least two numbers');
|
|
1046
|
-
}
|
|
1047
|
-
const result = inputs.reduce((quotient, val, index) => {
|
|
1048
|
-
const num = Number(val);
|
|
1049
|
-
if (isNaN(num)) {
|
|
1050
|
-
throw new Error('Div operator can\'t be used with non-numeric values');
|
|
1051
|
-
}
|
|
1052
|
-
if (index === 0)
|
|
1053
|
-
return num;
|
|
1054
|
-
if (num === 0) {
|
|
1055
|
-
throw new Error('division by zero');
|
|
1056
|
-
}
|
|
1057
|
-
return quotient / num;
|
|
1058
|
-
});
|
|
1059
|
-
return result;
|
|
1060
|
-
},
|
|
1061
|
-
// Floor returns the greatest integer value less than or equal to n
|
|
1062
|
-
Floor: (n) => {
|
|
1063
|
-
const num = Number(n);
|
|
1064
|
-
if (isNaN(num)) {
|
|
1065
|
-
throw new Error('Floor operator can\'t be used with non-numeric value');
|
|
1066
|
-
}
|
|
1067
|
-
return Math.floor(num);
|
|
1068
|
-
},
|
|
1069
|
-
// Log returns the natural logarithm of n
|
|
1070
|
-
Log: (n) => {
|
|
1071
|
-
const num = Number(n);
|
|
1072
|
-
if (isNaN(num)) {
|
|
1073
|
-
throw new Error('Log operator can\'t be used with non-numeric value');
|
|
1074
|
-
}
|
|
1075
|
-
return Math.log(num);
|
|
1076
|
-
},
|
|
1077
|
-
// Max returns the greater of all numbers in inputs
|
|
1078
|
-
Max: (...inputs) => {
|
|
1079
|
-
if (inputs.length === 0) {
|
|
1080
|
-
throw new Error('must provide at least one number');
|
|
1081
|
-
}
|
|
1082
|
-
const numbers = inputs.flat().map(val => {
|
|
1083
|
-
const num = Number(val);
|
|
1084
|
-
if (isNaN(num)) {
|
|
1085
|
-
throw new Error('Max operator can\'t be used with non-numeric values');
|
|
1086
|
-
}
|
|
1087
|
-
return num;
|
|
1088
|
-
});
|
|
1089
|
-
return Math.max(...numbers);
|
|
1090
|
-
},
|
|
1091
|
-
// Min returns the smaller of all numbers in inputs
|
|
1092
|
-
Min: (...inputs) => {
|
|
1093
|
-
if (inputs.length === 0) {
|
|
1094
|
-
throw new Error('must provide at least one number');
|
|
1095
|
-
}
|
|
1096
|
-
const numbers = inputs.flat().map(val => {
|
|
1097
|
-
const num = Number(val);
|
|
1098
|
-
if (isNaN(num)) {
|
|
1099
|
-
throw new Error('Min operator can\'t be used with non-numeric values');
|
|
1100
|
-
}
|
|
1101
|
-
return num;
|
|
1102
|
-
});
|
|
1103
|
-
return Math.min(...numbers);
|
|
1104
|
-
},
|
|
1105
|
-
// Mod returns n1 % n2
|
|
1106
|
-
Mod: (n1, n2) => {
|
|
1107
|
-
const a = Number(n1);
|
|
1108
|
-
const b = Number(n2);
|
|
1109
|
-
if (isNaN(a) || isNaN(b)) {
|
|
1110
|
-
throw new Error('modulo operator can\'t be used with non-numeric value');
|
|
1111
|
-
}
|
|
1112
|
-
if (b === 0) {
|
|
1113
|
-
throw new Error('the number can\'t be divided by zero at modulo operation');
|
|
1114
|
-
}
|
|
1115
|
-
return a % b;
|
|
1116
|
-
},
|
|
1117
|
-
// ModBool returns the boolean of n1 % n2. If n1 % n2 == 0, return true
|
|
1118
|
-
ModBool: (n1, n2) => {
|
|
1119
|
-
const a = Number(n1);
|
|
1120
|
-
const b = Number(n2);
|
|
1121
|
-
if (isNaN(a) || isNaN(b)) {
|
|
1122
|
-
throw new Error('modulo operator can\'t be used with non-numeric value');
|
|
1123
|
-
}
|
|
1124
|
-
if (b === 0) {
|
|
1125
|
-
throw new Error('the number can\'t be divided by zero at modulo operation');
|
|
1126
|
-
}
|
|
1127
|
-
return (a % b) === 0;
|
|
1128
|
-
},
|
|
1129
|
-
// Mul multiplies the multivalued numbers
|
|
1130
|
-
Mul: (...inputs) => {
|
|
1131
|
-
if (inputs.length < 2) {
|
|
1132
|
-
throw new Error('must provide at least two numbers');
|
|
1133
|
-
}
|
|
1134
|
-
return inputs.reduce((product, val) => {
|
|
1135
|
-
const num = Number(val);
|
|
1136
|
-
if (isNaN(num)) {
|
|
1137
|
-
throw new Error('Mul operator can\'t be used with non-numeric values');
|
|
1138
|
-
}
|
|
1139
|
-
return product * num;
|
|
1140
|
-
}, 1);
|
|
1141
|
-
},
|
|
1142
|
-
// Pow returns n1 raised to the power of n2
|
|
1143
|
-
Pow: (n1, n2) => {
|
|
1144
|
-
const a = Number(n1);
|
|
1145
|
-
const b = Number(n2);
|
|
1146
|
-
if (isNaN(a) || isNaN(b)) {
|
|
1147
|
-
throw new Error('Pow operator can\'t be used with non-numeric value');
|
|
1148
|
-
}
|
|
1149
|
-
return Math.pow(a, b);
|
|
1150
|
-
},
|
|
1151
|
-
// Rand returns a pseudo-random number in [0.0,1.0)
|
|
1152
|
-
Rand: () => Math.random(),
|
|
1153
|
-
// Round returns the integer nearest to n
|
|
1154
|
-
Round: (n) => {
|
|
1155
|
-
const num = Number(n);
|
|
1156
|
-
if (isNaN(num)) {
|
|
1157
|
-
throw new Error('Round operator can\'t be used with non-numeric value');
|
|
1158
|
-
}
|
|
1159
|
-
return Math.round(num);
|
|
1160
|
-
},
|
|
1161
|
-
// Sqrt returns the square root of n
|
|
1162
|
-
Sqrt: (n) => {
|
|
1163
|
-
const num = Number(n);
|
|
1164
|
-
if (isNaN(num)) {
|
|
1165
|
-
throw new Error('Sqrt operator can\'t be used with non-numeric value');
|
|
1166
|
-
}
|
|
1167
|
-
return Math.sqrt(num);
|
|
1168
|
-
},
|
|
1169
|
-
// Sub subtracts multivalued numbers
|
|
1170
|
-
Sub: (...inputs) => {
|
|
1171
|
-
if (inputs.length < 2) {
|
|
1172
|
-
throw new Error('must provide at least two numbers');
|
|
1173
|
-
}
|
|
1174
|
-
return inputs.reduce((difference, val, index) => {
|
|
1175
|
-
const num = Number(val);
|
|
1176
|
-
if (isNaN(num)) {
|
|
1177
|
-
throw new Error('Sub operator can\'t be used with non-numeric values');
|
|
1178
|
-
}
|
|
1179
|
-
if (index === 0)
|
|
1180
|
-
return num;
|
|
1181
|
-
return difference - num;
|
|
1182
|
-
});
|
|
1183
|
-
},
|
|
1184
|
-
// Sum returns the sum of all numbers in inputs
|
|
1185
|
-
Sum: (...inputs) => {
|
|
1186
|
-
if (inputs.length === 0) {
|
|
1187
|
-
throw new Error('must provide at least one number');
|
|
1188
|
-
}
|
|
1189
|
-
const numbers = inputs.flat().map(val => {
|
|
1190
|
-
const num = Number(val);
|
|
1191
|
-
if (isNaN(num)) {
|
|
1192
|
-
throw new Error('Sum operator can\'t be used with non-numeric values');
|
|
1193
|
-
}
|
|
1194
|
-
return num;
|
|
1195
|
-
});
|
|
1196
|
-
return numbers.reduce((sum, num) => sum + num, 0);
|
|
1197
|
-
},
|
|
1198
|
-
// Product returns the product of all numbers in inputs
|
|
1199
|
-
Product: (...inputs) => {
|
|
1200
|
-
if (inputs.length === 0) {
|
|
1201
|
-
throw new Error('must provide at least one number');
|
|
1202
|
-
}
|
|
1203
|
-
const numbers = inputs.flat().map(val => {
|
|
1204
|
-
const num = Number(val);
|
|
1205
|
-
if (isNaN(num)) {
|
|
1206
|
-
throw new Error('Product operator can\'t be used with non-numeric values');
|
|
1207
|
-
}
|
|
1208
|
-
return num;
|
|
1209
|
-
});
|
|
1210
|
-
return numbers.reduce((product, num) => product * num, 1);
|
|
1211
|
-
}
|
|
1212
|
-
}));
|
|
1213
|
-
}
|
|
1214
|
-
/**
|
|
1215
|
-
* Register time/date functions
|
|
1216
|
-
* Equivalent to Go's registerTime()
|
|
1217
|
-
*/
|
|
1218
|
-
registerTimeFunctions(funcMap) {
|
|
1219
|
-
// Time namespace functions - following Go's time package
|
|
1220
|
-
funcMap.set('time', () => ({
|
|
1221
|
-
// AsTime converts a value to a time.Time
|
|
1222
|
-
AsTime: (v) => {
|
|
1223
|
-
if (!v)
|
|
1224
|
-
return null;
|
|
1225
|
-
// If it's already a Date object
|
|
1226
|
-
if (v instanceof Date)
|
|
1227
|
-
return v;
|
|
1228
|
-
// If it's a string, try to parse it
|
|
1229
|
-
if (typeof v === 'string') {
|
|
1230
|
-
const date = new Date(v);
|
|
1231
|
-
return isNaN(date.getTime()) ? null : date;
|
|
1232
|
-
}
|
|
1233
|
-
// If it's a number (unix timestamp)
|
|
1234
|
-
if (typeof v === 'number') {
|
|
1235
|
-
// Check if it's in seconds (Unix timestamp) or milliseconds
|
|
1236
|
-
const date = new Date(v < 1e10 ? v * 1000 : v);
|
|
1237
|
-
return isNaN(date.getTime()) ? null : date;
|
|
1238
|
-
}
|
|
1239
|
-
return null;
|
|
1240
|
-
},
|
|
1241
|
-
// Format formats a time.Time
|
|
1242
|
-
Format: (layout, value) => {
|
|
1243
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
1244
|
-
if (isNaN(date.getTime())) {
|
|
1245
|
-
return '';
|
|
1246
|
-
}
|
|
1247
|
-
// Go time format parsing - based on reference time: Mon Jan 2 15:04:05 MST 2006
|
|
1248
|
-
const year = date.getFullYear();
|
|
1249
|
-
const month = date.getMonth() + 1; // JavaScript months are 0-based
|
|
1250
|
-
const day = date.getDate();
|
|
1251
|
-
const hour = date.getHours();
|
|
1252
|
-
const minute = date.getMinutes();
|
|
1253
|
-
const second = date.getSeconds();
|
|
1254
|
-
const weekday = date.toLocaleString('en-US', { weekday: 'short' });
|
|
1255
|
-
const monthName = date.toLocaleString('en-US', { month: 'short' });
|
|
1256
|
-
// Go format patterns with unique placeholders to avoid conflicts
|
|
1257
|
-
const patterns = [
|
|
1258
|
-
{ pattern: '2006', placeholder: '{{YEAR_FULL}}', value: year.toString() },
|
|
1259
|
-
{ pattern: 'January', placeholder: '{{MONTH_FULL}}', value: date.toLocaleString('en-US', { month: 'long' }) },
|
|
1260
|
-
{ pattern: 'Monday', placeholder: '{{WEEKDAY_FULL}}', value: date.toLocaleString('en-US', { weekday: 'long' }) },
|
|
1261
|
-
{ pattern: 'MST', placeholder: '{{TIMEZONE}}', value: date.toLocaleString('en-US', { timeZoneName: 'short' }) },
|
|
1262
|
-
{ pattern: 'Jan', placeholder: '{{MONTH_SHORT}}', value: monthName },
|
|
1263
|
-
{ pattern: 'Mon', placeholder: '{{WEEKDAY_SHORT}}', value: weekday },
|
|
1264
|
-
{ pattern: '06', placeholder: '{{YEAR_SHORT}}', value: year.toString().slice(-2) },
|
|
1265
|
-
{ pattern: '15', placeholder: '{{HOUR_24}}', value: hour.toString().padStart(2, '0') },
|
|
1266
|
-
{ pattern: '01', placeholder: '{{MONTH_ZERO}}', value: month.toString().padStart(2, '0') },
|
|
1267
|
-
{ pattern: '02', placeholder: '{{DAY_ZERO}}', value: day.toString().padStart(2, '0') },
|
|
1268
|
-
{ pattern: '04', placeholder: '{{MINUTE_ZERO}}', value: minute.toString().padStart(2, '0') },
|
|
1269
|
-
{ pattern: '05', placeholder: '{{SECOND_ZERO}}', value: second.toString().padStart(2, '0') },
|
|
1270
|
-
{ pattern: 'PM', placeholder: '{{AMPM_UPPER}}', value: hour >= 12 ? 'PM' : 'AM' },
|
|
1271
|
-
{ pattern: 'pm', placeholder: '{{AMPM_LOWER}}', value: hour >= 12 ? 'pm' : 'am' },
|
|
1272
|
-
{ pattern: '3', placeholder: '{{HOUR_12}}', value: ((hour + 11) % 12 + 1).toString() },
|
|
1273
|
-
{ pattern: '1', placeholder: '{{MONTH_NUM}}', value: month.toString() },
|
|
1274
|
-
{ pattern: '2', placeholder: '{{DAY_NUM}}', value: day.toString() },
|
|
1275
|
-
{ pattern: '4', placeholder: '{{MINUTE_NUM}}', value: minute.toString() },
|
|
1276
|
-
{ pattern: '5', placeholder: '{{SECOND_NUM}}', value: second.toString() },
|
|
1277
|
-
];
|
|
1278
|
-
let result = layout;
|
|
1279
|
-
// Step 1: Replace patterns with unique placeholders
|
|
1280
|
-
for (const { pattern, placeholder } of patterns) {
|
|
1281
|
-
const escapedPattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1282
|
-
result = result.replace(new RegExp(escapedPattern, 'g'), placeholder);
|
|
1283
|
-
}
|
|
1284
|
-
// Step 2: Replace placeholders with actual values
|
|
1285
|
-
for (const { placeholder, value } of patterns) {
|
|
1286
|
-
result = result.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), value);
|
|
1287
|
-
}
|
|
1288
|
-
return result;
|
|
1289
|
-
},
|
|
1290
|
-
// Now returns the current time
|
|
1291
|
-
Now: () => new Date(),
|
|
1292
|
-
// Parse parses a formatted string and returns the time value it represents
|
|
1293
|
-
Parse: (layout, value) => {
|
|
1294
|
-
try {
|
|
1295
|
-
const date = new Date(value);
|
|
1296
|
-
return isNaN(date.getTime()) ? null : date;
|
|
1297
|
-
}
|
|
1298
|
-
catch {
|
|
1299
|
-
return null;
|
|
1300
|
-
}
|
|
1301
|
-
},
|
|
1302
|
-
// Unix returns the Unix time in seconds
|
|
1303
|
-
Unix: (value) => {
|
|
1304
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
1305
|
-
return Math.floor(date.getTime() / 1000);
|
|
1306
|
-
},
|
|
1307
|
-
// UnixNano returns the Unix time in nanoseconds
|
|
1308
|
-
UnixNano: (value) => {
|
|
1309
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
1310
|
-
return date.getTime() * 1e6; // Convert milliseconds to nanoseconds
|
|
1311
|
-
}
|
|
1312
|
-
}));
|
|
1313
|
-
// Now function that returns an object with Format method (Go-style)
|
|
1314
|
-
funcMap.set('now', () => {
|
|
1315
|
-
const date = new Date();
|
|
1316
|
-
return {
|
|
1317
|
-
Format: (layout) => {
|
|
1318
|
-
// Go time format parsing - based on reference time: Mon Jan 2 15:04:05 MST 2006
|
|
1319
|
-
// This represents Unix time 1136239445
|
|
1320
|
-
const year = date.getFullYear();
|
|
1321
|
-
const month = date.getMonth() + 1; // JavaScript months are 0-based
|
|
1322
|
-
const day = date.getDate();
|
|
1323
|
-
const hour = date.getHours();
|
|
1324
|
-
const minute = date.getMinutes();
|
|
1325
|
-
const second = date.getSeconds();
|
|
1326
|
-
// Go format patterns in order of precedence (longer patterns first to avoid conflicts)
|
|
1327
|
-
const patterns = [
|
|
1328
|
-
// Year patterns
|
|
1329
|
-
{ pattern: '2006', value: year.toString() }, // 4-digit year
|
|
1330
|
-
{ pattern: '06', value: year.toString().slice(-2) }, // 2-digit year
|
|
1331
|
-
// Month patterns
|
|
1332
|
-
{ pattern: '01', value: month.toString().padStart(2, '0') }, // 2-digit month
|
|
1333
|
-
{ pattern: '1', value: month.toString() }, // 1-digit month
|
|
1334
|
-
// Day patterns
|
|
1335
|
-
{ pattern: '02', value: day.toString().padStart(2, '0') }, // 2-digit day
|
|
1336
|
-
{ pattern: '2', value: day.toString() }, // 1-digit day
|
|
1337
|
-
// Hour patterns (24-hour)
|
|
1338
|
-
{ pattern: '15', value: hour.toString().padStart(2, '0') }, // 2-digit hour (24h)
|
|
1339
|
-
// Hour patterns (12-hour)
|
|
1340
|
-
{ pattern: '3', value: ((hour % 12) || 12).toString() }, // 1-digit hour (12h)
|
|
1341
|
-
// Minute patterns
|
|
1342
|
-
{ pattern: '04', value: minute.toString().padStart(2, '0') }, // 2-digit minute
|
|
1343
|
-
{ pattern: '4', value: minute.toString() }, // 1-digit minute
|
|
1344
|
-
// Second patterns
|
|
1345
|
-
{ pattern: '05', value: second.toString().padStart(2, '0') }, // 2-digit second
|
|
1346
|
-
{ pattern: '5', value: second.toString() }, // 1-digit second
|
|
1347
|
-
];
|
|
1348
|
-
let result = layout;
|
|
1349
|
-
// Apply patterns in order, using word boundaries to avoid partial matches
|
|
1350
|
-
for (const { pattern, value } of patterns) {
|
|
1351
|
-
// Use a more precise regex that considers word boundaries and context
|
|
1352
|
-
const regex = new RegExp(`\\b${pattern}\\b`, 'g');
|
|
1353
|
-
result = result.replace(regex, value);
|
|
1354
|
-
}
|
|
1355
|
-
// Handle some special cases that might not have word boundaries
|
|
1356
|
-
// For patterns that might be standalone or part of other formatting
|
|
1357
|
-
if (layout === '2006') {
|
|
1358
|
-
return year.toString(); // Pure year format
|
|
1359
|
-
}
|
|
1360
|
-
if (layout === '06') {
|
|
1361
|
-
return year.toString().slice(-2); // Pure 2-digit year format
|
|
1362
|
-
}
|
|
1363
|
-
if (layout === '01') {
|
|
1364
|
-
return month.toString().padStart(2, '0'); // Pure month format
|
|
1365
|
-
}
|
|
1366
|
-
if (layout === '02') {
|
|
1367
|
-
return day.toString().padStart(2, '0'); // Pure day format
|
|
1368
|
-
}
|
|
1369
|
-
if (layout === '15') {
|
|
1370
|
-
return hour.toString().padStart(2, '0'); // Pure hour format
|
|
1371
|
-
}
|
|
1372
|
-
if (layout === '04') {
|
|
1373
|
-
return minute.toString().padStart(2, '0'); // Pure minute format
|
|
1374
|
-
}
|
|
1375
|
-
if (layout === '05') {
|
|
1376
|
-
return second.toString().padStart(2, '0'); // Pure second format
|
|
1377
|
-
}
|
|
1378
|
-
return result;
|
|
1379
|
-
},
|
|
1380
|
-
// Also provide direct access to the Date object
|
|
1381
|
-
getTime: () => date.getTime(),
|
|
1382
|
-
toString: () => date.toString(),
|
|
1383
|
-
toISOString: () => date.toISOString()
|
|
1384
|
-
};
|
|
1385
|
-
});
|
|
1386
|
-
funcMap.set('dateFormat', (format, date) => {
|
|
1387
|
-
// Simple date formatting - can be enhanced with proper library
|
|
1388
|
-
return date.toLocaleDateString();
|
|
1389
|
-
});
|
|
1390
|
-
}
|
|
1391
|
-
/**
|
|
1392
|
-
* Register collection functions
|
|
1393
|
-
* Equivalent to Go's registerCollections()
|
|
1394
|
-
*/
|
|
1395
|
-
registerCollectionFunctions(funcMap) {
|
|
1396
|
-
funcMap.set('len', (obj) => {
|
|
1397
|
-
if (Array.isArray(obj))
|
|
1398
|
-
return obj.length;
|
|
1399
|
-
if (typeof obj === 'string')
|
|
1400
|
-
return obj.length;
|
|
1401
|
-
if (obj && typeof obj === 'object')
|
|
1402
|
-
return Object.keys(obj).length;
|
|
1403
|
-
return 0;
|
|
1404
|
-
});
|
|
1405
|
-
funcMap.set('first', (n, arr) => {
|
|
1406
|
-
// Handle both cases: first(n, arr) and first(arr)
|
|
1407
|
-
if (Array.isArray(n)) {
|
|
1408
|
-
// Called as first(arr) - return first element
|
|
1409
|
-
return n.slice(0, 1);
|
|
1410
|
-
}
|
|
1411
|
-
else if (Array.isArray(arr)) {
|
|
1412
|
-
// Called as first(n, arr) - return first n elements
|
|
1413
|
-
return arr.slice(0, n);
|
|
1414
|
-
}
|
|
1415
|
-
return [];
|
|
1416
|
-
});
|
|
1417
|
-
funcMap.set('last', (n, arr) => {
|
|
1418
|
-
// Handle both cases: last(n, arr) and last(arr)
|
|
1419
|
-
if (Array.isArray(n)) {
|
|
1420
|
-
// Called as last(arr) - return last element
|
|
1421
|
-
return n.slice(-1);
|
|
1422
|
-
}
|
|
1423
|
-
else if (Array.isArray(arr)) {
|
|
1424
|
-
// Called as last(n, arr) - return last n elements
|
|
1425
|
-
return arr.slice(-n);
|
|
1426
|
-
}
|
|
1427
|
-
return [];
|
|
1428
|
-
});
|
|
1429
|
-
// Merge function for combining objects/maps
|
|
1430
|
-
funcMap.set('merge', (...args) => {
|
|
1431
|
-
const result = {};
|
|
1432
|
-
for (const arg of args) {
|
|
1433
|
-
if (arg && typeof arg === 'object' && !Array.isArray(arg)) {
|
|
1434
|
-
Object.assign(result, arg);
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
return result;
|
|
1438
|
-
});
|
|
1439
|
-
// Index function to get item at index - supports nested indexing like Go's implementation
|
|
1440
|
-
// Usage: {{ index array 0 }} or {{ index object "key" }} or {{ index nested "key1" "key2" 0 }}
|
|
1441
|
-
funcMap.set('index', (item, ...indices) => {
|
|
1442
|
-
try {
|
|
1443
|
-
return this.doIndex(item, indices);
|
|
1444
|
-
}
|
|
1445
|
-
catch (error) {
|
|
1446
|
-
log.error(`Index of type ${typeof item} with args [${indices.join(', ')}] failed:`, error);
|
|
1447
|
-
return null;
|
|
1448
|
-
}
|
|
1449
|
-
});
|
|
1450
|
-
// Reverse function
|
|
1451
|
-
funcMap.set('reverse', (arr) => {
|
|
1452
|
-
if (Array.isArray(arr)) {
|
|
1453
|
-
return [...arr].reverse();
|
|
1454
|
-
}
|
|
1455
|
-
return arr;
|
|
1456
|
-
});
|
|
1457
|
-
// Append function
|
|
1458
|
-
funcMap.set('append', (...args) => {
|
|
1459
|
-
if (args.length < 2) {
|
|
1460
|
-
return args[0] || [];
|
|
1461
|
-
}
|
|
1462
|
-
const result = Array.isArray(args[0]) ? [...args[0]] : [args[0]];
|
|
1463
|
-
// For each remaining argument, spread it if it's an array, otherwise add as single element
|
|
1464
|
-
for (let i = 1; i < args.length; i++) {
|
|
1465
|
-
if (Array.isArray(args[i])) {
|
|
1466
|
-
result.push(...args[i]);
|
|
1467
|
-
}
|
|
1468
|
-
else {
|
|
1469
|
-
result.push(args[i]);
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
return result;
|
|
1473
|
-
});
|
|
1474
|
-
// Prepend function
|
|
1475
|
-
funcMap.set('prepend', (arr, ...items) => {
|
|
1476
|
-
if (Array.isArray(arr)) {
|
|
1477
|
-
return [...items, ...arr];
|
|
1478
|
-
}
|
|
1479
|
-
return [...items, arr];
|
|
1480
|
-
});
|
|
1481
|
-
// Seq creates a sequence of integers from args. It's named and used as GNU's seq.
|
|
1482
|
-
// Examples:
|
|
1483
|
-
// 3 => 1, 2, 3
|
|
1484
|
-
// 1 2 4 => 1, 3
|
|
1485
|
-
// -3 => -1, -2, -3
|
|
1486
|
-
// 1 4 => 1, 2, 3, 4
|
|
1487
|
-
// 1 -2 => 1, 0, -1, -2
|
|
1488
|
-
funcMap.set('seq', (...args) => {
|
|
1489
|
-
if (args.length < 1 || args.length > 3) {
|
|
1490
|
-
throw new Error('invalid number of arguments to Seq');
|
|
1491
|
-
}
|
|
1492
|
-
// Convert all arguments to integers
|
|
1493
|
-
const intArgs = args.map(arg => {
|
|
1494
|
-
const num = Number(arg);
|
|
1495
|
-
if (isNaN(num)) {
|
|
1496
|
-
throw new Error('invalid arguments to Seq');
|
|
1497
|
-
}
|
|
1498
|
-
return Math.floor(num);
|
|
1499
|
-
});
|
|
1500
|
-
let inc = 1;
|
|
1501
|
-
let last;
|
|
1502
|
-
let first = intArgs[0];
|
|
1503
|
-
if (intArgs.length === 1) {
|
|
1504
|
-
last = first;
|
|
1505
|
-
if (last === 0) {
|
|
1506
|
-
return [];
|
|
1507
|
-
}
|
|
1508
|
-
else if (last > 0) {
|
|
1509
|
-
first = 1;
|
|
1510
|
-
}
|
|
1511
|
-
else {
|
|
1512
|
-
first = -1;
|
|
1513
|
-
inc = -1;
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
else if (intArgs.length === 2) {
|
|
1517
|
-
last = intArgs[1];
|
|
1518
|
-
if (last < first) {
|
|
1519
|
-
inc = -1;
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
else {
|
|
1523
|
-
inc = intArgs[1];
|
|
1524
|
-
last = intArgs[2];
|
|
1525
|
-
if (inc === 0) {
|
|
1526
|
-
throw new Error("'increment' must not be 0");
|
|
1527
|
-
}
|
|
1528
|
-
if (first < last && inc < 0) {
|
|
1529
|
-
throw new Error("'increment' must be > 0");
|
|
1530
|
-
}
|
|
1531
|
-
if (first > last && inc > 0) {
|
|
1532
|
-
throw new Error("'increment' must be < 0");
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
// Sanity check
|
|
1536
|
-
if (last < -100000) {
|
|
1537
|
-
throw new Error('size of result exceeds limit');
|
|
1538
|
-
}
|
|
1539
|
-
const size = Math.floor((last - first) / inc) + 1;
|
|
1540
|
-
// Sanity check
|
|
1541
|
-
if (size <= 0 || size > 2000) {
|
|
1542
|
-
throw new Error('size of result exceeds limit');
|
|
1543
|
-
}
|
|
1544
|
-
const seq = new Array(size);
|
|
1545
|
-
let val = first;
|
|
1546
|
-
for (let i = 0; i < size; i++) {
|
|
1547
|
-
seq[i] = val;
|
|
1548
|
-
val += inc;
|
|
1549
|
-
if ((inc < 0 && val < last) || (inc > 0 && val > last)) {
|
|
1550
|
-
break;
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
return seq;
|
|
1554
|
-
});
|
|
1555
|
-
// Sort returns a sorted copy of the list l
|
|
1556
|
-
// Equivalent to Go's Sort function in collections namespace
|
|
1557
|
-
// Usage: sort list [sortByField] [direction]
|
|
1558
|
-
// Examples:
|
|
1559
|
-
// {{ sort .Pages }} - sort by default comparison
|
|
1560
|
-
// {{ sort .Pages "Title" }} - sort by Title field ascending
|
|
1561
|
-
// {{ sort .Pages "Date" "desc" }} - sort by Date field descending
|
|
1562
|
-
funcMap.set('sort', (list, ...args) => {
|
|
1563
|
-
if (list === null || list === undefined) {
|
|
1564
|
-
throw new Error('sequence must be provided');
|
|
1565
|
-
}
|
|
1566
|
-
let arr;
|
|
1567
|
-
// Handle different input types
|
|
1568
|
-
if (Array.isArray(list)) {
|
|
1569
|
-
arr = [...list]; // Create a copy to avoid mutating original
|
|
1570
|
-
}
|
|
1571
|
-
else if (typeof list === 'object' && list !== null) {
|
|
1572
|
-
// Handle objects/maps - convert to array of values
|
|
1573
|
-
arr = Object.values(list);
|
|
1574
|
-
}
|
|
1575
|
-
else {
|
|
1576
|
-
throw new Error(`can't sort ${typeof list}`);
|
|
1577
|
-
}
|
|
1578
|
-
if (arr.length === 0) {
|
|
1579
|
-
return arr;
|
|
1580
|
-
}
|
|
1581
|
-
// Parse arguments
|
|
1582
|
-
let sortByField = '';
|
|
1583
|
-
let sortAsc = true;
|
|
1584
|
-
for (let i = 0; i < args.length; i++) {
|
|
1585
|
-
const arg = args[i];
|
|
1586
|
-
if (i === 0) {
|
|
1587
|
-
// First argument is the field to sort by
|
|
1588
|
-
if (typeof arg === 'string') {
|
|
1589
|
-
sortByField = arg;
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
else if (i === 1) {
|
|
1593
|
-
// Second argument is the sort direction
|
|
1594
|
-
if (typeof arg === 'string' && arg.toLowerCase() === 'desc') {
|
|
1595
|
-
sortAsc = false;
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
// Helper function to get nested property value
|
|
1600
|
-
const getNestedValue = (obj, path) => {
|
|
1601
|
-
if (!path || path === 'value') {
|
|
1602
|
-
return obj;
|
|
1603
|
-
}
|
|
1604
|
-
const keys = path.split('.');
|
|
1605
|
-
let current = obj;
|
|
1606
|
-
for (const key of keys) {
|
|
1607
|
-
if (current === null || current === undefined) {
|
|
1608
|
-
return undefined;
|
|
1609
|
-
}
|
|
1610
|
-
// Handle both object properties and method calls
|
|
1611
|
-
if (typeof current === 'object') {
|
|
1612
|
-
current = current[key];
|
|
1613
|
-
}
|
|
1614
|
-
else {
|
|
1615
|
-
return undefined;
|
|
1616
|
-
}
|
|
1617
|
-
}
|
|
1618
|
-
return current;
|
|
1619
|
-
};
|
|
1620
|
-
// Comparison function
|
|
1621
|
-
const compare = (a, b) => {
|
|
1622
|
-
let aVal = sortByField ? getNestedValue(a, sortByField) : a;
|
|
1623
|
-
let bVal = sortByField ? getNestedValue(b, sortByField) : b;
|
|
1624
|
-
// Handle undefined/null values
|
|
1625
|
-
if (aVal === undefined || aVal === null) {
|
|
1626
|
-
if (bVal === undefined || bVal === null) {
|
|
1627
|
-
return 0;
|
|
1628
|
-
}
|
|
1629
|
-
return sortAsc ? -1 : 1;
|
|
1630
|
-
}
|
|
1631
|
-
if (bVal === undefined || bVal === null) {
|
|
1632
|
-
return sortAsc ? 1 : -1;
|
|
1633
|
-
}
|
|
1634
|
-
// Convert to comparable values
|
|
1635
|
-
if (typeof aVal === 'string' && typeof bVal === 'string') {
|
|
1636
|
-
const result = aVal.localeCompare(bVal);
|
|
1637
|
-
return sortAsc ? result : -result;
|
|
1638
|
-
}
|
|
1639
|
-
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
|
1640
|
-
const result = aVal - bVal;
|
|
1641
|
-
return sortAsc ? result : -result;
|
|
1642
|
-
}
|
|
1643
|
-
// For mixed types, convert to strings and compare
|
|
1644
|
-
const aStr = String(aVal);
|
|
1645
|
-
const bStr = String(bVal);
|
|
1646
|
-
const result = aStr.localeCompare(bStr);
|
|
1647
|
-
return sortAsc ? result : -result;
|
|
1648
|
-
};
|
|
1649
|
-
// Sort the array
|
|
1650
|
-
return arr.sort(compare);
|
|
1651
|
-
});
|
|
1652
|
-
// where function - filters a collection based on conditions
|
|
1653
|
-
// Usage: {{ where .Pages "Section" "blog" }}
|
|
1654
|
-
// Usage: {{ where .Pages "Params.tags" "intersect" (slice "hugo" "go") }}
|
|
1655
|
-
funcMap.set('where', (() => {
|
|
1656
|
-
return (collection, key, ...args) => {
|
|
1657
|
-
if (!collection) {
|
|
1658
|
-
return [];
|
|
1659
|
-
}
|
|
1660
|
-
// Parse arguments to get value and operator
|
|
1661
|
-
let matchValue;
|
|
1662
|
-
let operator = '=='; // default operator
|
|
1663
|
-
if (args.length === 1) {
|
|
1664
|
-
matchValue = args[0];
|
|
1665
|
-
}
|
|
1666
|
-
else if (args.length === 2) {
|
|
1667
|
-
operator = args[0];
|
|
1668
|
-
matchValue = args[1];
|
|
1669
|
-
}
|
|
1670
|
-
else {
|
|
1671
|
-
throw new Error('where function requires 2-4 arguments');
|
|
1672
|
-
}
|
|
1673
|
-
const result = [];
|
|
1674
|
-
// Handle different collection types
|
|
1675
|
-
if (Array.isArray(collection)) {
|
|
1676
|
-
for (let i = 0; i < collection.length; i++) {
|
|
1677
|
-
const item = collection[i];
|
|
1678
|
-
const itemValue = this.getNestedValue(item, key);
|
|
1679
|
-
if (this.checkCondition(itemValue, matchValue, operator)) {
|
|
1680
|
-
result.push(item);
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
else if (typeof collection === 'object') {
|
|
1685
|
-
// Handle object/map
|
|
1686
|
-
for (const [mapKey, mapValue] of Object.entries(collection)) {
|
|
1687
|
-
if (Array.isArray(mapValue)) {
|
|
1688
|
-
const filtered = mapValue.filter(item => {
|
|
1689
|
-
const itemValue = this.getNestedValue(item, key);
|
|
1690
|
-
return this.checkCondition(itemValue, matchValue, operator);
|
|
1691
|
-
});
|
|
1692
|
-
if (filtered.length > 0) {
|
|
1693
|
-
result.push({ [mapKey]: filtered });
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
return result;
|
|
1699
|
-
};
|
|
1700
|
-
})());
|
|
1701
|
-
// intersect function - finds intersection of two arrays
|
|
1702
|
-
funcMap.set('intersect', (set1, set2) => {
|
|
1703
|
-
if (!Array.isArray(set1) || !Array.isArray(set2)) {
|
|
1704
|
-
return [];
|
|
1705
|
-
}
|
|
1706
|
-
return set1.filter(item => set2.includes(item));
|
|
1707
|
-
});
|
|
1708
|
-
// querify function - converts key-value pairs to URL query string
|
|
1709
|
-
// Usage: {{ querify "foo" 1 "bar" 2 "baz" "with spaces" }}
|
|
1710
|
-
// Returns: bar=2&baz=with+spaces&foo=1
|
|
1711
|
-
// Also supports array input: {{ slice "foo" 1 "bar" 2 | querify }}
|
|
1712
|
-
funcMap.set('querify', (...args) => {
|
|
1713
|
-
let params = [];
|
|
1714
|
-
// Handle single array argument (from pipe)
|
|
1715
|
-
if (args.length === 1 && Array.isArray(args[0])) {
|
|
1716
|
-
params = args[0];
|
|
1717
|
-
}
|
|
1718
|
-
else {
|
|
1719
|
-
params = args;
|
|
1720
|
-
}
|
|
1721
|
-
// Must have even number of parameters (key-value pairs)
|
|
1722
|
-
if (params.length % 2 !== 0) {
|
|
1723
|
-
throw new Error('querify requires an even number of arguments (key-value pairs)');
|
|
1724
|
-
}
|
|
1725
|
-
const queryParams = [];
|
|
1726
|
-
// Process key-value pairs
|
|
1727
|
-
for (let i = 0; i < params.length; i += 2) {
|
|
1728
|
-
const key = String(params[i]);
|
|
1729
|
-
const value = String(params[i + 1]);
|
|
1730
|
-
queryParams.push([key, value]);
|
|
1731
|
-
}
|
|
1732
|
-
// Sort by key for consistent output (like Go's implementation)
|
|
1733
|
-
queryParams.sort((a, b) => a[0].localeCompare(b[0]));
|
|
1734
|
-
// Build query string
|
|
1735
|
-
const queryString = queryParams
|
|
1736
|
-
.map(([key, value]) => {
|
|
1737
|
-
// URL encode key and value, replacing %20 with + for spaces (query string convention)
|
|
1738
|
-
const encodedKey = encodeURIComponent(key).replace(/%20/g, '+');
|
|
1739
|
-
const encodedValue = encodeURIComponent(value).replace(/%20/g, '+');
|
|
1740
|
-
return `${encodedKey}=${encodedValue}`;
|
|
1741
|
-
})
|
|
1742
|
-
.join('&');
|
|
1743
|
-
return queryString;
|
|
1744
|
-
});
|
|
1745
|
-
// IsSet returns whether a given array, slice, or map has the given key defined
|
|
1746
|
-
// Equivalent to Go's IsSet function in collections namespace
|
|
1747
|
-
// Usage: {{ isset .array 0 }} or {{ isset .object "key" }}
|
|
1748
|
-
funcMap.set('isset', (c, key) => {
|
|
1749
|
-
if (c === null || c === undefined) {
|
|
1750
|
-
return false;
|
|
1751
|
-
}
|
|
1752
|
-
// Handle arrays and slices
|
|
1753
|
-
if (Array.isArray(c)) {
|
|
1754
|
-
// Convert key to integer for array indexing
|
|
1755
|
-
const k = Number(key);
|
|
1756
|
-
if (isNaN(k) || !Number.isInteger(k)) {
|
|
1757
|
-
console.warn(`isset unable to use key of type ${typeof key} as index`);
|
|
1758
|
-
return false;
|
|
1759
|
-
}
|
|
1760
|
-
// Check if index is valid (within bounds)
|
|
1761
|
-
return c.length > k && k >= 0;
|
|
1762
|
-
}
|
|
1763
|
-
// Handle objects/maps
|
|
1764
|
-
if (typeof c === 'object') {
|
|
1765
|
-
// For objects, check if the key exists as a property
|
|
1766
|
-
return key in c;
|
|
1767
|
-
}
|
|
1768
|
-
// Handle strings (similar to arrays, but for character indexing)
|
|
1769
|
-
if (typeof c === 'string') {
|
|
1770
|
-
const k = Number(key);
|
|
1771
|
-
if (isNaN(k) || !Number.isInteger(k)) {
|
|
1772
|
-
console.warn(`isset unable to use key of type ${typeof key} as index`);
|
|
1773
|
-
return false;
|
|
1774
|
-
}
|
|
1775
|
-
return c.length > k && k >= 0;
|
|
1776
|
-
}
|
|
1777
|
-
// Unsupported types
|
|
1778
|
-
console.warn(`calling isset with unsupported type "${typeof c}" (${c.constructor?.name || typeof c}) will always return false.`);
|
|
1779
|
-
return false;
|
|
1780
|
-
});
|
|
1781
|
-
}
|
|
1782
|
-
/**
|
|
1783
|
-
* Core indexing implementation following Go's doIndex logic
|
|
1784
|
-
* Supports nested indexing of arrays, objects, and maps
|
|
1785
|
-
*/
|
|
1786
|
-
doIndex(item, indices) {
|
|
1787
|
-
// Handle null/undefined item
|
|
1788
|
-
if (item === null || item === undefined) {
|
|
1789
|
-
return null;
|
|
1790
|
-
}
|
|
1791
|
-
// If no indices provided, return the item itself
|
|
1792
|
-
if (indices.length === 0) {
|
|
1793
|
-
return item;
|
|
1794
|
-
}
|
|
1795
|
-
let currentValue = item;
|
|
1796
|
-
// Process each index in sequence (supports chained indexing like x[1][2][3])
|
|
1797
|
-
for (const index of indices) {
|
|
1798
|
-
// Handle null/undefined current value in chain
|
|
1799
|
-
if (currentValue === null || currentValue === undefined) {
|
|
1800
|
-
return null;
|
|
1801
|
-
}
|
|
1802
|
-
// Determine how to index based on the current value type
|
|
1803
|
-
if (Array.isArray(currentValue)) {
|
|
1804
|
-
// Handle array/slice indexing
|
|
1805
|
-
currentValue = this.indexArray(currentValue, index);
|
|
1806
|
-
}
|
|
1807
|
-
else if (typeof currentValue === 'string') {
|
|
1808
|
-
// Handle string indexing (strings are indexable like arrays)
|
|
1809
|
-
currentValue = this.indexString(currentValue, index);
|
|
1810
|
-
}
|
|
1811
|
-
else if (typeof currentValue === 'object') {
|
|
1812
|
-
// Handle object/map indexing (including TaxonomyList type)
|
|
1813
|
-
currentValue = this.indexObject(currentValue, index);
|
|
1814
|
-
}
|
|
1815
|
-
else {
|
|
1816
|
-
// Cannot index this type
|
|
1817
|
-
throw new Error(`can't index item of type ${typeof currentValue}`);
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
return currentValue;
|
|
1821
|
-
}
|
|
1822
|
-
/**
|
|
1823
|
-
* Index into an array or slice
|
|
1824
|
-
*/
|
|
1825
|
-
indexArray(arr, index) {
|
|
1826
|
-
// Convert index to integer
|
|
1827
|
-
const i = this.toInteger(index);
|
|
1828
|
-
if (i === null) {
|
|
1829
|
-
throw new Error(`cannot index slice/array with type ${typeof index}`);
|
|
1830
|
-
}
|
|
1831
|
-
// Check bounds - Go version returns null for out of bounds instead of error
|
|
1832
|
-
if (i < 0 || i >= arr.length) {
|
|
1833
|
-
return null;
|
|
1834
|
-
}
|
|
1835
|
-
return arr[i];
|
|
1836
|
-
}
|
|
1837
|
-
/**
|
|
1838
|
-
* Index into a string (treating it like a character array)
|
|
1839
|
-
*/
|
|
1840
|
-
indexString(str, index) {
|
|
1841
|
-
// Convert index to integer
|
|
1842
|
-
const i = this.toInteger(index);
|
|
1843
|
-
if (i === null) {
|
|
1844
|
-
throw new Error(`cannot index string with type ${typeof index}`);
|
|
1845
|
-
}
|
|
1846
|
-
// Check bounds
|
|
1847
|
-
if (i < 0 || i >= str.length) {
|
|
1848
|
-
return null;
|
|
1849
|
-
}
|
|
1850
|
-
return str.charAt(i);
|
|
1851
|
-
}
|
|
1852
|
-
/**
|
|
1853
|
-
* Index into an object/map (including TaxonomyList)
|
|
1854
|
-
*/
|
|
1855
|
-
indexObject(obj, key) {
|
|
1856
|
-
// Convert key to string for object property access
|
|
1857
|
-
const keyStr = String(key);
|
|
1858
|
-
// Check if property exists
|
|
1859
|
-
if (obj.hasOwnProperty(keyStr)) {
|
|
1860
|
-
return obj[keyStr];
|
|
1861
|
-
}
|
|
1862
|
-
// Try case-insensitive lookup (following Hugo's behavior)
|
|
1863
|
-
const keys = Object.keys(obj);
|
|
1864
|
-
const matchingKey = keys.find(k => k.toLowerCase() === keyStr.toLowerCase());
|
|
1865
|
-
if (matchingKey) {
|
|
1866
|
-
return obj[matchingKey];
|
|
1867
|
-
}
|
|
1868
|
-
// Map
|
|
1869
|
-
if (obj instanceof Map) {
|
|
1870
|
-
if (obj.has(keyStr)) {
|
|
1871
|
-
return obj.get(keyStr);
|
|
1872
|
-
}
|
|
1873
|
-
// case-insensitive 查找
|
|
1874
|
-
for (const k of obj.keys()) {
|
|
1875
|
-
if (String(k).toLowerCase() === keyStr.toLowerCase()) {
|
|
1876
|
-
return obj.get(k);
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
// Property not found - return undefined/null like Go's zero value
|
|
1881
|
-
return null;
|
|
1882
|
-
}
|
|
1883
|
-
/**
|
|
1884
|
-
* Convert value to integer, similar to Go's index conversion
|
|
1885
|
-
*/
|
|
1886
|
-
toInteger(value) {
|
|
1887
|
-
if (typeof value === 'number') {
|
|
1888
|
-
if (Number.isInteger(value)) {
|
|
1889
|
-
return value;
|
|
1890
|
-
}
|
|
1891
|
-
// Convert float to int (truncate)
|
|
1892
|
-
return Math.floor(value);
|
|
1893
|
-
}
|
|
1894
|
-
if (typeof value === 'string') {
|
|
1895
|
-
const parsed = parseInt(value, 10);
|
|
1896
|
-
if (!isNaN(parsed)) {
|
|
1897
|
-
return parsed;
|
|
1898
|
-
}
|
|
1899
|
-
}
|
|
1900
|
-
// Cannot convert to integer
|
|
1901
|
-
return null;
|
|
1902
|
-
}
|
|
1903
|
-
/**
|
|
1904
|
-
* Check condition between two values using the specified operator
|
|
1905
|
-
* Following golang's checkCondition logic
|
|
1906
|
-
*/
|
|
1907
|
-
checkCondition(value, matchValue, operator) {
|
|
1908
|
-
// Normalize operator
|
|
1909
|
-
const op = operator.toLowerCase().trim();
|
|
1910
|
-
// Handle null/undefined cases
|
|
1911
|
-
if (value == null && matchValue == null) {
|
|
1912
|
-
return ['==', '=', 'eq', ''].includes(op);
|
|
1913
|
-
}
|
|
1914
|
-
if (value == null || matchValue == null) {
|
|
1915
|
-
return ['!=', '<>', 'ne'].includes(op);
|
|
1916
|
-
}
|
|
1917
|
-
// Handle array membership (in operator)
|
|
1918
|
-
if (op === 'in') {
|
|
1919
|
-
if (Array.isArray(matchValue)) {
|
|
1920
|
-
return matchValue.includes(value);
|
|
1921
|
-
}
|
|
1922
|
-
if (typeof matchValue === 'string' && typeof value === 'string') {
|
|
1923
|
-
return matchValue.includes(value);
|
|
1924
|
-
}
|
|
1925
|
-
return false;
|
|
1926
|
-
}
|
|
1927
|
-
// Handle intersect operator for arrays
|
|
1928
|
-
if (op === 'intersect') {
|
|
1929
|
-
if (Array.isArray(value) && Array.isArray(matchValue)) {
|
|
1930
|
-
return value.some(item => matchValue.includes(item));
|
|
1931
|
-
}
|
|
1932
|
-
return false;
|
|
1933
|
-
}
|
|
1934
|
-
// Type conversion for comparison
|
|
1935
|
-
const [normalizedValue, normalizedMatch] = this.normalizeForComparison(value, matchValue);
|
|
1936
|
-
switch (op) {
|
|
1937
|
-
case '':
|
|
1938
|
-
case '=':
|
|
1939
|
-
case '==':
|
|
1940
|
-
case 'eq':
|
|
1941
|
-
return normalizedValue === normalizedMatch;
|
|
1942
|
-
case '!=':
|
|
1943
|
-
case '<>':
|
|
1944
|
-
case 'ne':
|
|
1945
|
-
return normalizedValue !== normalizedMatch;
|
|
1946
|
-
case '<':
|
|
1947
|
-
case 'lt':
|
|
1948
|
-
return normalizedValue < normalizedMatch;
|
|
1949
|
-
case '<=':
|
|
1950
|
-
case 'le':
|
|
1951
|
-
return normalizedValue <= normalizedMatch;
|
|
1952
|
-
case '>':
|
|
1953
|
-
case 'gt':
|
|
1954
|
-
return normalizedValue > normalizedMatch;
|
|
1955
|
-
case '>=':
|
|
1956
|
-
case 'ge':
|
|
1957
|
-
return normalizedValue >= normalizedMatch;
|
|
1958
|
-
default:
|
|
1959
|
-
return false;
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
/**
|
|
1963
|
-
* Normalize values for comparison
|
|
1964
|
-
*/
|
|
1965
|
-
normalizeForComparison(value, matchValue) {
|
|
1966
|
-
// If both are numbers, compare as numbers
|
|
1967
|
-
if (typeof value === 'number' && typeof matchValue === 'number') {
|
|
1968
|
-
return [value, matchValue];
|
|
1969
|
-
}
|
|
1970
|
-
// If one is number and other is string number, convert both to numbers
|
|
1971
|
-
if (typeof value === 'number' && typeof matchValue === 'string') {
|
|
1972
|
-
const num = parseFloat(matchValue);
|
|
1973
|
-
if (!isNaN(num)) {
|
|
1974
|
-
return [value, num];
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
|
-
if (typeof value === 'string' && typeof matchValue === 'number') {
|
|
1978
|
-
const num = parseFloat(value);
|
|
1979
|
-
if (!isNaN(num)) {
|
|
1980
|
-
return [num, matchValue];
|
|
1981
|
-
}
|
|
1982
|
-
}
|
|
1983
|
-
// If both are strings, compare as strings
|
|
1984
|
-
if (typeof value === 'string' && typeof matchValue === 'string') {
|
|
1985
|
-
return [value, matchValue];
|
|
1986
|
-
}
|
|
1987
|
-
// If both are booleans, compare as booleans
|
|
1988
|
-
if (typeof value === 'boolean' && typeof matchValue === 'boolean') {
|
|
1989
|
-
return [value, matchValue];
|
|
1990
|
-
}
|
|
1991
|
-
// Default: convert both to strings for comparison
|
|
1992
|
-
return [String(value), String(matchValue)];
|
|
1993
|
-
}
|
|
1994
|
-
/**
|
|
1995
|
-
* Register safe functions
|
|
1996
|
-
* Equivalent to Go's registerSafe()
|
|
1997
|
-
*/
|
|
1998
|
-
registerSafeFunctions(funcMap) {
|
|
1999
|
-
// Return function - implements early return like Go's template.Return
|
|
2000
|
-
// Usage: {{ return VALUE }}
|
|
2001
|
-
funcMap.set('return', (...args) => {
|
|
2002
|
-
// If no arguments provided, return empty string
|
|
2003
|
-
if (args.length === 0) {
|
|
2004
|
-
return '';
|
|
2005
|
-
}
|
|
2006
|
-
// If single argument, return it directly
|
|
2007
|
-
if (args.length === 1) {
|
|
2008
|
-
return args[0];
|
|
2009
|
-
}
|
|
2010
|
-
// If multiple arguments, return them as an array
|
|
2011
|
-
return args;
|
|
2012
|
-
});
|
|
2013
|
-
// Cond function - implements conditional branching like Go's template.Cond
|
|
2014
|
-
// Usage: {{ cond CONDITION VALUE_IF_TRUE VALUE_IF_FALSE }}
|
|
2015
|
-
funcMap.set('cond', (...args) => {
|
|
2016
|
-
if (args.length < 2) {
|
|
2017
|
-
throw new Error('cond requires at least 2 arguments');
|
|
2018
|
-
}
|
|
2019
|
-
const condition = args[0];
|
|
2020
|
-
const trueValue = args[1];
|
|
2021
|
-
const falseValue = args.length > 2 ? args[2] : '';
|
|
2022
|
-
// Convert condition to boolean, following Go's truthiness rules
|
|
2023
|
-
let isTrue = false;
|
|
2024
|
-
if (condition === true || condition === 1) {
|
|
2025
|
-
isTrue = true;
|
|
2026
|
-
}
|
|
2027
|
-
else if (typeof condition === 'string') {
|
|
2028
|
-
isTrue = condition.length > 0 && condition !== "false" && condition !== "0";
|
|
2029
|
-
}
|
|
2030
|
-
else if (typeof condition === 'number') {
|
|
2031
|
-
isTrue = condition !== 0;
|
|
2032
|
-
}
|
|
2033
|
-
else if (Array.isArray(condition)) {
|
|
2034
|
-
isTrue = condition.length > 0;
|
|
2035
|
-
}
|
|
2036
|
-
else if (condition && typeof condition === 'object') {
|
|
2037
|
-
isTrue = Object.keys(condition).length > 0;
|
|
2038
|
-
}
|
|
2039
|
-
return isTrue ? trueValue : falseValue;
|
|
2040
|
-
});
|
|
2041
|
-
funcMap.set('safeHTML', (str) => str);
|
|
2042
|
-
funcMap.set('safeCSS', (str) => str);
|
|
2043
|
-
funcMap.set('safeJS', (str) => str);
|
|
2044
|
-
funcMap.set('safeURL', (str) => str);
|
|
2045
|
-
// Dict function for creating key-value maps
|
|
2046
|
-
funcMap.set('dict', (...args) => {
|
|
2047
|
-
if (args.length % 2 !== 0) {
|
|
2048
|
-
throw new Error('dict requires an even number of arguments');
|
|
2049
|
-
}
|
|
2050
|
-
const result = {};
|
|
2051
|
-
for (let i = 0; i < args.length; i += 2) {
|
|
2052
|
-
result[String(args[i])] = args[i + 1];
|
|
2053
|
-
}
|
|
2054
|
-
return result;
|
|
2055
|
-
});
|
|
2056
|
-
// Slice function for creating arrays
|
|
2057
|
-
funcMap.set('slice', (...args) => {
|
|
2058
|
-
return args;
|
|
2059
|
-
});
|
|
2060
|
-
// Default function for providing default values
|
|
2061
|
-
// TypeScript equivalent of Go's default function
|
|
2062
|
-
funcMap.set('default', (defaultValue, value) => {
|
|
2063
|
-
// Return the value if it exists and is not empty/null/undefined, otherwise return default
|
|
2064
|
-
if (value !== null && value !== undefined && value !== '' && value !== 0) {
|
|
2065
|
-
return value;
|
|
2066
|
-
}
|
|
2067
|
-
return defaultValue;
|
|
2068
|
-
});
|
|
2069
|
-
// Jsonify function - encodes a given object to JSON
|
|
2070
|
-
// Usage: {{ jsonify . }}
|
|
2071
|
-
// Usage: {{ jsonify (dict "indent" " ") . }}
|
|
2072
|
-
funcMap.set('jsonify', (...args) => {
|
|
2073
|
-
if (args.length === 0) {
|
|
2074
|
-
return '';
|
|
2075
|
-
}
|
|
2076
|
-
let obj;
|
|
2077
|
-
let opts = {};
|
|
2078
|
-
if (args.length === 1) {
|
|
2079
|
-
obj = args[0];
|
|
2080
|
-
}
|
|
2081
|
-
else if (args.length === 2) {
|
|
2082
|
-
// First argument is options, second is the object to jsonify
|
|
2083
|
-
const options = args[0];
|
|
2084
|
-
obj = args[1];
|
|
2085
|
-
if (options && typeof options === 'object') {
|
|
2086
|
-
opts.prefix = options.prefix || '';
|
|
2087
|
-
opts.indent = options.indent || '';
|
|
2088
|
-
opts.noHTMLEscape = options.noHTMLEscape || false;
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
else {
|
|
2092
|
-
throw new Error('too many arguments to jsonify');
|
|
2093
|
-
}
|
|
2094
|
-
try {
|
|
2095
|
-
let jsonString;
|
|
2096
|
-
if (opts.indent) {
|
|
2097
|
-
// Pretty print with indentation
|
|
2098
|
-
jsonString = JSON.stringify(obj, null, opts.indent);
|
|
2099
|
-
// Add prefix to each line if specified
|
|
2100
|
-
if (opts.prefix) {
|
|
2101
|
-
jsonString = jsonString
|
|
2102
|
-
.split('\n')
|
|
2103
|
-
.map(line => opts.prefix + line)
|
|
2104
|
-
.join('\n');
|
|
2105
|
-
}
|
|
2106
|
-
}
|
|
2107
|
-
else {
|
|
2108
|
-
// Compact JSON
|
|
2109
|
-
jsonString = JSON.stringify(obj);
|
|
2110
|
-
}
|
|
2111
|
-
// Handle HTML escaping (by default, JSON.stringify doesn't escape HTML)
|
|
2112
|
-
if (!opts.noHTMLEscape) {
|
|
2113
|
-
jsonString = jsonString
|
|
2114
|
-
.replace(/&/g, '\\u0026')
|
|
2115
|
-
.replace(/</g, '\\u003c')
|
|
2116
|
-
.replace(/>/g, '\\u003e');
|
|
2117
|
-
}
|
|
2118
|
-
return jsonString;
|
|
2119
|
-
}
|
|
2120
|
-
catch (error) {
|
|
2121
|
-
throw new Error(`failed to jsonify object: ${error.message}`);
|
|
2122
|
-
}
|
|
2123
|
-
});
|
|
2124
|
-
}
|
|
2125
|
-
/**
|
|
2126
|
-
* Register format functions (fmt namespace)
|
|
2127
|
-
* Equivalent to Go's registerFmt()
|
|
2128
|
-
*/
|
|
2129
|
-
registerFmtFunctions(funcMap) {
|
|
2130
|
-
// Basic printf, print, println functions (for backward compatibility)
|
|
2131
|
-
funcMap.set('printf', (format, ...args) => {
|
|
2132
|
-
// Enhanced printf implementation supporting %v, %s, %d, %f, %t
|
|
2133
|
-
let result = format;
|
|
2134
|
-
let argIndex = 0;
|
|
2135
|
-
// Replace format specifiers sequentially
|
|
2136
|
-
result = result.replace(/%[vsdft%]/g, (match) => {
|
|
2137
|
-
if (match === '%%') {
|
|
2138
|
-
return '%'; // Literal %
|
|
2139
|
-
}
|
|
2140
|
-
if (argIndex >= args.length) {
|
|
2141
|
-
return match; // Not enough arguments, keep the format specifier
|
|
2142
|
-
}
|
|
2143
|
-
const arg = args[argIndex++];
|
|
2144
|
-
switch (match) {
|
|
2145
|
-
case '%v': // Go's general format specifier
|
|
2146
|
-
case '%s': // String
|
|
2147
|
-
return String(arg);
|
|
2148
|
-
case '%d': // Integer
|
|
2149
|
-
return String(Math.floor(Number(arg) || 0));
|
|
2150
|
-
case '%f': // Float
|
|
2151
|
-
return String(Number(arg) || 0);
|
|
2152
|
-
case '%t': // Boolean
|
|
2153
|
-
return String(Boolean(arg));
|
|
2154
|
-
default:
|
|
2155
|
-
return String(arg);
|
|
2156
|
-
}
|
|
2157
|
-
});
|
|
2158
|
-
return result;
|
|
2159
|
-
});
|
|
2160
|
-
funcMap.set('print', (...args) => {
|
|
2161
|
-
return args.map(arg => String(arg)).join(' ');
|
|
2162
|
-
});
|
|
2163
|
-
funcMap.set('println', (...args) => {
|
|
2164
|
-
return args.map(arg => String(arg)).join(' ') + '\n';
|
|
2165
|
-
});
|
|
2166
|
-
// Standalone errorf and warnf functions for backward compatibility
|
|
2167
|
-
funcMap.set('errorf', (format, ...args) => {
|
|
2168
|
-
let message = format;
|
|
2169
|
-
for (let i = 0; i < args.length; i++) {
|
|
2170
|
-
message = message.replace(/%[sd%]/, String(args[i]));
|
|
2171
|
-
}
|
|
2172
|
-
log.error("Template Error:", message);
|
|
2173
|
-
return ''; // errorf returns empty string but logs the error
|
|
2174
|
-
});
|
|
2175
|
-
funcMap.set('warnf', (format, ...args) => {
|
|
2176
|
-
let message = format;
|
|
2177
|
-
for (let i = 0; i < args.length; i++) {
|
|
2178
|
-
message = message.replace(/%[sd%]/, String(args[i]));
|
|
2179
|
-
}
|
|
2180
|
-
log.warn("Template Warning:", message);
|
|
2181
|
-
return ''; // warnf returns empty string but logs the warning
|
|
2182
|
-
});
|
|
2183
|
-
// Fmt namespace functions - following Go's fmt package
|
|
2184
|
-
funcMap.set('fmt', () => ({
|
|
2185
|
-
// Print returns a string representation of args
|
|
2186
|
-
Print: (...args) => {
|
|
2187
|
-
return args.map(arg => String(arg)).join(' ');
|
|
2188
|
-
},
|
|
2189
|
-
// Printf returns string representation of args formatted with the layout in format
|
|
2190
|
-
Printf: (format, ...args) => {
|
|
2191
|
-
let result = format;
|
|
2192
|
-
for (let i = 0; i < args.length; i++) {
|
|
2193
|
-
result = result.replace(/%[sd%]/, String(args[i]));
|
|
2194
|
-
}
|
|
2195
|
-
return result;
|
|
2196
|
-
},
|
|
2197
|
-
// Println returns string representation of args ending with a newline
|
|
2198
|
-
Println: (...args) => {
|
|
2199
|
-
return args.map(arg => String(arg)).join(' ') + '\n';
|
|
2200
|
-
},
|
|
2201
|
-
// Errorf formats args according to a format specifier and logs an ERROR
|
|
2202
|
-
// It returns an empty string
|
|
2203
|
-
Errorf: (format, ...args) => {
|
|
2204
|
-
let message = format;
|
|
2205
|
-
for (let i = 0; i < args.length; i++) {
|
|
2206
|
-
message = message.replace(/%[sd%]/, String(args[i]));
|
|
2207
|
-
}
|
|
2208
|
-
log.error("Template Error:", message);
|
|
2209
|
-
return '';
|
|
2210
|
-
},
|
|
2211
|
-
// Erroridf formats args according to a format specifier and logs an ERROR with ID
|
|
2212
|
-
// It returns an empty string
|
|
2213
|
-
Erroridf: (id, format, ...args) => {
|
|
2214
|
-
let message = format;
|
|
2215
|
-
for (let i = 0; i < args.length; i++) {
|
|
2216
|
-
message = message.replace(/%[sd%]/, String(args[i]));
|
|
2217
|
-
}
|
|
2218
|
-
log.error("Template Error:", message);
|
|
2219
|
-
return '';
|
|
2220
|
-
},
|
|
2221
|
-
// Warnf formats args according to a format specifier and logs a WARNING
|
|
2222
|
-
// It returns an empty string
|
|
2223
|
-
Warnf: (format, ...args) => {
|
|
2224
|
-
let message = format;
|
|
2225
|
-
for (let i = 0; i < args.length; i++) {
|
|
2226
|
-
message = message.replace(/%[sd%]/, String(args[i]));
|
|
2227
|
-
}
|
|
2228
|
-
log.error("Template Warning:", message);
|
|
2229
|
-
return '';
|
|
2230
|
-
},
|
|
2231
|
-
// Warnidf formats args according to a format specifier and logs a WARNING with ID
|
|
2232
|
-
// It returns an empty string
|
|
2233
|
-
Warnidf: (id, format, ...args) => {
|
|
2234
|
-
let message = format;
|
|
2235
|
-
for (let i = 0; i < args.length; i++) {
|
|
2236
|
-
message = message.replace(/%[sd%]/, String(args[i]));
|
|
2237
|
-
}
|
|
2238
|
-
log.error("Template Warning:", message);
|
|
2239
|
-
return '';
|
|
2240
|
-
}
|
|
2241
|
-
}));
|
|
2242
|
-
}
|
|
2243
|
-
/**
|
|
2244
|
-
* Register reflect functions
|
|
2245
|
-
* Equivalent to Go's registerReflect()
|
|
2246
|
-
*/
|
|
2247
|
-
registerReflectFunctions(funcMap) {
|
|
2248
|
-
// Reflect namespace functions - following Go's reflect package
|
|
2249
|
-
funcMap.set('reflect', () => ({
|
|
2250
|
-
// IsMap reports whether v is a map/object
|
|
2251
|
-
// Following Go's implementation: only true maps, not structs/classes
|
|
2252
|
-
IsMap: (v) => {
|
|
2253
|
-
if (v === null || v === undefined) {
|
|
2254
|
-
return false;
|
|
2255
|
-
}
|
|
2256
|
-
// Must be an object
|
|
2257
|
-
if (typeof v !== 'object' || Array.isArray(v)) {
|
|
2258
|
-
return false;
|
|
2259
|
-
}
|
|
2260
|
-
// In TypeScript/JavaScript context, we consider something a "map" only if:
|
|
2261
|
-
// 1. It's a plain Object (constructor === Object)
|
|
2262
|
-
// 2. OR it's a Map instance
|
|
2263
|
-
// 3. OR it was explicitly created as a dict/map (has no prototype methods)
|
|
2264
|
-
// Check for Map instance
|
|
2265
|
-
if (v instanceof Map) {
|
|
2266
|
-
return true;
|
|
2267
|
-
}
|
|
2268
|
-
// Check for plain object (like golang's map)
|
|
2269
|
-
if (v.constructor === Object) {
|
|
2270
|
-
return true;
|
|
2271
|
-
}
|
|
2272
|
-
// Check if it looks like a dict created by template functions
|
|
2273
|
-
// (has no methods, only data properties)
|
|
2274
|
-
const proto = Object.getPrototypeOf(v);
|
|
2275
|
-
if (proto === Object.prototype || proto === null) {
|
|
2276
|
-
return true;
|
|
2277
|
-
}
|
|
2278
|
-
// Everything else (including class instances like Page) is not a map
|
|
2279
|
-
return false;
|
|
2280
|
-
},
|
|
2281
|
-
// IsSlice reports whether v is a slice/array
|
|
2282
|
-
IsSlice: (v) => {
|
|
2283
|
-
return Array.isArray(v);
|
|
2284
|
-
}
|
|
2285
|
-
}));
|
|
2286
|
-
}
|
|
2287
|
-
/**
|
|
2288
|
-
* Register path manipulation functions
|
|
2289
|
-
* Equivalent to Go's path package functions
|
|
2290
|
-
*/
|
|
2291
|
-
registerPathFunctions(funcMap) {
|
|
2292
|
-
// Path namespace functions - following Go's path package
|
|
2293
|
-
funcMap.set('path', () => ({
|
|
2294
|
-
// Base returns the last element of path
|
|
2295
|
-
Base: (path) => {
|
|
2296
|
-
if (!path)
|
|
2297
|
-
return '.';
|
|
2298
|
-
// 替换 Windows 分隔符 \ 为 /
|
|
2299
|
-
path = path.replace(/\\/g, '/');
|
|
2300
|
-
// Trim trailing slashes
|
|
2301
|
-
path = path.replace(/\/+$/, '');
|
|
2302
|
-
if (!path)
|
|
2303
|
-
return '/';
|
|
2304
|
-
// Get the last part after the last slash
|
|
2305
|
-
const parts = path.split('/');
|
|
2306
|
-
return parts[parts.length - 1] || '/';
|
|
2307
|
-
},
|
|
2308
|
-
// Clean returns the shortest path name equivalent to path
|
|
2309
|
-
Clean: (path) => {
|
|
2310
|
-
if (!path)
|
|
2311
|
-
return '.';
|
|
2312
|
-
// Convert backslashes to forward slashes
|
|
2313
|
-
path = path.replace(/\\/g, '/');
|
|
2314
|
-
// Handle absolute paths
|
|
2315
|
-
const isAbs = path.startsWith('/');
|
|
2316
|
-
// Split path into parts
|
|
2317
|
-
const parts = path.split('/').filter(p => p && p !== '.');
|
|
2318
|
-
// Handle .. parts
|
|
2319
|
-
const stack = [];
|
|
2320
|
-
for (const part of parts) {
|
|
2321
|
-
if (part === '..') {
|
|
2322
|
-
if (stack.length > 0 && stack[stack.length - 1] !== '..') {
|
|
2323
|
-
stack.pop();
|
|
2324
|
-
}
|
|
2325
|
-
else if (!isAbs) {
|
|
2326
|
-
stack.push('..');
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
else {
|
|
2330
|
-
stack.push(part);
|
|
2331
|
-
}
|
|
2332
|
-
}
|
|
2333
|
-
// Join parts back together
|
|
2334
|
-
path = stack.join('/');
|
|
2335
|
-
if (isAbs)
|
|
2336
|
-
path = '/' + path;
|
|
2337
|
-
return path || (isAbs ? '/' : '.');
|
|
2338
|
-
},
|
|
2339
|
-
// Dir returns all but the last element of path
|
|
2340
|
-
Dir: (path) => {
|
|
2341
|
-
if (!path)
|
|
2342
|
-
return '.';
|
|
2343
|
-
// Trim trailing slashes
|
|
2344
|
-
path = path.replace(/\/+$/, '');
|
|
2345
|
-
if (!path)
|
|
2346
|
-
return '/';
|
|
2347
|
-
// Get everything before the last slash
|
|
2348
|
-
const parts = path.split('/');
|
|
2349
|
-
parts.pop();
|
|
2350
|
-
return parts.join('/') || '.';
|
|
2351
|
-
},
|
|
2352
|
-
// Ext returns the file name extension
|
|
2353
|
-
Ext: (path) => {
|
|
2354
|
-
const base = path.split('/').pop() || '';
|
|
2355
|
-
const dot = base.lastIndexOf('.');
|
|
2356
|
-
if (dot === -1 || dot === 0)
|
|
2357
|
-
return '';
|
|
2358
|
-
return base.substring(dot);
|
|
2359
|
-
},
|
|
2360
|
-
// IsAbs reports whether the path is absolute
|
|
2361
|
-
IsAbs: (path) => {
|
|
2362
|
-
return path.startsWith('/');
|
|
2363
|
-
},
|
|
2364
|
-
// Join joins any number of path elements into a single path
|
|
2365
|
-
Join: (...elements) => {
|
|
2366
|
-
if (elements.length === 0)
|
|
2367
|
-
return '.';
|
|
2368
|
-
// Filter out empty elements and handle trailing slashes
|
|
2369
|
-
const parts = elements
|
|
2370
|
-
.filter(e => e)
|
|
2371
|
-
.map(e => e.replace(/^\/+|\/+$/g, ''));
|
|
2372
|
-
// Join parts with single slashes
|
|
2373
|
-
let path = parts.join('/');
|
|
2374
|
-
// Handle absolute paths
|
|
2375
|
-
if (elements[0] && elements[0].startsWith('/')) {
|
|
2376
|
-
path = '/' + path;
|
|
2377
|
-
}
|
|
2378
|
-
return path || '.';
|
|
2379
|
-
},
|
|
2380
|
-
// Split splits path immediately following the final slash
|
|
2381
|
-
Split: (path) => {
|
|
2382
|
-
if (!path)
|
|
2383
|
-
return ['.', ''];
|
|
2384
|
-
// Find the last slash
|
|
2385
|
-
const lastSlash = path.lastIndexOf('/');
|
|
2386
|
-
if (lastSlash === -1) {
|
|
2387
|
-
return ['', path];
|
|
2388
|
-
}
|
|
2389
|
-
return [
|
|
2390
|
-
path.substring(0, lastSlash),
|
|
2391
|
-
path.substring(lastSlash + 1)
|
|
2392
|
-
];
|
|
2393
|
-
}
|
|
2394
|
-
}));
|
|
2395
|
-
}
|
|
2396
|
-
/**
|
|
2397
|
-
* Register transform functions (unmarshal, etc.)
|
|
2398
|
-
* Equivalent to Go's transform package functions
|
|
2399
|
-
*/
|
|
2400
|
-
registerTransformFunctions(funcMap) {
|
|
2401
|
-
// Transform namespace functions - following Go's transform package
|
|
2402
|
-
funcMap.set('transform', () => ({
|
|
2403
|
-
// Unmarshal unmarshals data from JSON, YAML, TOML, CSV formats
|
|
2404
|
-
// Usage: {{ $data := "{"key": "value"}" | transform.Unmarshal }}
|
|
2405
|
-
// Usage: {{ $data := (dict "format" "json") $jsonString | transform.Unmarshal }}
|
|
2406
|
-
Unmarshal: (...args) => {
|
|
2407
|
-
if (args.length < 1 || args.length > 2) {
|
|
2408
|
-
throw new Error('unmarshal takes 1 or 2 arguments');
|
|
2409
|
-
}
|
|
2410
|
-
let data;
|
|
2411
|
-
let options = {};
|
|
2412
|
-
if (args.length === 1) {
|
|
2413
|
-
data = args[0];
|
|
2414
|
-
}
|
|
2415
|
-
else {
|
|
2416
|
-
// First argument is options map
|
|
2417
|
-
const opts = args[0];
|
|
2418
|
-
if (!opts || typeof opts !== 'object') {
|
|
2419
|
-
throw new Error('first argument must be a map');
|
|
2420
|
-
}
|
|
2421
|
-
options = opts;
|
|
2422
|
-
data = args[1];
|
|
2423
|
-
}
|
|
2424
|
-
// Handle Resource objects (if data has Content method)
|
|
2425
|
-
if (data && typeof data === 'object' && typeof data.Content === 'function') {
|
|
2426
|
-
try {
|
|
2427
|
-
const content = data.Content();
|
|
2428
|
-
return this.unmarshalContent(content, options);
|
|
2429
|
-
}
|
|
2430
|
-
catch (error) {
|
|
2431
|
-
throw new Error(`failed to get content from resource: ${error.message}`);
|
|
2432
|
-
}
|
|
2433
|
-
}
|
|
2434
|
-
// Handle string data
|
|
2435
|
-
let dataStr;
|
|
2436
|
-
if (typeof data === 'string') {
|
|
2437
|
-
dataStr = data;
|
|
2438
|
-
}
|
|
2439
|
-
else if (data && typeof data.toString === 'function') {
|
|
2440
|
-
dataStr = data.toString();
|
|
2441
|
-
}
|
|
2442
|
-
else {
|
|
2443
|
-
throw new Error(`type ${typeof data} not supported`);
|
|
2444
|
-
}
|
|
2445
|
-
if (!dataStr || dataStr.trim() === '') {
|
|
2446
|
-
return null;
|
|
2447
|
-
}
|
|
2448
|
-
return this.unmarshalContent(dataStr, options);
|
|
2449
|
-
},
|
|
2450
|
-
// Plainify returns a copy of s with all HTML tags removed
|
|
2451
|
-
// Equivalent to Go's Plainify function in transform namespace
|
|
2452
|
-
// Usage: {{ "Hello <strong>world</strong>!" | transform.Plainify }} -> "Hello world!"
|
|
2453
|
-
// Usage: {{ transform.Plainify "<p>Text with <br> tags</p>" }} -> "Text with tags"
|
|
2454
|
-
Plainify: (s) => {
|
|
2455
|
-
const str = String(s);
|
|
2456
|
-
return this.stripHTML(str);
|
|
2457
|
-
}
|
|
2458
|
-
}));
|
|
2459
|
-
// Also register unmarshal as a standalone function for backward compatibility
|
|
2460
|
-
funcMap.set('unmarshal', (...args) => {
|
|
2461
|
-
const transform = funcMap.get('transform')();
|
|
2462
|
-
return transform.Unmarshal(...args);
|
|
2463
|
-
});
|
|
2464
|
-
// Register plainify as a standalone function for convenience
|
|
2465
|
-
funcMap.set('plainify', (s) => {
|
|
2466
|
-
const str = String(s);
|
|
2467
|
-
return this.stripHTML(str);
|
|
2468
|
-
});
|
|
2469
|
-
}
|
|
2470
|
-
/**
|
|
2471
|
-
* Strip HTML tags from a string
|
|
2472
|
-
* Equivalent to Go's helpers.StripHTML function
|
|
2473
|
-
* Preserves line breaks from block elements and normalizes whitespace
|
|
2474
|
-
*/
|
|
2475
|
-
stripHTML(html) {
|
|
2476
|
-
// Shortcut for strings with no HTML tags
|
|
2477
|
-
if (!html.includes('<') && !html.includes('>')) {
|
|
2478
|
-
return html;
|
|
2479
|
-
}
|
|
2480
|
-
// First pass: Replace block elements that should create line breaks
|
|
2481
|
-
let result = html
|
|
2482
|
-
.replace(/\n/g, ' ') // Convert newlines to spaces first
|
|
2483
|
-
.replace(/<\/p>/gi, '\n') // </p> creates line break
|
|
2484
|
-
.replace(/<br\s*\/?>/gi, '\n') // <br> and <br/> create line breaks
|
|
2485
|
-
.replace(/<\/div>/gi, '\n') // </div> creates line break
|
|
2486
|
-
.replace(/<\/h[1-6]>/gi, '\n') // Heading end tags create line breaks
|
|
2487
|
-
.replace(/<\/li>/gi, '\n') // List items create line breaks
|
|
2488
|
-
.replace(/<\/tr>/gi, '\n') // Table rows create line breaks
|
|
2489
|
-
.replace(/<\/blockquote>/gi, '\n'); // Blockquotes create line breaks
|
|
2490
|
-
// Second pass: Remove all HTML tags
|
|
2491
|
-
result = result.replace(/<[^>]*>/g, '');
|
|
2492
|
-
// Third pass: Normalize whitespace
|
|
2493
|
-
// Convert multiple spaces to single spaces, but preserve intentional line breaks
|
|
2494
|
-
const lines = result.split('\n');
|
|
2495
|
-
const normalizedLines = lines.map(line => line.trim().replace(/\s+/g, ' '));
|
|
2496
|
-
// Join lines back together, removing empty lines but preserving intentional breaks
|
|
2497
|
-
result = normalizedLines
|
|
2498
|
-
.filter(line => line.length > 0)
|
|
2499
|
-
.join('\n')
|
|
2500
|
-
.trim();
|
|
2501
|
-
// Final cleanup: ensure we don't have multiple consecutive newlines
|
|
2502
|
-
result = result.replace(/\n\s*\n/g, '\n');
|
|
2503
|
-
return result;
|
|
2504
|
-
}
|
|
2505
|
-
/**
|
|
2506
|
-
* Unmarshal content from string based on format
|
|
2507
|
-
* Supports JSON, YAML, TOML, CSV formats
|
|
2508
|
-
*/
|
|
2509
|
-
unmarshalContent(content, options = {}) {
|
|
2510
|
-
const trimmedContent = content.trim();
|
|
2511
|
-
if (!trimmedContent) {
|
|
2512
|
-
return null;
|
|
2513
|
-
}
|
|
2514
|
-
// Determine format
|
|
2515
|
-
let format = options.format;
|
|
2516
|
-
if (!format) {
|
|
2517
|
-
format = this.detectFormat(trimmedContent);
|
|
2518
|
-
}
|
|
2519
|
-
try {
|
|
2520
|
-
switch (format.toLowerCase()) {
|
|
2521
|
-
case 'json':
|
|
2522
|
-
return JSON.parse(trimmedContent);
|
|
2523
|
-
case 'yaml':
|
|
2524
|
-
case 'yml':
|
|
2525
|
-
return this.parseYAML(trimmedContent);
|
|
2526
|
-
case 'toml':
|
|
2527
|
-
return this.parseTOML(trimmedContent);
|
|
2528
|
-
case 'csv':
|
|
2529
|
-
return this.parseCSV(trimmedContent);
|
|
2530
|
-
default:
|
|
2531
|
-
throw new Error(`format "${format}" not supported`);
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
catch (error) {
|
|
2535
|
-
throw new Error(`failed to unmarshal ${format}: ${error.message}`);
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
/**
|
|
2539
|
-
* Detect format from content
|
|
2540
|
-
*/
|
|
2541
|
-
detectFormat(content) {
|
|
2542
|
-
const trimmed = content.trim();
|
|
2543
|
-
// JSON detection
|
|
2544
|
-
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
2545
|
-
(trimmed.startsWith('[') && trimmed.endsWith(']'))) {
|
|
2546
|
-
try {
|
|
2547
|
-
JSON.parse(trimmed);
|
|
2548
|
-
return 'json';
|
|
2549
|
-
}
|
|
2550
|
-
catch {
|
|
2551
|
-
// Not valid JSON, continue checking
|
|
2552
|
-
}
|
|
2553
|
-
}
|
|
2554
|
-
// YAML detection (starts with --- or has key: value patterns)
|
|
2555
|
-
if (trimmed.startsWith('---') || /^[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*.+/m.test(trimmed)) {
|
|
2556
|
-
return 'yaml';
|
|
2557
|
-
}
|
|
2558
|
-
// TOML detection (has [section] or key = value patterns)
|
|
2559
|
-
if (/^\[.*\]$/m.test(trimmed) || /^[a-zA-Z_][a-zA-Z0-9_]*\s*=\s*.+/m.test(trimmed)) {
|
|
2560
|
-
return 'toml';
|
|
2561
|
-
}
|
|
2562
|
-
// CSV detection (has comma-separated values)
|
|
2563
|
-
if (/^[^,\n]*,[^,\n]*/.test(trimmed)) {
|
|
2564
|
-
return 'csv';
|
|
2565
|
-
}
|
|
2566
|
-
// Default to JSON if uncertain
|
|
2567
|
-
return 'json';
|
|
2568
|
-
}
|
|
2569
|
-
/**
|
|
2570
|
-
* Parse YAML content (basic implementation)
|
|
2571
|
-
* For a full implementation, you'd want to use a proper YAML library
|
|
2572
|
-
*/
|
|
2573
|
-
parseYAML(content) {
|
|
2574
|
-
// This is a very basic YAML parser for simple key-value pairs
|
|
2575
|
-
// For production use, consider integrating a proper YAML library like js-yaml
|
|
2576
|
-
const lines = content.split('\n');
|
|
2577
|
-
const result = {};
|
|
2578
|
-
for (const line of lines) {
|
|
2579
|
-
const trimmedLine = line.trim();
|
|
2580
|
-
if (!trimmedLine || trimmedLine.startsWith('#') || trimmedLine === '---') {
|
|
2581
|
-
continue;
|
|
2582
|
-
}
|
|
2583
|
-
const colonIndex = trimmedLine.indexOf(':');
|
|
2584
|
-
if (colonIndex > 0) {
|
|
2585
|
-
const key = trimmedLine.substring(0, colonIndex).trim();
|
|
2586
|
-
let value = trimmedLine.substring(colonIndex + 1).trim();
|
|
2587
|
-
// Remove quotes if present
|
|
2588
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
2589
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
2590
|
-
value = value.slice(1, -1);
|
|
2591
|
-
}
|
|
2592
|
-
// Try to parse as number or boolean
|
|
2593
|
-
if (value === 'true') {
|
|
2594
|
-
result[key] = true;
|
|
2595
|
-
}
|
|
2596
|
-
else if (value === 'false') {
|
|
2597
|
-
result[key] = false;
|
|
2598
|
-
}
|
|
2599
|
-
else if (/^\d+$/.test(value)) {
|
|
2600
|
-
result[key] = parseInt(value, 10);
|
|
2601
|
-
}
|
|
2602
|
-
else if (/^\d*\.\d+$/.test(value)) {
|
|
2603
|
-
result[key] = parseFloat(value);
|
|
2604
|
-
}
|
|
2605
|
-
else {
|
|
2606
|
-
result[key] = value;
|
|
2607
|
-
}
|
|
2608
|
-
}
|
|
2609
|
-
}
|
|
2610
|
-
return result;
|
|
2611
|
-
}
|
|
2612
|
-
/**
|
|
2613
|
-
* Parse TOML content (basic implementation)
|
|
2614
|
-
* For a full implementation, you'd want to use a proper TOML library
|
|
2615
|
-
*/
|
|
2616
|
-
parseTOML(content) {
|
|
2617
|
-
// This is a very basic TOML parser for simple key-value pairs
|
|
2618
|
-
// For production use, consider integrating a proper TOML library
|
|
2619
|
-
const lines = content.split('\n');
|
|
2620
|
-
const result = {};
|
|
2621
|
-
let currentSection = '';
|
|
2622
|
-
for (const line of lines) {
|
|
2623
|
-
const trimmedLine = line.trim();
|
|
2624
|
-
if (!trimmedLine || trimmedLine.startsWith('#')) {
|
|
2625
|
-
continue;
|
|
2626
|
-
}
|
|
2627
|
-
// Section headers [section]
|
|
2628
|
-
if (trimmedLine.startsWith('[') && trimmedLine.endsWith(']')) {
|
|
2629
|
-
currentSection = trimmedLine.slice(1, -1);
|
|
2630
|
-
if (!result[currentSection]) {
|
|
2631
|
-
result[currentSection] = {};
|
|
2632
|
-
}
|
|
2633
|
-
continue;
|
|
2634
|
-
}
|
|
2635
|
-
// Key-value pairs
|
|
2636
|
-
const equalIndex = trimmedLine.indexOf('=');
|
|
2637
|
-
if (equalIndex > 0) {
|
|
2638
|
-
const key = trimmedLine.substring(0, equalIndex).trim();
|
|
2639
|
-
let value = trimmedLine.substring(equalIndex + 1).trim();
|
|
2640
|
-
// Remove quotes if present
|
|
2641
|
-
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
2642
|
-
(value.startsWith("'") && value.endsWith("'"))) {
|
|
2643
|
-
value = value.slice(1, -1);
|
|
2644
|
-
}
|
|
2645
|
-
// Parse value
|
|
2646
|
-
let parsedValue;
|
|
2647
|
-
if (value === 'true') {
|
|
2648
|
-
parsedValue = true;
|
|
2649
|
-
}
|
|
2650
|
-
else if (value === 'false') {
|
|
2651
|
-
parsedValue = false;
|
|
2652
|
-
}
|
|
2653
|
-
else if (/^\d+$/.test(value)) {
|
|
2654
|
-
parsedValue = parseInt(value, 10);
|
|
2655
|
-
}
|
|
2656
|
-
else if (/^\d*\.\d+$/.test(value)) {
|
|
2657
|
-
parsedValue = parseFloat(value);
|
|
2658
|
-
}
|
|
2659
|
-
else {
|
|
2660
|
-
parsedValue = value;
|
|
2661
|
-
}
|
|
2662
|
-
if (currentSection) {
|
|
2663
|
-
result[currentSection][key] = parsedValue;
|
|
2664
|
-
}
|
|
2665
|
-
else {
|
|
2666
|
-
result[key] = parsedValue;
|
|
2667
|
-
}
|
|
2668
|
-
}
|
|
2669
|
-
}
|
|
2670
|
-
return result;
|
|
2671
|
-
}
|
|
2672
|
-
/**
|
|
2673
|
-
* Parse CSV content (basic implementation)
|
|
2674
|
-
*/
|
|
2675
|
-
parseCSV(content) {
|
|
2676
|
-
const lines = content.trim().split('\n');
|
|
2677
|
-
if (lines.length === 0) {
|
|
2678
|
-
return [];
|
|
2679
|
-
}
|
|
2680
|
-
// Parse header row
|
|
2681
|
-
const headers = this.parseCSVLine(lines[0]);
|
|
2682
|
-
const result = [];
|
|
2683
|
-
// Parse data rows
|
|
2684
|
-
for (let i = 1; i < lines.length; i++) {
|
|
2685
|
-
const values = this.parseCSVLine(lines[i]);
|
|
2686
|
-
const row = {};
|
|
2687
|
-
for (let j = 0; j < headers.length; j++) {
|
|
2688
|
-
const header = headers[j];
|
|
2689
|
-
const value = j < values.length ? values[j] : '';
|
|
2690
|
-
// Try to parse as number
|
|
2691
|
-
if (/^\d+$/.test(value)) {
|
|
2692
|
-
row[header] = parseInt(value, 10);
|
|
2693
|
-
}
|
|
2694
|
-
else if (/^\d*\.\d+$/.test(value)) {
|
|
2695
|
-
row[header] = parseFloat(value);
|
|
2696
|
-
}
|
|
2697
|
-
else if (value === 'true') {
|
|
2698
|
-
row[header] = true;
|
|
2699
|
-
}
|
|
2700
|
-
else if (value === 'false') {
|
|
2701
|
-
row[header] = false;
|
|
2702
|
-
}
|
|
2703
|
-
else {
|
|
2704
|
-
row[header] = value;
|
|
2705
|
-
}
|
|
2706
|
-
}
|
|
2707
|
-
result.push(row);
|
|
2708
|
-
}
|
|
2709
|
-
return result;
|
|
2710
|
-
}
|
|
2711
|
-
/**
|
|
2712
|
-
* Parse a single CSV line, handling quoted values
|
|
2713
|
-
*/
|
|
2714
|
-
parseCSVLine(line) {
|
|
2715
|
-
const result = [];
|
|
2716
|
-
let current = '';
|
|
2717
|
-
let inQuotes = false;
|
|
2718
|
-
for (let i = 0; i < line.length; i++) {
|
|
2719
|
-
const char = line[i];
|
|
2720
|
-
if (char === '"') {
|
|
2721
|
-
if (inQuotes && line[i + 1] === '"') {
|
|
2722
|
-
// Escaped quote
|
|
2723
|
-
current += '"';
|
|
2724
|
-
i++; // Skip next quote
|
|
2725
|
-
}
|
|
2726
|
-
else {
|
|
2727
|
-
// Toggle quote state
|
|
2728
|
-
inQuotes = !inQuotes;
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
else if (char === ',' && !inQuotes) {
|
|
2732
|
-
// Field separator
|
|
2733
|
-
result.push(current.trim());
|
|
2734
|
-
current = '';
|
|
2735
|
-
}
|
|
2736
|
-
else {
|
|
2737
|
-
current += char;
|
|
2738
|
-
}
|
|
2739
|
-
}
|
|
2740
|
-
// Add the last field
|
|
2741
|
-
result.push(current.trim());
|
|
2742
|
-
return result;
|
|
2743
|
-
}
|
|
2744
|
-
/**
|
|
2745
|
-
* Get nested value from object using dot notation path
|
|
2746
|
-
* Following golang's path resolution logic
|
|
2747
|
-
*/
|
|
2748
|
-
getNestedValue(obj, path) {
|
|
2749
|
-
if (!obj || !path) {
|
|
2750
|
-
return undefined;
|
|
2751
|
-
}
|
|
2752
|
-
// Handle special case where path starts with a dot
|
|
2753
|
-
const cleanPath = path.replace(/^\\.+/, '');
|
|
2754
|
-
const parts = cleanPath.split('.');
|
|
2755
|
-
let current = obj;
|
|
2756
|
-
for (let i = 0; i < parts.length; i++) {
|
|
2757
|
-
const part = parts[i];
|
|
2758
|
-
if (current == null) {
|
|
2759
|
-
return undefined;
|
|
2760
|
-
}
|
|
2761
|
-
// Handle array/object access
|
|
2762
|
-
if (typeof current === 'object') {
|
|
2763
|
-
// First try exact match (case-sensitive)
|
|
2764
|
-
if (current.hasOwnProperty(part)) {
|
|
2765
|
-
current = current[part];
|
|
2766
|
-
continue;
|
|
2767
|
-
}
|
|
2768
|
-
// Then try case-insensitive property access (like Hugo)
|
|
2769
|
-
const keys = Object.keys(current);
|
|
2770
|
-
const matchingKey = keys.find(k => k.toLowerCase() === part.toLowerCase());
|
|
2771
|
-
if (matchingKey) {
|
|
2772
|
-
current = current[matchingKey];
|
|
2773
|
-
continue;
|
|
2774
|
-
}
|
|
2775
|
-
// Special case: Try method call for common Hugo properties
|
|
2776
|
-
// Kind -> kind(), Content -> content(), etc.
|
|
2777
|
-
const methodName = part.toLowerCase();
|
|
2778
|
-
if (typeof current[methodName] === 'function') {
|
|
2779
|
-
try {
|
|
2780
|
-
current = current[methodName]();
|
|
2781
|
-
continue;
|
|
2782
|
-
}
|
|
2783
|
-
catch (error) {
|
|
2784
|
-
return undefined;
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
return undefined;
|
|
2788
|
-
}
|
|
2789
|
-
else {
|
|
2790
|
-
return undefined;
|
|
2791
|
-
}
|
|
2792
|
-
}
|
|
2793
|
-
return current;
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
exports.DefaultTemplateRegistry = DefaultTemplateRegistry;
|
|
2797
|
-
/**
|
|
2798
|
-
* Create default template registry
|
|
2799
|
-
*/
|
|
2800
|
-
function newTemplateRegistry() {
|
|
2801
|
-
return new DefaultTemplateRegistry();
|
|
2802
|
-
}
|
|
2803
|
-
/**
|
|
2804
|
-
* Convenience function to create and register core functions only
|
|
2805
|
-
*/
|
|
2806
|
-
function createCoreFuncMap() {
|
|
2807
|
-
const funcMap = new Map();
|
|
2808
|
-
const registry = newTemplateRegistry();
|
|
2809
|
-
registry.registerCoreFunctions(funcMap);
|
|
2810
|
-
return funcMap;
|
|
2811
|
-
}
|
|
2812
|
-
/**
|
|
2813
|
-
* Convenience function to create and register all functions with services
|
|
2814
|
-
*/
|
|
2815
|
-
function createStandardFuncMap(services) {
|
|
2816
|
-
const funcMap = new Map();
|
|
2817
|
-
const registry = newTemplateRegistry();
|
|
2818
|
-
registry.registerAllFunctions(funcMap, services);
|
|
2819
|
-
return funcMap;
|
|
2820
|
-
}
|
|
2821
|
-
/**
|
|
2822
|
-
* Update all engine-dependent functions with the template engine instance
|
|
2823
|
-
* This should be called after the template engine is created
|
|
2824
|
-
*/
|
|
2825
|
-
function updateEngineDependentFunctions(engine) {
|
|
2826
|
-
for (const func of engineDependentFunctions) {
|
|
2827
|
-
try {
|
|
2828
|
-
func.updateEngine(engine);
|
|
2829
|
-
}
|
|
2830
|
-
catch (error) {
|
|
2831
|
-
log.error(`❌ Failed to update function ${func.getFunctionName()}:`, error);
|
|
2832
|
-
}
|
|
2833
|
-
}
|
|
2834
|
-
}
|
|
2835
|
-
//# sourceMappingURL=registry.js.map
|