
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
logicful-templates
Advanced tools
A library allowing you to build HTML templates using React & JSX
A wrapper over React's renderToStaticMarkup for building logicful HTML templates, using JSX, transform hooks, and a hint of magic. 🧙
const Template = () => {
const employees = [
{ name: 'Petra', age: 33, title: 'Chief Template Creator' },
{ name: 'John', age: 31, title: 'Template Hacker' },
{ name: 'Jacky', age: 26, title: 'Senior Template Engineer' },
{ name: 'Boris', age: 28, title: 'Template Acquisition Expert' },
];
return (
<html lang='en'>
<head>
<title>An example JSX template</title>
<meta charSet='UTF-8' />
<script type='text/javascript' dangerouslySetInnerHTML={{ __html: 'alert("An in-your-face message!")' }} />
</head>
<body>
<div className='employees'>
{employees.map((employee) => (
<div key={employee.name} className='employee'>
<div className='name'>
{employee.name}, {employee.age}
</div>
<div className='title'>{employee.title}</div>
</div>
))}
</div>
</body>
</html>
);
};
would compile into
<!DOCTYPE html>
<html lang="en">
<head>
<title>An example JSX template</title>
<meta charset="UTF-8" />
<script type="text/javascript">
alert("An in-your-face message!");
</script>
</head>
<body>
<div class="employees">
<div class="employee">
<div class="name">Petra, 33</div>
<div class="title">Chief Template Creator</div>
</div>
<div class="employee">
<div class="name">John, 31</div>
<div class="title">Template Hacker</div>
</div>
<div class="employee">
<div class="name">Jacky, 26</div>
<div class="title">Senior Template Engineer</div>
</div>
<div class="employee">
<div class="name">Boris, 28</div>
<div class="title">Template Acquisition Expert</div>
</div>
</div>
</body>
</html>
Install the library using:
npm i logicful-templates
If you're using TypeScript, ensure you're using a version larger than 4.1 as we'll be using the jsxImportSource configuration to load the react JSX runtime.
Add the configuration below to your tsconfig.json:
{
"compilerOptions": {
"target": "ES6",
"jsx": "react-jsx",
"jsxImportSource": "react",
"module": "commonjs",
"esModuleInterop": true,
"skipLibCheck": true,
"strict": true
},
}
If you're using plain JavaScript we'll need Babel to transpile the JSX syntax into regular JS.
Add the configuration below to your Babel configuration file:
{
"presets": ["@babel/preset-env"],
"plugins": [
[
"@babel/plugin-transform-react-jsx",
{
"runtime": "automatic",
"importSource": "react"
}
]
]
}
compileTemplateCompiles a component and spits out an HTML string.
A function that compiles a React component into a plain HTML string. This is simply a wrapper over react-dom/server's renderToStaticMarkup function, allowing us to specify before and after compilation hooks, which also power the magic components.
Arguments
element: A ReactElement or a function returning one e.g. <Template /> or () => <Template />compileOptions: An object taking various compilation options:
Note: If you specify both addDocType: true and pretty: true the doctype will be formatted as <!DOCTYPE html>
import type { FunctionComponent } from 'react';
import LogicfulTemplates from 'logicful-templates';
const Template: FunctionComponent<{}> = () => (
<div className="greeting">Hello World</div>
);
const result = LogicfulTemplates.compileTemplate(<Template />);
// result: <div class="greeting">Hello World</div>
// Write output to a file
fs.writeFile("template.html", result, () => {});
registerHookRegister a before or after hook to execute during compilation.
For example:
addDocType to true registers an after hook, ensuring the output starts with <!doctype html>pretty to true registers an after hook, tidying up HTML before returning it.You can find the source of above hooks below:
Internally hooks are being used to make <Magic> and <Comment> components possible, they simply render a placeholder which is then replaced when the after hook is executed. You can check out their implementation below:
If you have a good idea for other hooks, PRs are more than welcome. 🚀
Registering a before hook
before hooks execute before calling renderToStaticMarkup, they aren't called with any parameters, but they allow you to execute any type of logic before compilation starts. For example:
LogicfulTemplates.registerHook('before', () => {
console.log('Starting compilation...');
});
Registering an after hook
after hooks execute after calling renderToStaticMarkup, they are called with the output of either that call, or the output of the previously executed after hook. For example:
LogicfulTemplates.registerHook('after', (html) => {
return html.toUpperCase();
});
Notes
LogicfulTemplates.compileTemplate multiple times and want to re-use the hooks, you'll have to register them again.<Magic> 🧙This component allows you to perform magic that normally wouldn't work when using React regularly.
| prop | type | description |
|---|---|---|
compileLater | boolean OR number | Allows you to compile the component after everything else is compiled. If a boolean is passed, it will be rendered after every other regular component. If you have multiple <Magic compileLater> components, the regular order is maintained (i.e. based on which one is executed first). If a number is passed, the number will be considered as the priority of when to render the component, priority 1 is considered higher than priority 99. |
children | ReactNode | React children |
dangerouslySetInnerHTML | { __html: string } | Sets this element's innerHTML (which becomes outerHTML as <Magic> itself does not render an element) |
hoist | boolean | Allows you to hoist its children up a level, i.e. you could set this element's outerHTML |
Compiling a component later
This could be useful when you need to execute a function only at the end of compilation.
import { Magic } from 'logicful-templates';
import type { FunctionComponent } from 'react';
const Template: FunctionComponent<{}> = () => {
return (
<html>
<head>
<meta charSet='utf-8' />
</head>
<body>
<div className="header">
<Magic compileLater>
{() => {
executeSomeFunctionLast();
const header = 'I am executed last';
return <h1>{header}</h1>
}}
</Magic>
</div>
<div className="content">
<p>Some text goes here.</p>
</div>
</body>
</html>
);
}
You can also specify a priority level by passing a number instead of true, the "compiler" will respect these values and execute the <Magic compileLater={number}> components in the correct order.
import { Magic } from 'logicful-templates';
import type { FunctionComponent } from 'react';
const Template: FunctionComponent<{}> = () => {
return (
<Magic compileLater={2}>
{() => {
executeSomeFunction();
return <h1>I am executed 2nd!</h1>
}}
</Magic>
<Magic compileLater={1}>
{() => {
executeSomeFunction();
return <h1>I am executed 1st!</h1>
}}
</Magic>
);
}
Notes
<Magic> component's children, but they allow you to execute functions. Passing regular children (i.e. React elements) will work fine.<Magic> component within a child render function of another <Magic> component, the priority number will only count for that level of <Magic> components. You normally wouldn't run into this scenario.Hoisting a component / setting outerHTML
By itself <Magic hoist> isn't very useful, but combined with the dangerouslySetInnerHTML prop you can technically set this element's outerHTML. This could be useful if you need to inline non-standard bits into the DOM, for example a stylesheet, custom elements, or HTML comments.
import { Magic } from 'logicful-templates';
import type { FunctionComponent } from 'react';
const Template: FunctionComponent<{}> = () => {
return (
<>
<Magic hoist dangerouslySetInnerHTML={{ __html: '<!-- A stylesheet below -->' }} />
<style>
<Magic
hoist
dangerouslySetInnerHTML={{
__html: `
body {
background-color: linen;
}
h1 {
color: maroon;
margin-left: 40px;
}
`,
}}
/>
</style>
</>
);
};
<!-- A stylesheet below -->
<style>
body {
background-color: linen;
}
h1 {
color: maroon;
margin-left: 40px;
}
</style>
<Custom>Provides flexibility by allowing you to specify what the output tag name for an element will be, while also allowing you to specify any type of prop (or attribute) on the element.
| prop | type | description |
|---|---|---|
tagName | string (lowercased) | A lowercased custom tag name for the custom element |
[key: string] | any | The <Custom> component accepts any type of props |
JSX.IntrinsicElements interface.For example:
import { Custom } from 'logicful-templates';
import type { FunctionComponent } from 'react'
const MyComponent: FunctionComponent<{}> = () => {
return (
<Custom
tagName='amp-img'
alt='A view of the sea'
src='/path/to/img'
width={900}
height={675}
layout='responsive'
/>
)
}
<amp-img
alt="a view of the sea"
src="/path/to/img"
width="900"
height="675"
layout="responsive"
></amp-img>
You could even write an abstraction over the <Custom> component to provide better type hinting for the next person consuming your component. For example:
import { Custom } from 'logicful-templates';
import type { FunctionComponent } from 'react';
interface AmpImgProps {
alt: string;
src: string;
width: number;
height: number;
layout: string;
}
const AmpImg: FunctionComponent<AmpImgProps> = (props) => {
return <Custom tagName='amp-img' {...props} />;
};
<Comment>Provides a way of adding HTML comments to the compiled output.
| prop | type | description |
|---|---|---|
children | string OR number OR boolean | The content of the HTML comment. |
import { Comment } from 'logicful-templates';
import type { FunctionComponent } from 'react';
const MyComponent: FunctionComponent<{}> = () => {
const input = 'World';
return (
<div>
<Comment>Hello {input}</Comment>
</div>
)
};
<div>
<!-- Hello World -->
</div>
You could easily extend the default JSX types by defining your own types in a separate typings.d.ts file.
ts-node to compile your templates, make sure to set { "ts-node": { "files": true } in your tsconfig.json, else you may run into TypeScript errors.export {}
declare global {
namespace JSX {
interface IntrinsicElements {
// Add a new element:
'custom-element': {
[key: string]: any;
};
// Or extend an existing React element:
html: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHtmlElement>, HTMLHtmlElement> & {
amp4email: ""
}
}
}
}
FAQs
A library allowing you to build HTML templates using React & JSX
We found that logicful-templates demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.