diff --git a/.changeset/fast-forks-cough.md b/.changeset/fast-forks-cough.md new file mode 100644 index 0000000..c883898 --- /dev/null +++ b/.changeset/fast-forks-cough.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': minor +--- + +feat(title): add templated title support diff --git a/.changeset/frank-books-grow.md b/.changeset/frank-books-grow.md new file mode 100644 index 0000000..1dec88a --- /dev/null +++ b/.changeset/frank-books-grow.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': patch +--- + +test: add test case to cover all codebase diff --git a/.changeset/goofy-groups-post.md b/.changeset/goofy-groups-post.md new file mode 100644 index 0000000..1839a5f --- /dev/null +++ b/.changeset/goofy-groups-post.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': minor +--- + +feat(script): extract src or inline source as dedicated parameter in addScript diff --git a/.changeset/itchy-eagles-give.md b/.changeset/itchy-eagles-give.md new file mode 100644 index 0000000..c16beb1 --- /dev/null +++ b/.changeset/itchy-eagles-give.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': patch +--- + +refactor(builder): explicitly return this and unify variable names diff --git a/.changeset/loose-banks-nail.md b/.changeset/loose-banks-nail.md new file mode 100644 index 0000000..eb7e5bf --- /dev/null +++ b/.changeset/loose-banks-nail.md @@ -0,0 +1,10 @@ +--- +'@devsantara/head': minor +--- + +feat(builder): implement element deduplication with map + +- Replace array-based element storage with Map for O(1) deduplication +- Add getElementKey() method to generate unique keys based on element type and attributes +- Elements with same key now replace previous ones instead of duplicating +- Update build() method to convert Map to array format diff --git a/.changeset/pink-pumas-judge.md b/.changeset/pink-pumas-judge.md new file mode 100644 index 0000000..d7b5c42 --- /dev/null +++ b/.changeset/pink-pumas-judge.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': minor +--- + +feat(link): extract href as dedicated parameter in addLink diff --git a/.changeset/public-turtles-hammer.md b/.changeset/public-turtles-hammer.md new file mode 100644 index 0000000..a8d40e0 --- /dev/null +++ b/.changeset/public-turtles-hammer.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': minor +--- + +fix(builder): missing manifest key and remove unused try-catch diff --git a/.changeset/whole-badgers-slide.md b/.changeset/whole-badgers-slide.md new file mode 100644 index 0000000..9d5080a --- /dev/null +++ b/.changeset/whole-badgers-slide.md @@ -0,0 +1,5 @@ +--- +'@devsantara/head': minor +--- + +feat(style): extract inline css as dedicated parameter in addStyle diff --git a/.gitignore b/.gitignore index cf2a798..a774930 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,8 @@ node_modules/ # Build dist/ +# Testing +coverage/ + # Misc .DS_Store \ No newline at end of file diff --git a/README.md b/README.md index 4cdb358..244be0b 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,12 @@ import { HeadBuilder } from '@devsantara/head'; const head = new HeadBuilder() .addTitle('My Awesome Website') .addDescription('A comprehensive guide to web development') + .addStyle('body { margin: 0; padding: 0; }') .addViewport({ width: 'device-width', initialScale: 1 }) + .addScript({ code: 'console.log("Hello, world!");' }) + .addScript(new URL('https://devsantara.com/assets/scripts/utils.js'), { + async: true, + }) .build(); ``` @@ -85,6 +90,28 @@ const head = new HeadBuilder() content: 'width=device-width, initial-scale=1', }, }, + { + type: 'style', + attributes: { + type: 'text/css', + children: 'body { margin: 0; padding: 0; }', + }, + }, + { + type: 'script', + attributes: { + type: 'text/javascript', + children: 'console.log("Hello, world!");', + }, + }, + { + type: 'script', + attributes: { + type: 'text/javascript', + src: 'https://devsantara.com/assets/scripts/utils.js', + async: true, + }, + }, ]; ``` @@ -140,6 +167,95 @@ const head = new HeadBuilder({ ]; ``` +### With Templated Title + +Set a title template with a default value, then pass page-specific titles as strings. The builder automatically applies the saved template to subsequent title updates: + +```typescript +import { HeadBuilder } from '@devsantara/head'; + +// Create a builder and set title template with default +// The template stays active for all future addTitle() calls +const sharedHead = new HeadBuilder().addTitle({ + template: '%s | My Awesome site', // Store template (%s is the placeholder) + default: 'Home', // Initial title using template +}); +// Output: