{"id":22374184,"url":"https://github.com/creativestyle/kombinator","last_synced_at":"2025-07-09T01:11:58.094Z","repository":{"id":153245430,"uuid":"628279498","full_name":"creativestyle/kombinator","owner":"creativestyle","description":null,"archived":false,"fork":false,"pushed_at":"2024-06-05T09:49:03.000Z","size":171,"stargazers_count":0,"open_issues_count":2,"forks_count":5,"subscribers_count":9,"default_branch":"main","last_synced_at":"2024-11-26T03:03:49.102Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/creativestyle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-15T13:07:43.000Z","updated_at":"2023-04-15T13:08:20.000Z","dependencies_parsed_at":"2024-03-27T09:26:41.183Z","dependency_job_id":"551e200e-b00d-4966-ae26-b152896e08ad","html_url":"https://github.com/creativestyle/kombinator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creativestyle%2Fkombinator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creativestyle%2Fkombinator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creativestyle%2Fkombinator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creativestyle%2Fkombinator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/creativestyle","download_url":"https://codeload.github.com/creativestyle/kombinator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228192318,"owners_count":17882756,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-04T21:16:19.868Z","updated_at":"2024-12-04T21:16:20.412Z","avatar_url":"https://github.com/creativestyle.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kombinator\n\n**Kombinator** is a set of build plugins that combines a Nuxt 3 base project and a customization layer into a fully functional product. It is designed to streamline the process of creating customized versions of a Nuxt 3 application.\n\nTo use the tool, developers first create or obtain the Nuxt 3 base project, which serves as the foundation for all customized versions. They then create a customization layer that includes any necessary modifications or additions to the base project. This might include changes to the user interface, business logic, or integration with other systems.\n\nOnce the base project and customization layer are created, the tool combines them into a single, fully functional product. This can be done through a process of merging the two codebases, compiling the resulting code, and generating any necessary configuration files or deployment scripts.\n\nThe resulting product is then ready for testing and deployment, either on a local machine or in a production environment. The customization layer can be easily swapped out or modified as needed, allowing for rapid iteration and customization of the underlying Nuxt 3 application.\n\n\n# API - VUE - functions you can use in mod files\n\n#### `fromTemplate(template: string)`\n\nSets the template to be modified.\n\n#### `getTemplate(): string`\n\nGets the modified template.\n\n## Finding element (tag)\n\nBefore modifying elements you need to find proper element with simplified selectors.\n\n#### `findByTag(tagName: string)`\n\nFinds the first element with given tag\n\n#### `findByAttribute(name: string)`\n\nFinds the first tag in the template with given attribute\n\n#### `findByAttributeValue(name: string, value: string)`\n\nFinds the first tag in the template with given attribute having given value\n\n#### `findFirst(): VueElementFinder`\n\nFinds first element in the template\n\n## Modification of attributes\n\n#### `removeAttribute(name: string)`\n\nRemoves an attribute with the given `name` from the HTML element found by `find*()`. \n\n#### `reduceAttribute(name: string, value: string)`\n\nReduces the value of an attribute with the given `name` by removing the given `value` from it. \n\n#### `regexpAttribute(name: string, regexp: RegExp, replace: string)`\n\nReplaces the value of an attribute with the given `name` by applying the given regular expression `regexp` and replacement `replace` on it.\n\n#### `extendAttribute(name: string, value: string, glue = ' ')`\n\nExtends the value of an attribute with the given `name` by appending the given `value` to it with the given `glue` separator. If the attribute does not exist, it will be added to the HTML element. \n\n#### `transformAttributeValue(name: string, callback: AttributeTransformer)`\n\nThe method is used to modify the value of an attribute of an element using a callback function.\n\n- `callback` (AttributeTransformer): A function that takes the current value of the attribute as input and returns either a new value or `null` if the attribute should be removed\n\n#### `setAttribute(name: string, value: string)`\n\nSets the value of an attribute with the given `name` to the given `value`. If the attribute already exists, its value will be replaced. Otherwise, the attribute will be added to the HTML element.\n\n#### `getAttributeValue(name: string, value: string): string`\n\nGets the value of an attribute with the given `name`. If the attribute does not exist, its value will be \"\". Usefull for optimization of  classes, e.g. with tailwind-merge.\n\n### Example Usage\n\n```javascript\nimport { VueModifyTemplate } from \"@creativestyle/kombinator\";\n\nconst code = `\n  \u003cdiv class=\"foo\" id=\"bar\" v-if=\"isTrue\" v-for=\"item in items\"\u003e{{ item }}\u003c/div\u003e\n`;\n\nconst modifier = new VueModifyTemplate(code);\n\nmodifier\n  .findByTag('div')\n  .removeAttribute('id')\n  .reduceAttribute('class', 'foo')\n  .regexpAttribute('v-if', /isTrue/g, 'show')\n  .extendAttribute('class', 'baz')\n  .setAttribute('data-foo', 'bar');\n\nconst modifiedCode = modifier.getModifiedCode();\nconsole.log(modifiedCode);\n\n// Output:\n// \u003cdiv class=\"baz\" v-show=\"true\" v-for=\"item in items\" data-foo=\"bar\"\u003e{{ item }}\u003c/div\u003e\n```\n## Modification of tags\n\n#### `removeElement()`\n\nRemoves the entire element (including its contents) currently selected by the class instance.\n\n#### `renameElement(newTagName: string)`\n\nRenames the tag name of the element currently selected by the class instance to `newTagName`.\n\n#### `insertBefore(html: string)`\n\nInserts the HTML code `html` before the element currently selected by the class instance.\n\n#### `insertAfter(html: string)`\n\nInserts the HTML code `html` after the element currently selected by the class instance.\n\n#### `unwrap()`\n\nRemoves the current element's tag but retains its contents.\n\n#### `getElementCode(): string`\n\nReturns the HTML code for the element currently selected by the class instance.\n\n#### `insertInside(html: string)`\n\nInserts the HTML code `html` inside the element currently selected by the class instance.\n\n### Usage\n\n```javascript\nimport { VueModifyTemplate } from \"@creativestyle/kombinator\";\n\nconst template = `\n  \u003ctemplate\u003e\n    \u003cdiv id=\"main\"\u003e\n      \u003cp\u003eHello world\u003c/p\u003e\n    \u003c/div\u003e\n  \u003c/template\u003e\n`;\n\nconst vm = new VueModifyTemplate();\nvm.fromTemplate(template)\n  .findByTag(\"div\")\n  .renameElement(\"section\")\n  .insertAfter(\"\u003cp\u003eNew element\u003c/p\u003e\")\n  .findByAttribute(\"id\")\n  .insertBefore('\u003cspan\u003e');\n  .insertAfter('\u003c/span\u003e\u003csome-component :foo=\"ok\"/\u003e');\nconst modifiedTemplate = vm.getTemplate();\nconsole.log(modifiedTemplate);\n\n// Output: \n// \u003ctemplate\u003e\n//   \u003cspan\u003e\u003csection id=\"main\"\u003e\n//     \u003cp\u003eHello world\u003c/p\u003e\u003cp\u003eNew element\u003c/p\u003e\n//   \u003c/section\u003e\u003c/span\u003e\u003csome-component :foo=\"ok\"/\u003e\n// \u003c/template\u003e\n```\n\n# API - GRAPHQL - functions you can use in mod files\n\n#### `fromString(content: string)`\n\nSets the graphql to be modified.\n\n#### `getString(): string`\n\nGets the modified graphql.\n\n## Finding field\n\nBefore modifying graphql you need to find proper field by define its path\n\n#### `findField(fieldPath: string[])`\n\nFinds the field based on path. Each array item is another nested field in graphql file.\n\n## Modification of fields\n\n#### `addFields(fieldsToAdd: string[])`\n\nAdds fields or spread fragments to active field.\n\n#### `removeFields(fieldsToRemove: string[])`\n\nRemove fields or spread fragments to active field.\n\n### Usage\n\n```javascript\nimport { GraphqlModificator } from \"@creativestyle/kombinator\";\n\nconst graphql = `\n  query HelloWorld {\n    queryName {\n      field\n    }\n  }\n`;\n\nconst gm = new GraphqlModificator();\ngm.fromString(graphql)\n  .findField(['queryName'])\n  .removeFields(['field'])\n  .addFields(['anotherField', '...someFragment']);\nconst modifiedTemplate = gm.getString();\nconsole.log(modifiedTemplate);\n\n// Output: \n// query HelloWorld {\n//   queryName {\n//     anotherField\n//     ...someFragment\n//   }\n// }\n```\n\n## Modification of variables\n\n#### `addVariable(variableName: string, variableType: string, hardcodedValue: string | null = null)`\n\nAdds variable assigned to a field. Dynamic variable by default. Hardcoded when `hardcodedValue` is provided.\n\n#### `removeVariable(variableName: string)`\n\nRemoves variable assigned to a field.\n\n### Usage\n\n```javascript\nimport { GraphqlModificator } from \"@creativestyle/kombinator\";\n\nconst graphql = `\n  query HelloWorld {\n    queryName {\n      field (sort: \"ASC\") {\n        nestedField\n      }\n    }\n  }\n`;\n\nconst gm = new GraphqlModificator();\ngm.fromString(graphql)\n  .findField(['queryName', 'field'])\n  .removeVariable('sort')\n  .findField(['queryName', 'field', 'nestedField'])\n  .addVariable('type', 'String')\nconst modifiedTemplate = gm.getString();\nconsole.log(modifiedTemplate);\n\n// Output: \n// query HelloWorld($type: String) {\n//   queryName {\n//     field {\n//       nestedField(type: $type)\n//     }\n//   }\n// }\n```\n\n# History associated with the name\n\nThe Polish word *kombinator* refers to a person who is crafty, resourceful, and skilled at finding solutions to problems through creative thinking, often using unconventional or cunning methods. It can have a slightly negative connotation and may be used to describe someone who is overly scheming or manipulative.\n\nDuring the Polish People's Republic (PRL) era, which lasted from 1947 to 1989, the country was under communist rule and faced many economic and social challenges. The government controlled most aspects of daily life, including education, media, and the economy.\n\nUnder such a system, being a *kombinator* was often necessary for survival. People had to find creative ways to obtain scarce goods and services, navigate the complex bureaucracy, and make ends meet. Many faced shortages of basic necessities, such as food, housing, and clothing, and had to resort to various strategies to acquire them.\n\nAdditionally, the government often interfered in people's personal lives, limiting their freedoms and restricting their ability to pursue their goals. Being a *kombinator* allowed individuals to find ways to circumvent these restrictions and pursue their interests and ambitions.\n\nTherefore, being a *kombinator* was often necessary during the PRL times to navigate the challenging economic and social conditions and to find ways to improve one's quality of life.\n\n# Other things\n\n## Known limitations\n\nThere are a few challenges that were not able to solve now. Feel free to contribute!\n- This file watches changes only on existing .mod.ts files, if you add .mod.ts file you need to restart your dev/watch process. \n\n### Why this plugin duplicates some features of other plugins\n\nThis plugin has some *minor functions* that can be achieved also by plugins like rollup-plugin-copy, but:\n- that plugin seems to be not maintained - many merge requests are not merged for months.\n- We need only a small subset of functionalities, and we do not want to pull a huge pile of dependencies.\n- At some point if those alternative plugins will be better maintained we will kick out this functionality from here.\n\nThe main purpose of this plugin is to deliver convenient API for automated modification/patching of the base project, not copying files around.\n\n### Chapeau bas to AI\n*Parts of this plugin its documentation and tests are written with the support of Chat GPT3.5*","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcreativestyle%2Fkombinator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcreativestyle%2Fkombinator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcreativestyle%2Fkombinator/lists"}