npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@item-enonic-types/lib-freemarker

v3.0.0

Published

Type definitions for lib-freemarker

Readme

FreeMarker for Enonic XP

This library lets you use Apache FreeMarker-templates with Enonic XP.

Build badge

Installation

To install this library you need to add a new dependency to your app's build.gradle file.

Gradle

repositories {
  maven { url "https://repo.itemtest.no/releases" }
  maven { url "https://repo.itemtest.no/snapshots" }
}

dependencies {
  include "no.item:lib-xp-freemarker:3.0.0-SNAPSHOT"
}

TypeScript

To update the version of enonic-types in package.json using npm, run the following command:

npm i -D @item-enonic-types/lib-freemarker

You can add the following changes to your tsconfig.json to get TypeScript-support.

{
  "compilerOptions": {
+   "baseUrl": "./",
+   "paths": {
+     "/lib/xp/*": ["./node_modules/@enonic-types/lib-*"],
+     "/lib/*": [ "./node_modules/@item-enonic-types/lib-*" ,"./src/main/resources/lib/*"],
+   }
  }
}

Add types for IntelliJ

If you are using IDEs from IntelliJ, you can get the correct type for the portal object by adding a file src/main/resources/freemarker_implicit.ftl with this content:

[#ftl]
[#-- @implicitly included --]
[#-- @ftlvariable name="portal" type="no.item.freemarker.FreemarkerPortalObject" --]

Configuration file

You can configure the FreeMarker settings by adding an XP_HOME/config/freemarker.properties file.

To preserve backwards compatibility in an existing project you can set the incompatible_improvements version like this:

incompatible_improvements=2.3.25

Developers should use the HTML Debug Exception Handler in their local development environments.

template_exception_handler=html_debug

[!CAUTION] Do not use the html_debug exception handler in production! It should only be used for development as it shows technical information about your system.

Usage

Render from template files

You can use resolve to get the ResourceKey of a template file in your application. Then you can pass in a data model to render that template.

import { render } from "/lib/freemarker";
import { getContent } from "/lib/xp/portal";
import type { Response } from "@enonic-types/core";

type FreeMarkerParams = {
  title: string;
  text: string | undefined;
}

const view = resolve("article.ftl");

export function get(): Response {
  const content = getContent()!;

  const model: FreeMarkerParams = {
    title: content.data.title,
    text: content.data.text,
  };

  return {
    body: render<FreeMarkerParams>(view, model),
  };
};

Render from inline strings

Alternatively you can use a string as the template.

import { render } from "/lib/freemarker";
import { getContent } from "/lib/xp/portal";
import type { Response } from "@enonic-types/core";

type FreeMarkerParams = {
  title: string;
  text: string | undefined;
  year: string;
}

// The FreeMarker template as a string. Notice how the $ needs to be escaped.
const view = `
    [#import "/site/utils/footer.ftl" as Footer]

    <h1>\${title}</h1>

    [#if text?has_content]
      <p>\${text}</p>
    [/#if]

    [@Footer.render year=year /]
  `;

export function get(): Response {
  const content = getContent()!;
  const virtualTemplateName = "my-inline-template.ftl";

  const model: FreeMarkerParams = {
    title: content.data.title,
    text: content.data.text,
    year: "2025"
  };

  return {
    body: render<FreeMarkerParams>(view, model, virtualTemplateName),
  };
};

The portal object

The following utility functions are made available in the portal object:

  • portal.localize()
  • portal.processHtml()

The portal-functions can be used within interpolations (${}). Example:

[#-- @ftlvariable name="nextPageUrl" type="String" --]

<a href="${nextPageUrl}">
  ${portal.localize("article.nextPage")}
</a>

[!WARNING] Always use the ?no_esc built-in with portal.processHtml(). It prevents auto-escaping the markup if an output format is set.

The portal.component directive

When rendering components from regions in pages and layouts you can use the portal.component directive.

[#-- @ftlvariable name="mainRegion" type="com.enonic.xp.region.Region" --]

<div class="my-layout">
  [#list mainRegion.components as component]
    [@portal.component path=component.path /]
  [/#list]
</div>

If you are creating a view to preview fragments, you can use the portal.component directive like this:

[@portal.component path="fragment" /]

Localization

This library will use the first locale it finds, checking in the following order:

| Order | Source of locale | Use case | |------:|---------------------------------------------------------------------------------------------|-----------------------| | 1 | The language field of the current content | Normal content | | 2 | The language field of the current site | E.g. the error page | | 3 | The end users "Accept-Language" that matches a supported language in the i18n directory | E.g. an admin tool | | 4 | Default to "en-US" | E.g. the main.js file |

So you can use the special variables ${.locale} and ${.lang} to access the "language tag" resolved based on the list above.

You also don't need to pass in a locale for portal.localize() unless you want a different locale then automatically selected locale.

<!doctype html>
<html lang="${.lang}">
  <body>
    <h1>The language tag is: ${.locale}</h1>

    <p>${portal.localize("article.text")}</p>
  </body>
</html>

If you need another locale to be used (han that of the current content), you can set it with the #setting directive.

[#-- Changes the `locale` to Norwegian for the remainder of the template.  --]
[#-- This will affect the `portal.localize()` and date formatting. --]
[#setting locale="no"]

[#-- Setting the `time_zone` to get the correct time when formatting dates  --]
[#setting time_zone="Europe/Oslo"]

Deploying

Building

To build the project, run the following command

enonic project build

You will find the jar-file at ./build/libs/lib-xp-freemarker-[version].jar

Deploying locally

Deploy locally for testing purposes:

./gradlew publishToMavenLocal

Deploy to Maven

./gradlew publish -P com.enonic.xp.app.production=true

Publish types to npm

npm publish
# npm publish --tag beta

Acknowledgments

This library was inspired by the lib-freemarker library by TINE IKT.