{"id":19475525,"url":"https://github.com/artdecocode/competent","last_synced_at":"2026-06-07T21:31:54.855Z","repository":{"id":135404376,"uuid":"182221754","full_name":"artdecocode/competent","owner":"artdecocode","description":"Extracts, Renders And Exports For Dynamic Render JSX Components From Within HTML.","archived":false,"fork":false,"pushed_at":"2019-12-08T22:30:40.000Z","size":1286,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-08T06:32:26.992Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://artd.eco","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/artdecocode.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","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":"2019-04-19T07:27:29.000Z","updated_at":"2021-01-24T23:18:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"f9b48366-0e9b-4d1d-b271-dfeed5ac3cf4","html_url":"https://github.com/artdecocode/competent","commit_stats":null,"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artdecocode%2Fcompetent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artdecocode%2Fcompetent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artdecocode%2Fcompetent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artdecocode%2Fcompetent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/artdecocode","download_url":"https://codeload.github.com/artdecocode/competent/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240699324,"owners_count":19843511,"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-11-10T19:33:25.926Z","updated_at":"2025-02-25T15:47:16.794Z","avatar_url":"https://github.com/artdecocode.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# competent\n\n[![npm version](https://badge.fury.io/js/competent.svg)](https://www.npmjs.com/package/competent)\n\n`competent` Extracts, Renders And Exports For Dynamic Render _JSX_ Components From Within HTML.\n\n```sh\nyarn add competent\n```\n\n## Table Of Contents\n\n- [Table Of Contents](#table-of-contents)\n- [API](#api)\n- [`competent(components, config=): !_restream.Rule`](#competentcomponents-objectstring-functionfunctionnew-preactcomponentconfig-config-_restreamrule)\n  * [`Config`](#type-config)\n  * [`Meta`](#type-meta)\n- [Additional Methods](#additional-methods)\n  * [`CompetentComponent`](#type-competentcomponent)\n- [`DEBUG=competent`](#debugcompetent)\n- [`makeComponentsScript(components, options=): string`](#makecomponentsscriptcomponents-arrayexportedcomponentoptions-makecompsconfig-string)\n  * [`MakeCompsConfig`](#type-makecompsconfig)\n  * [`IOOptions`](#type-iooptions)\n  * [`ExportedComponent`](#type-exportedcomponent)\n  * [Assets](#assets)\n  * [Intersection Observer](#intersection-observer)\n    * [Unrender](#unrender)\n- [`async writeAssets(path): void`](#async-writeassetspath-string-void)\n- [Known Limitations](#known-limitations)\n- [Who Uses _Competent_](#who-uses-competent)\n- [License \u0026 Copyright](#license--copyright)\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/0.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## API\n\nThe package is available by importing its default and named functions:\n\n```js\nimport competent, { makeComponentsScript, writeAssets } from 'competent'\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## \u003ccode\u003e\u003cins\u003ecompetent\u003c/ins\u003e(\u003c/code\u003e\u003csub\u003e\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`components: !Object\u003cstring, !Function|function(new: preact.Component)\u003e,`\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`config=: !Config,`\u003cbr/\u003e\u003c/sub\u003e\u003ccode\u003e): \u003ci\u003e!_restream.Rule\u003c/i\u003e\u003c/code\u003e\nCreates a rule for _Replaceable_ from the `restream` package that replaces HTML with rendered JSX components. The configuration object will be needed to export components, so that they can then be rendered on the page using JavaScript.\n\n - \u003ckbd\u003e\u003cstrong\u003ecomponents*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Object\u0026lt;string, (!Function \\| function(new: \u003ca href=\"https://github.com/externs/preact/wiki/Component\" title=\"A base class that is usually subclassed to create stateful Preact components.\"\u003epreact.Component\u003c/a\u003e))\u0026gt;\u003c/code\u003e\u003c/em\u003e: Components to extract from HTML and render using _Preact's_ server-side rendering. Can be either a functional stateless component, or a _Preact_ component constructor.\n - \u003ckbd\u003econfig\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-config\" title=\"Options for the program. All functions will be called with the Replaceable instance as their `this` context.\"\u003e!Config\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): Options for the program. All functions will be called with the _Replaceable_ instance as their `this` context.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003eExample Usage\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```html\n\u003chtml lang=\"en\"\u003e\n\n\u003cnpm-package style=\"background:red;\"\u003esplendid\u003c/npm-package\u003e\n\u003cnpm-package style=\"background:green;\"\u003e@a-la/jsx\u003c/npm-package\u003e\n\u003cnpm-package style=\"background:grey;\"\u003eunknown-package\u003c/npm-package\u003e\n\n\u003chello-world from=\"Art Deco\"\u003e\n  An example usage of competent.\n\u003c/hello-world\u003e\n\u003cfriends count=\"10\"/\u003e\n\u003c/html\u003e\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\nFor example, the above HTML page can be rendered with \u003cem\u003eCompetent\u003c/em\u003e by creating a \u003cem\u003eReplaceable\u003c/em\u003e rule:\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```jsx\nimport competent from 'competent'\nimport aqt from '@rqt/aqt'\nimport read from '@wrote/read'\nimport { Replaceable } from 'restream'\n\n/**\n * A standard JSX component.\n */\nconst HelloWorld = ({ from, children, competent: c }) =\u003e {\n  c.setPretty(false)\n  return (\u003cp\u003eHello World From {from}.{children}\u003c/p\u003e)\n}\n\n/**\n * A string component.\n */\nconst FriendCount = ({ count }) =\u003e {\n  return `You have ${count} friends.`\n}\n\n/**\n * An async component.\n */\nconst NpmPackage = async ({ style, children, competent: c }) =\u003e {\n  c.export()\n  let [pck] = children\n  pck = encodeURIComponent(pck)\n  const { statusCode, body } =\n    await aqt('https://registry.npmjs.com/' + pck)\n  if (statusCode == 404) throw new Error(`Package ${pck} not found.`)\n  const { name, versions, description } = body\n  const keys = Object.keys(versions)\n  const version = keys[keys.length - 1]\n  return \u003cdiv style={style}\u003e\n    \u003cspan className=\"name\"\u003e{name}\u003c/span\u003e\n    \u003cspan className=\"ver\"\u003e{version}\u003c/span\u003e\n    \u003cp\u003e{description}\u003c/p\u003e\n  \u003c/div\u003e\n}\n\nconst CompetentExample = async () =\u003e {\n  let i = 0\n  const exported = []\n  const file = await read('example/index.html')\n  const rule = competent({\n    'hello-world': HelloWorld,\n    'npm-package': NpmPackage,\n    'friends': FriendCount,\n  }, {\n    getId() {\n      i++\n      return `c${i}`\n    },\n    getProps(props, meta) {\n      meta.setPretty(true, 60)\n      return { ...props, competent: meta }\n    },\n    onFail(key, err) {\n      console.error('Component %s did not render:', key)\n      console.error(err.message)\n    },\n    markExported(key, id, props, children) {\n      exported.push({ key, id, props, children })\n    },\n  })\n  const r = new Replaceable(rule)\n  const res = await Replaceable.replace(r, file)\n  return { res, exported }\n}\n\nexport default CompetentExample\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\nThe output will contain rendered \u003cstrong\u003eJSX\u003c/strong\u003e.\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```html\n\u003chtml lang=\"en\"\u003e\n\n\u003cdiv style=\"background:red;\" id=\"c1\"\u003e\n  \u003cspan class=\"name\"\u003esplendid\u003c/span\u003e\n  \u003cspan class=\"ver\"\u003e1.16.2\u003c/span\u003e\n  \u003cp\u003e\n    Static Web Site Compiler That Uses Closure Compiler For JS Bundling And Closure Stylesheets For CSS optimisations. Supports JSX Syntax To Write Static Elements And Dynamic Preact Components.\n  \u003c/p\u003e\n\u003c/div\u003e\n\u003cdiv style=\"background:green;\" id=\"c2\"\u003e\n  \u003cspan class=\"name\"\u003e@a-la/jsx\u003c/span\u003e\n  \u003cspan class=\"ver\"\u003e1.6.0\u003c/span\u003e\n  \u003cp\u003eThe JSX Transform For ÀLaMode And Other Packages.\u003c/p\u003e\n\u003c/div\u003e\n\u003cnpm-package style=\"background:grey;\"\u003eunknown-package\u003c/npm-package\u003e\n\n\u003cp\u003eHello World From Art Deco.\n  An example usage of competent.\n\u003c/p\u003e\nYou have 10 friends.\n\u003c/html\u003e\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\nThe logging will be output to \u003ccode\u003estderr\u003c/code\u003e.\n\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nComponent npm-package did not render:\nPackage unknown-package not found.\nExported packages:\n[ { key: 'npm-package',\n    id: 'c1',\n    props: { style: 'background:red;' },\n    children: [ 'splendid' ] },\n  { key: 'npm-package',\n    id: 'c2',\n    props: { style: 'background:green;' },\n    children: [ '@a-la/jsx' ] } ]\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n__\u003ca name=\"type-config\"\u003e`Config`\u003c/a\u003e__: Options for the program. All functions will be called with the Replaceable instance as their `this` context.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n  \u003cth\u003eDefault\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eremoveOnError\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   If there was an error when rendering the component, controls whether the HTML should be be left on the page.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003egetId\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(key: string, props: !Props) =\u003e string\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The function which returns an \u003ccode\u003eid\u003c/code\u003e for the html element.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ekey*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: Component key.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eprops*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Props\u003c/code\u003e\u003c/em\u003e: Either HTML props, or properties overriden by \u003ccode\u003e.export\u003c/code\u003e call.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003egetProps\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(props: !Props, meta: \u003ca href=\"#type-meta\" title=\"Service methods for `competent`.\"\u003e!Meta\u003c/a\u003e, componentName: string, position: number) =\u003e Object\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The function which takes the parsed properties from HTML and competent's meta methods, and returns the properties object to be passed to the component. By default, returns the properties simply merged with \u003cem\u003emeta\u003c/em\u003e.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eprops*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Props\u003c/code\u003e\u003c/em\u003e: Properties.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003emeta*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-meta\" title=\"Service methods for `competent`.\"\u003e!Meta\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e: Meta properties.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ecomponentName*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The name of the component.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eposition*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003enumber\u003c/code\u003e\u003c/em\u003e: The position where match happened.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003emarkExported\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(key: string, id: string, props: !Props, children: !Array\u0026lt;string\u0026gt;) =\u003e ?\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   If the component called the \u003ccode\u003eexport\u003c/code\u003e meta method, this function will be called at the end of the replacement rule with its key, root id, properties and children as strings.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ekey*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: Component key.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eid*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The ID assigned manually either via the element's id attribute, or with the \u003ccode\u003egetId\u003c/code\u003e function automatically.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eprops*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Props\u003c/code\u003e\u003c/em\u003e: Component properties.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003echildren*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Array\u0026lt;string\u0026gt;\u003c/code\u003e\u003c/em\u003e: Component children.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eonSuccess\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(componentName: string, htmlProps: !Object\u0026lt;string, string\u0026gt;) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The callback at the end of a successful replacement with the component's key.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ecomponentName*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The element name, e.g., \u003ccode\u003emy-element\u003c/code\u003e.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ehtmlProps*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Object\u0026lt;string, string\u0026gt;\u003c/code\u003e\u003c/em\u003e: The properties with which the component was initialised.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eonFail\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(componentName: string, error: !Error, position: number, input: string) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The callback at the end of failed replacement with the component's key, error object, position number and the string which was fed to the rule.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ecomponentName*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The element name, e.g., \u003ccode\u003emy-element\u003c/code\u003e.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eerror*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Error\u003c/code\u003e\u003c/em\u003e: The error.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eposition*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003enumber\u003c/code\u003e\u003c/em\u003e: The position in the input text where element started.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003einput*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The input string.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003egetContext\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(childContext?: !Object, parent: { position: number, key: string }) =\u003e !Object\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The function to be called to get the properties to set on the child \u003cem\u003eReplaceable\u003c/em\u003e started to recursively replace inner HTML. This is needed if the root \u003cem\u003eReplaceable\u003c/em\u003e was assigned some properties that are referenced in components.\u003cbr/\u003e\n   \u003ckbd\u003echildContext\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Object\u003c/code\u003e\u003c/em\u003e (optional): The child context set by \u003ccode\u003emeta.setChildContext\u003c/code\u003e with \u003ccode\u003eundefined\u003c/code\u003e if not set.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eparent*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e{ position: number, key: string }\u003c/code\u003e\u003c/em\u003e: The info about the parent component.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003egetReplacements\u003c/td\u003e\n  \u003ctd colSpan=\"2\"\u003e\u003cem\u003e(componentName: string, recursiveRenderAgain: boolean) =\u003e !Array\u0026lt;!_restream.Rule\u0026gt;\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd colSpan=\"2\"\u003e\n   The function which should return the list of replacements for \u003ccode\u003erenderAgain\u003c/code\u003e method. By default, the initial rule generated by \u003cem\u003eCompetent\u003c/em\u003e is used. The first argument passed is the key, and the second argument is the value passed via the \u003ccode\u003erenderAgain\u003c/code\u003e, that is if the component might render recursively.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003ecomponentName*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: Component key.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003erecursiveRenderAgain*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/em\u003e: The value passed to \u003ccode\u003erenderAgain\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\nThe meta methods are usually used by the components in the `render`/`serverRender` methods, to control how the specific component instance should be rendered. If the `getProps` is not passed in the config, by default they will extend the HTML properties of the component.\n\n__\u003ca name=\"type-meta\"\u003e`Meta`\u003c/a\u003e__: Service methods for `competent`.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eexport*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(shouldExport?: boolean, props?: Object) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   When called, marks the component for export and adds an \u003ccode\u003eid\u003c/code\u003e if the root element of the hyper result did not have it. Individual instances can pass the \u003ccode\u003efalse\u003c/code\u003e value if they don't want to get exported.\u003cbr/\u003e\n   \u003ckbd\u003eshouldExport\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/em\u003e (optional): Whether to export the component. Default \u003ccode\u003etrue\u003c/code\u003e.\u003cbr/\u003e\n   \u003ckbd\u003eprops\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eObject\u003c/code\u003e\u003c/em\u003e (optional): Properties with which to export. If not passed, the same HTML props are used, otherwise overrides them. Undefined values will be removed.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eskipRender*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e() =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   If this method is called, \u003cem\u003eCompetent\u003c/em\u003e will return the original match without rendering the component into static HTML. This should be used together with \u003ccode\u003eexport\u003c/code\u003e to provide run-time dynamic browser rendering, without static HTML code generation.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003esetPretty*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(isPretty: boolean, lineLength?: number) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The function which controls whether to enable pretty printing, and the line width.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eisPretty*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/em\u003e: Whether to pretty print.\u003cbr/\u003e\n   \u003ckbd\u003elineLength\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003enumber\u003c/code\u003e\u003c/em\u003e (optional): Number of characters after which to wrap lines.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003eremoveLine*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(shouldRemove?: boolean) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   If the component rendered a falsy value (e.g., \u003ccode\u003enull\u003c/code\u003e, \u003ccode\u003e''\u003c/code\u003e), and the \u003ccode\u003eremoveLine\u003c/code\u003e was called, \u003cem\u003eCompetent\u003c/em\u003e will remove \u003ccode\u003e\\n___＜component＞\u003c/code\u003e. By default, this is switched off.\u003cbr/\u003e\n   \u003ckbd\u003eshouldRemove\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/em\u003e (optional): Sets whether the new line should be removed (default \u003ccode\u003etrue\u003c/code\u003e).\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003erenderAgain*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(doRender?: boolean, recursiveRender?: boolean) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   After rendering the component itself, the children by default are also rendered by spawning another \u003cem\u003eReplaceable\u003c/em\u003e stream. This is needed when a component might contain other components when rendered.\n   \u003cli\u003eWhen \u003ccode\u003erecursiveRender\u003c/code\u003e is set to false (default), the component key will be excluded from the rule to prevent recursion.\u003c/li\u003e\n   \u003cli\u003eNo recursion is allowed otherwise the program will get stuck, unless \u003ccode\u003e＜img/＞\u003c/code\u003e renders \u003ccode\u003e＜img＞\u003c/code\u003e (no \u003ccode\u003e/\u003c/code\u003e) for example.\u003c/li\u003e\n   \u003cli\u003eIf \u003ccode\u003egetReplacements\u003c/code\u003e was used to specify how to acquire the replacements for the new child \u003cem\u003eReplaceable\u003c/em\u003e stream, the \u003ccode\u003erecursiveRender\u003c/code\u003e arg will be pased to it.\u003cbr/\u003e\u003c/li\u003e\n   \u003ckbd\u003edoRender\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/em\u003e (optional): Whether to render component again to update its inner HTML. Default \u003ccode\u003etrue\u003c/code\u003e.\u003cbr/\u003e\n   \u003ckbd\u003erecursiveRender\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eboolean\u003c/code\u003e\u003c/em\u003e (optional): Whether to render element with the same name. Default \u003ccode\u003efalse\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cstrong\u003esetChildContext*\u003c/strong\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(context: !Object) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   JSX nodes are rendered breadth-first, meaning that siblings will receive the same \u003ccode\u003ethis\u003c/code\u003e context. If one of them modifies it, the another one will also pass the updated one to children, which is not always desirable. To create a fork context unique for children of sibling nodes, the child context can be set. It will be passed as an argument to \u003ccode\u003egetContext\u003c/code\u003e.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003econtext*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Object\u003c/code\u003e\u003c/em\u003e: The context specific for children of the node that calls \u003ccode\u003erenderAgain\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/2.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Additional Methods\n\n_Competent_ can work with additional API of components, in which case they must extend the _Preact_ class and implement these additional methods.\n\n__\u003ca name=\"type-competentcomponent\"\u003e`CompetentComponent`\u003c/a\u003e extends \u003ca title=\"A base class that is usually subclassed to create stateful Preact components.\" href=\"https://github.com/externs/preact/wiki/Component\"\u003e`preact.Component`\u003c/a\u003e__: A component could have an additional API understood by _Competent_.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003ckbd\u003estatic\u003c/kbd\u003e \u003cins\u003eload\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(callback: function(Error, !Object=): void, element: Element, props: !Object) =\u003e void\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   \u003ckbd\u003e\u003cstrong\u003ecallback*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003efunction(Error, !Object=): void\u003c/code\u003e\u003c/em\u003e: A method called by browser-side bundle prior to rendering of a component with a callback, e.g., to load necessary assets. The callback should be called by the component when the loading is done, after which the component will render. The second argument to the callback can be a map of properties that should also be passed to the component.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eelement*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003eElement\u003c/code\u003e\u003c/em\u003e: The element into which the component will be rendered.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003eprops*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Object\u003c/code\u003e\u003c/em\u003e: The properties that the component will receive.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eplain\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether this is a non-Preact component. This is required since Closure Compiler will compile classes into functions and the \u003ccode\u003e.isPrototypeOf\u003c/code\u003e won't wort to detect components that shouldn't be rendered with \u003cem\u003ePreact\u003c/em\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eserverRender\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(props?: \u003ca href=\"https://github.com/externs/preact/wiki/API#type-preactprops\"\u003e!preact.PreactProps\u003c/a\u003e) =\u003e (\u003ca href=\"https://github.com/externs/preact/wiki/API#type-acceptedchild\"\u003epreact.AcceptedChild\u003c/a\u003e | !Array\u0026lt;\u003ca href=\"https://github.com/externs/preact/wiki/API#type-acceptedchild\"\u003epreact.AcceptedChild\u003c/a\u003e\u0026gt;)\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   The same as render, but for the server only. Called by \u003cem\u003eComponent\u003c/em\u003e using \u003cem\u003eNodeJS\u003c/em\u003e runtime and not by \u003cem\u003ePreact\u003c/em\u003e in browser, therefore \u003cem\u003eNodeJS\u003c/em\u003e API could be used here.\u003cbr/\u003e\n   \u003ckbd\u003eprops\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"https://github.com/externs/preact/wiki/API#type-preactprops\"\u003e!preact.PreactProps\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): Component properties.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003efileRender\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(data: string, props?: \u003ca href=\"https://github.com/externs/preact/wiki/API#type-preactprops\"\u003e!preact.PreactProps\u003c/a\u003e) =\u003e !Promise\u0026lt;void\u0026gt;\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   When \u003ccode\u003eserverRender\u003c/code\u003e was specified, this method will also render the component using the standard \u003ccode\u003erender\u003c/code\u003e method, and return the output. The output could then be written by the implementation to the filesystem, e.g., saved as \u003ccode\u003ecomponent.html\u003c/code\u003e file which is then loaded in browser by \u003ccode\u003eload\u003c/code\u003e method.\u003cbr/\u003e\n   \u003ckbd\u003e\u003cstrong\u003edata*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003estring\u003c/code\u003e\u003c/em\u003e: The rendered component.\u003cbr/\u003e\n   \u003ckbd\u003eprops\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"https://github.com/externs/preact/wiki/API#type-preactprops\"\u003e!preact.PreactProps\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): Component properties.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\nFor example, we could implement a component that loads additional libraries and JSON data, and only renders when they are ready in the following way:\n\n```js\n/* eslint-env browser */\nimport loadScripts from '@lemuria/load-scripts'\nimport { Component } from 'preact'\n\nexport default class Menu extends Component {\n  /**\n   * @suppress {checkTypes}\n   */\n  static 'load'(callback) {\n    loadScripts([\n      'js/menu.json',\n      'snapsvg/dist/snap.svg-min.js',\n      'js/svg-anim.js',\n    ], (err, res) =\u003e {\n      if (err) return callback(err)\n      try {\n        const [json] = /** @type {!Array\u003cstring\u003e}*/ (res)\n        callback(null, { json: JSON.parse(json) })\n      } catch (er) {\n        callback(er)\n      }\n    })\n  }\n  serverRender({ splendid }) {\n    splendid.export()\n    splendid.addFile('js/menu.json')\n    splendid.addFile('js/svg-anim.js.map')\n    splendid.addFile('img/menu.svg')\n    splendid.polyfill('replace-with', true)\n    splendid.addExtern('node_modules://@artdeco/snapsvg-animator/types/externs.js')\n    return (\u003cdiv id=\"menu\" style=\"width:100%;\"\u003e\n      \u003cimg style=\"max-width:100%;\" alt=\"menu\" src=\"img/menu.svg\" /\u003e\n    \u003c/div\u003e)\n  }\n  render({ json }) {\n    const width = 1226\n    const height = 818\n\n    /** @type {!_snapsvgAnimator.SVGAnim} */\n    const comp = new window['SVGAnim'](json, width, height)\n    const n = comp.s.node\n    n.style['max-width'] = '100%'\n\n    return (\u003cdiv id=\"menu\" style=\"width:100%;\" ref={(el) =\u003e {\n      el.appendChild(n)\n    }}/\u003e)\n  }\n}\n```\n\nWhen compiling with _Closure Compiler_ (or _Depack_), the static methods need to be written in quotes like `static 'method'()`, otherwise Closure will rename them. The `checkTypes` warning should also be suppressed. The other way to do that would be to write static methods normally, but then [reassign them](https://github.com/google/closure-compiler/issues/3447): `Example['staticMethod'] = Example.staticMethod;`\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/3.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## `DEBUG=competent`\n\nWhen the `DEBUG` env variable is set to _competent_, the program will print some debug information, e.g.,\n\n```\n2019-12-01T05:14:49.257Z competent render npm-package\n2019-12-01T05:14:49.303Z competent render npm-package\n2019-12-01T05:14:49.311Z competent render npm-package\n2019-12-01T05:14:49.313Z competent render hello-world\n2019-12-01T05:14:49.319Z competent render friends\n```\n\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/4.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## \u003ccode\u003e\u003cins\u003emakeComponentsScript\u003c/ins\u003e(\u003c/code\u003e\u003csub\u003e\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`components: !Array\u003c!ExportedComponent\u003e,`\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`options=: MakeCompsConfig,`\u003cbr/\u003e\u003c/sub\u003e\u003ccode\u003e): \u003ci\u003estring\u003c/i\u003e\u003c/code\u003e\nBased on the exported components that were detected using the rule, generates a script for the web browser to dynamically render them with _Preact_.\n\n - \u003ckbd\u003e\u003cstrong\u003ecomponents*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e!Array\u0026lt;\u003ca href=\"#type-exportedcomponent\" title=\"An exported component.\"\u003e!ExportedComponent\u003c/a\u003e\u0026gt;\u003c/code\u003e\u003c/em\u003e: All components that were made exportable by the rule.\n - \u003ckbd\u003eoptions\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-makecompsconfig\" title=\"The options for make components script.\"\u003eMakeCompsConfig\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): The options for the make components script.\n\n__\u003ca name=\"type-makecompsconfig\"\u003e`MakeCompsConfig`\u003c/a\u003e__: The options for make components script.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n  \u003cth\u003eDefault\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003emap\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e!Object\u0026lt;string, !Array\u0026lt;?string\u0026gt;\u0026gt;\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nThe map with locations from where components should be imported, e.g.,\n```js\n{\n  '../components/named.jsx': [null, 'named-component'],\n  '../components/default.jsx': ['default-component'],\n}\n```\nThe default export must come first in the array.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eio\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(boolean | \u003ca href=\"#type-iooptions\" title=\"Options for the observer.\"\u003e!IOOptions\u003c/a\u003e)\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether to use an \u003cem\u003eIntersectionObserver\u003c/em\u003e to render elements. If an object is given, it will be passed to the IO constructor, otherwise the default options are used (\u003ccode\u003erootMargin: '76px'\u003c/code\u003e).\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003epreact\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(string | boolean)\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003epreact\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether any of the components are \u003cem\u003ePreact\u003c/em\u003e components.\n   Only pass \u003ccode\u003efalse\u003c/code\u003e when you know for sure that all components implement \u003ccode\u003eplain\u003c/code\u003e getter.\n   A string can be passed to name the package from which to import the \u003ccode\u003eh\u003c/code\u003e pragma (e.g., \u003ccode\u003e@externs/preact\u003c/code\u003e).\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eprops\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e!Object\u0026lt;string, *\u0026gt;\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e-\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Shared properties made available for each component in addition to its own properties.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eincludeH\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Include \u003ccode\u003eimport { h } from 'preact'\u003c/code\u003e on top of the file.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003eexternalAssets\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(boolean | string)\u003c/em\u003e\u003c/td\u003e\n  \u003ctd rowSpan=\"3\"\u003e\u003ccode\u003efalse\u003c/code\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether the library functions should be required from a separate file, \u003ccode\u003e./__competent-lib\u003c/code\u003e. Works together with \u003ccode\u003ewriteAssets\u003c/code\u003e and is useful when generating more than one script. The relative path can be passed as a string, e.g., \u003ccode\u003e..\u003c/code\u003e will make \u003ccode\u003e../__competent-lib\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n\n__\u003ca name=\"type-iooptions\"\u003e`IOOptions`\u003c/a\u003e extends `IntersectionObserverInit`__: Options for the observer.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003elog\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003eboolean\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Whether to print a message to console when a component is rendered.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n__\u003ca name=\"type-exportedcomponent\"\u003e`ExportedComponent`\u003c/a\u003e__: An exported component.\n\n\n|     Name      |             Type              |                     Description                     |\n| ------------- | ----------------------------- | --------------------------------------------------- |\n| __key*__      | \u003cem\u003estring\u003c/em\u003e               | The name of the component as passed to _Competent_. |\n| __id*__       | \u003cem\u003estring\u003c/em\u003e               | The ID where the component should render.           |\n| __props*__    | \u003cem\u003e!Object\u003c/em\u003e              | Properties of the component.                        |\n| __children*__ | \u003cem\u003e!Array\u0026lt;string\u0026gt;\u003c/em\u003e | Children as strings.                                |\n\n```js\nimport CompetentExample from './'\nimport { makeComponentsScript } from 'competent'\n\n(async () =\u003e {\n  const { exported } = await CompetentExample()\n  console.log(makeComponentsScript(exported, {\n    map: {\n      '../components/npm': ['npm-package'],\n      // default first then named\n      '../components': ['hello-world', 'friends'],\n    },\n  }))\n})()\n```\n```js\nimport { Component, render } from 'preact'\nimport NpmPackage from '../components/npm'\n\nconst __components = {\n  'npm-package': NpmPackage,\n}\n\nfunction init(id, key) {\n  const el = document.getElementById(id)\n  if (!el) {\n    console.warn('Parent element for component %s with id %s not found', key, id)\n    return {}\n  }\n  const parent = el.parentElement\n  if (!parent) {\n    console.warn('Parent of element for component %s with id %s not found', key, id)\n    return {}\n  }\n  return { parent, el  }\n}\n\nclass PreactProxy {\n  /**\n   * Create a new proxy.\n   * @param {Element} el\n   * @param {Element} parent\n   * @param {*} Comp\n   * @param {*} preact\n   */\n  constructor(el, parent, Comp, preact) {\n    this.preact = preact\n    this.Comp = Comp\n    this.el = el\n    this.parent = parent\n    /**\n     * A Preact instance.\n     */\n    this.comp = null\n    this.unrender = null\n  }\n  render({ children, ...props }) {\n    if (!this.comp) {\n      this.preact.render(this.preact.h(this.Comp, props, children), this.parent, this.el)\n      const comp = this.el['_component']\n      if (comp.componentWillUnmount) {\n        this.unrender = () =\u003e {\n          comp.componentWillUnmount()\n        }\n      }\n      this.comp = comp\n    } else {\n      if (this.comp.componentDidMount) this.comp.componentDidMount()\n      this.comp.forceUpdate()\n    }\n  }\n}\n\nfunction start(meta, Comp, comp, el, parent, props, children, preact) {\n  const isPlain = meta.plain\n  if (!comp \u0026\u0026 isPlain) {\n    comp = new Comp(el, parent)\n  } else if (!comp) {\n    comp = new PreactProxy(el, parent, Comp, preact)\n  }\n  const r = () =\u003e {\n    comp.render({ ...props, children })\n    meta.instance = comp\n  }\n  if (Comp.load) {\n    Comp.load((err, data) =\u003e {\n      if (data) Object.assign(props, data)\n      if (!err) r()\n      else console.warn(err)\n    }, el, props)\n  } else r()\n  return comp\n}\n\n/** @type {!Array\u003c!preact.PreactProps\u003e} */\nconst meta = [{\n  key: 'npm-package',\n  id: 'c1',\n  props: {\n    style: 'background:green;',\n  },\n  children: [\"@a-la/jsx\"],\n},\n{\n  key: 'npm-package',\n  id: 'c2',\n  props: {\n    style: 'background:red;',\n  },\n  children: [\"splendid\"],\n}]\nmeta.forEach(({ key, id, props = {}, children = [] }) =\u003e {\n  const Comp = __components[key]\n  const plain = Comp.plain || (/^\\s*class\\s+/.test(Comp.toString()) \u0026\u0026 !Component.isPrototypeOf(Comp))\n\n  const ids = id.split(',')\n  ids.forEach((Id) =\u003e {\n    const { parent, el } = init(Id, key)\n    if (!el) return\n    const renderMeta = /** @type {_competent.RenderMeta} */ ({ key, id: Id, plain })\n    let comp\n    comp = start(renderMeta, Comp, comp, el, parent, props, children, { render, Component, h })\n  })\n})\n```\n\nThere are _Plain_ and _Preact_ components. By default, the assumption is that there are _Preact_ components in the map passed in options. When `preact` option is set to false, only plain logic is enabled, skipping the _Preact_ imports and externs.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/5.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### Assets\n\nBy default, the lib functions will be embedded into the source code. To place them in separate files for reuse across multiple generated scripts, the `externalAssets` option is used together with `writeAssets` method.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/6.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### Intersection Observer\n\nCompetent can generate code that will utilise the _IntesectionObserver_ browser capability to detect when the element into which the components needs to be rendered comes into view, and only mount it at that point. This will only work when _IntesectionObserver_ is present either natively, or via a polyfill. When the `io` argument value is passed as an object rather than boolean, it will be serialised, e.g., `{ rootMargin: '0 0 76px 0' }`.\n\n```js\nimport CompetentExample from './'\nimport { makeComponentsScript } from 'competent'\n\n(async () =\u003e {\n  const { exported } = await CompetentExample()\n  console.log(\n    makeComponentsScript(exported, {\n      map: {\n        '../components/npm': ['npm-package'],\n        '../components': ['hello-world', 'friends'],\n      },\n      io: { threshold: 10, rootMargin: '50px' },\n      externalAssets: true,\n    })\n  )\n})()\n```\n```js\nimport { Component, render } from 'preact'\nimport { makeIo, init, start } from './__competent-lib'\nimport NpmPackage from '../components/npm'\n\nconst __components = {\n  'npm-package': NpmPackage,\n}\n\nconst io = makeIo({ threshold: 10, rootMargin: \"50px\" })\n\n/** @type {!Array\u003c!preact.PreactProps\u003e} */\nconst meta = [{\n  key: 'npm-package',\n  id: 'c1',\n  props: {\n    style: 'background:green;',\n  },\n  children: [\"@a-la/jsx\"],\n},\n{\n  key: 'npm-package',\n  id: 'c2',\n  props: {\n    style: 'background:red;',\n  },\n  children: [\"splendid\"],\n}]\nmeta.forEach(({ key, id, props = {}, children = [] }) =\u003e {\n  const Comp = __components[key]\n  const plain = Comp.plain || (/^\\s*class\\s+/.test(Comp.toString()) \u0026\u0026 !Component.isPrototypeOf(Comp))\n\n  const ids = id.split(',')\n  ids.forEach((Id) =\u003e {\n    const { parent, el } = init(Id, key)\n    if (!el) return\n    const renderMeta = /** @type {_competent.RenderMeta} */ ({ key, id: Id, plain })\n    let comp\n    el.render = () =\u003e {\n      comp = start(renderMeta, Comp, comp, el, parent, props, children, { render, Component, h })\n      return comp\n    }\n    el.render.meta = renderMeta\n    io.observe(el)\n  })\n})\n```\n\n#### Unrender\n\nWhen a plain component implements an `unrender` method, _Competent_ will call it when the component is no longer intersecting. Components that don't provide the `unrender` method won't be destroyed.\n\nWhen it comes to _Preact_ component, the same applies, but the `unrender` method is called `componentWillUnmount`. Here, an instance will get a chance to remove event listeners and tidy up so that the page keeps performant. The component won't actually be unmounted, because that requires removing the element into which it is rendered from DOM, which can be inefficient and would result in page jumps. Instead, the `componentWillUnmount` will be called and the component should change its state so that it becomes invisible or a similar measure. Whenever the component comes back into view, its `componentDidMount` will be called again, and an update scheduled.\n\n\u003cimg src=\"docs/appshot.gif\" alt=\"unrender method implementation\"\u003e\n\n\n```js\n/**\n * Example implementation of Preact unrender.\n */\nexport default class Test extends Component {\n  constructor() {\n    super()\n    this.state.ellipsis = false\n  }\n  componentDidMount() {\n    this.setState({ ellipsis: true })\n  }\n  componentWillUnmount() {\n    this.setState({ ellipsis: false })\n  }\n  render() {\n    return (\u003cspan\u003eHello World{this.state.ellipsis \u0026\u0026 \u003cEllipsis /\u003e}\u003c/span\u003e)\n  }\n}\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/7.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## \u003ccode\u003easync \u003cins\u003ewriteAssets\u003c/ins\u003e(\u003c/code\u003e\u003csub\u003e\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`path: string,`\u003cbr/\u003e\u003c/sub\u003e\u003ccode\u003e): \u003ci\u003evoid\u003c/i\u003e\u003c/code\u003e\n - \u003ckbd\u003e\u003cstrong\u003epath*\u003c/strong\u003e\u003c/kbd\u003e \u003cem\u003e`string`\u003c/em\u003e: The folder where to create the `__competent-lib.js` file, when the `externalAssets` option is passed to _makeComps_.\n\n```js\nimport { writeAssets } from 'competent'\n\n(async () =\u003e {\n  await writeAssets('example')\n})()\n```\n\n\n\n```js\nexport function init(id, key) {\n  const el = document.getElementById(id)\n  if (!el) {\n    console.warn('Parent element for component %s with id %s not found', key, id)\n    return {}\n  }\n  const parent = el.parentElement\n  if (!parent) {\n    console.warn('Parent of element for component %s with id %s not found', key, id)\n    return {}\n  }\n  return { parent, el  }\n}\n\nexport function makeIo(options = {}) {\n  const { rootMargin = '76px', log = true, ...rest } = options\n  const io = new IntersectionObserver((entries) =\u003e {\n    entries.forEach(({ target, isIntersecting }) =\u003e {\n      /**\n       * @type {_competent.RenderMeta}\n       */\n      const meta = target.render.meta\n      const { key, id, plain } = meta\n      if (isIntersecting) {\n        if (log)\n          console.warn('🏗 Rendering%s component %s into the element %s',\n            !plain ? ' Preact' : '', key, id, target)\n        try {\n          const instance = target.render()\n          if (instance \u0026\u0026 !instance.unrender) io.unobserve(target) // plain\n        } catch (err) {\n          if (log) console.warn(err)\n        }\n      } else if (meta.instance) {\n        if (log)\n          console.warn('💨 Unrendering%s component %s from the element %s',\n            !plain ? ' Preact' : '', key, id, target)\n        meta.instance.unrender()\n      }\n    })\n  }, { rootMargin, ...rest })\n  return io\n}\n\n/**\n * @param {_competent.RenderMeta} meta\n * @param {function(new:_competent.PlainComponent, Element, Element)} Comp\n */\nexport function startPlain(meta, Comp, comp, el, parent, props, children) {\n  if (!comp) comp = new Comp(el, parent)\n  const r = () =\u003e {\n    comp.render({ ...props, children })\n    meta.instance = comp\n  }\n  if (Comp.load) { // \u0026!comp\n    Comp.load((err, data) =\u003e {\n      if (data) Object.assign(props, data)\n      if (!err) r()\n      else console.warn(err)\n    }, el, props)\n  } else r()\n  return comp\n}\n\n/**\n * This is the class to provide render and unrender methods via standard API\n * common for Preact and Plain components.\n */\nclass PreactProxy {\n  /**\n   * Create a new proxy.\n   * @param {Element} el\n   * @param {Element} parent\n   * @param {*} Comp\n   * @param {*} preact\n   */\n  constructor(el, parent, Comp, preact) {\n    this.preact = preact\n    this.Comp = Comp\n    this.el = el\n    this.parent = parent\n    /**\n     * A Preact instance.\n     */\n    this.comp = null\n  }\n  render({ children, ...props }) {\n    if (!this.comp) {\n      this.preact.render(this.preact.h(this.Comp, props, children), this.parent, this.el)\n      const comp = this.el['_component']\n      if (comp.componentWillUnmount) {\n        this.unrender = () =\u003e {\n          comp.componentWillUnmount()\n        }\n      }\n      this.comp = comp\n    } else {\n      if (this.comp.componentDidMount) this.comp.componentDidMount()\n      this.comp.forceUpdate()\n    }\n  }\n}\n\n/**\n * @param {_competent.RenderMeta} meta\n */\nexport function start(meta, Comp, comp, el, parent, props, children, preact) {\n  const isPlain = meta.plain\n  if (!comp \u0026\u0026 isPlain) {\n    comp = new Comp(el, parent)\n  } else if (!comp) {\n    comp = new PreactProxy(el, parent, Comp, preact)\n  }\n  const r = () =\u003e {\n    comp.render({ ...props, children })\n    meta.instance = comp\n  }\n  if (Comp.load) {\n    Comp.load((err, data) =\u003e {\n      if (data) Object.assign(props, data)\n      if (!err) r()\n      else console.warn(err)\n    }, el, props)\n  } else r()\n  return comp\n}\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/8.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Known Limitations\n\nCurrently, it is not possible to match nested components.\n\n```js\n\u003cComponent\u003e\n  \u003cComponent example /\u003e\n  \u003cComponent test boolean\u003e\u003c/Component\u003e\n\u003c/Component\u003e\n```\n\n```html\n\u003ccomponent-processed /\u003e\n\u003c/component\u003e\n```\n\nThis is because the RegExp is not capable of doing that sort of thing, because it cannot balance matches, however when _Competent_ switches to a non-regexp parser it will become possible.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/9.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Who Uses _Competent_\n\n_Competent_ is used by:\n\n- [_Documentary_](https://artdecocode.com/documentary/): a documentation pre-processor that supports JSX for reusable components when generating `README` files.\n- [_Splendid_](https://github.com/artdecocode/splendid): a static website generator that allows to write JSX components in HTML, and bundles JS compiler with _Google Closure Compiler_ to also dynamically render them on the page.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/10.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## License \u0026 Copyright\n\n```\nDual licensed under limited Affero GPL and a commercial license.\nThe limitations on the standard AGPL text are as follows:\n\n- Within the UK: no commercial use is allowed until the\n  organisation signs up. After: see below. Sign up at:\n  https://www.technation.sucks/license/.\n- Across the globe: Affero GPL. No companies affiliated\n  with Tech Nation in any way (e.g., participation in\n  their programs, being part of their network, hiring\n  their directors), are allowed to use the software\n  unless they sign up.\n\n(c) 2019 Art Deco Code\n\nThe COPYING file contains the full text of the public license.\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\nThe Affero GPL 101 (only dev-dep: commercial OK), click to expand.\n\u003c/summary\u003e\n\n- You can use _Competent_ as dev dependency to render HTML code, and the components invocation script in any personal/commercial project. For example, you can build a website for your client by writing a script that uses *Competent* to generate HTML.\n- However, you cannot use the software as part of an online service such as a cloud website builder because then it's not a dev dependency that you run to generate HTML of your website once, but a runtime-linking prod dependency.\n- In other words, when you need to link to the package during runtime, i.e., use it as a standard dependency in your own software (even if bundled), you're creating an extension of the main program with this plugin, and thus have to release your source code under _AGPL_, or obtain the commercial license.\n- Contact `license@artd.eco` for more information.\n\u003c/details\u003e\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://artd.eco\"\u003e\n        \u003cimg width=\"100\" src=\"https://raw.githubusercontent.com/wrote/wrote/master/images/artdeco.png\"\n          alt=\"Art Deco\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e© \u003ca href=\"https://artd.eco\"\u003eArt Deco\u003c/a\u003e   2019\u003c/th\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://www.technation.sucks\" title=\"Tech Nation Visa\"\u003e\n        \u003cimg width=\"100\" src=\"https://raw.githubusercontent.com/idiocc/cookies/master/wiki/arch4.jpg\"\n          alt=\"Tech Nation Visa\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e\u003ca href=\"https://www.technation.sucks\"\u003eTech Nation Visa Sucks\u003c/a\u003e\u003c/th\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/-1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartdecocode%2Fcompetent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartdecocode%2Fcompetent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartdecocode%2Fcompetent/lists"}