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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@akb2/layouts-generator

v1.11.1

Published

`Layouts Generator` - это мини-фреймворк для генерации простых HTML страниц.

Downloads

1,942

Readme

Layouts Generator

Layouts Generator - это мини-фреймворк для генерации простых HTML страниц.

Ключевые оссобенности

Установка и входная точка

Вход *.page.ts (пример src/pages/home/home.page.ts):

import { Page, OnInit, OnViewInit } from "@akb2/layouts-generator/core";

@Page({
  templateSrc: "./home.page.pug",
  styleSrc: "./home.page.scss"
})
export class HomePage implements OnInit, OnViewInit {
  constructor() {
    // Вызывается при формировании DOM
  }

  onInit(): void {
    // Логика и подписки
    // Безопасно вызывается после DOMContentLoaded
  }

  onViewInit(): void {
    // Доступены корневой элемент @RootElement и @Child
    // После window.load
  }
}

Компоненты страниц @Page

  • Декоратор: @Page({ templateSrc, styleSrc?, imports?, isLayout? });
  • templateSrc Файлы шаблонов: .page.pug;
  • styleSrc Файлы стилей: .page.scss;
  • isLayout Отметка, что страница содержит структуру HTML документа;
  • imports Перечисление классов компонентов, используемых в шаблоне;
  • Жизненный цикл: constructoronInit()onViewInit();

onInit() вешается на DOMContentLoaded (или микро-задачу, если документ уже загружен).

onViewInit() вызывается после window.load, внутри доступны ссылки на DOM элементы с помощью @RootElement и @Child.

isLayout - В цепочке зависимостей может быть только страница со значением TRUE или только один компонент.

Компоненты @Component и свойства @Define

import { Component, Define, OnInit } from "@akb2/layouts-generator/core";

@Component({
  selector: "app-card",
  templateSrc: "./card.component.pug",
  styleSrc: "./card.component.scss"
})
export class CardComponent implements OnInit {
  // значение по умолчанию — это инициализатор поля
  @Define() title = "Заголовок по умолчанию";
  @Define() dense = false;

  onInit(): void {
    // Инициализация компонента
  }
}

Для передачи данных в компонент для присвоения @Define свойствам используйте объектный синтаксис @{ ... }, помечая объект символом @.

Использование в разметке (на странице/в другом компоненте):

div
  - dense = true
  app-card@{ title: "Профиль", dense }

Примечание по @Define: помечает публичные поля класса как входные параметры компонента. Значение по умолчанию задаётся обычным инициализатором поля (см. title = "...").

Статичные свойства @Static

Внутри компонентов и страниц вы можете использовать декоратор @Static, чтобы использовать эти переменные и значения при генерации проекта. Эти свойства не могут быть изменены в рантайме, они используются только при генерации. Ключевое отличие данного декоратора от @Define в том, что @Static не является входящим параметром и не может переопределяться через пропсы.

Обычные свойства класса

Если создать свойства без какого либо декоратора, тогда эти свойства можно будет изменять в рантайме в рамках хуков жизненного цикла. Нельзя использовать такие свойства в качестве значений атрибутов, только в виде видимого текста.

Общие свойства @Expose

Это особый хук, позволяет объединить в себе все свойства @Static и обычных свойств класса. Это позволяет задать отображаемое значение при компиляции, а так же обновлять его в дальнейшем динамически в рамках хуков жизненного цикла. Так же здесь применимы все те же ограничения, что и в указанных свойствах.

Ссылка на DOM узел экземпляра компонента @RootElement

После запуска приложения на клиенте в поле класса, помеченное декоратором @RootElement фреймворк подставит DOM узел, соответствующий текущему экземпляру компонента. Для страницы или компонента с isLayout: true - ссылка на html тег страницы, для остальных ссылка на собственный DOM элемент. Значение в переменной появляется в момент вызова хука onViewInit и доступен только внутри него.

Связывание DOM элементов с контроллером @Child

Если у вас появляется необходимость в ссылке на конкретный DOM элемент внутри вашего компонента или страницы, то эту задачу решает декоратор @Child. Единственный аргумент декоратора - это строка-идентификатор DOM елемента. Идентификатор может состоять из цифр, букв, тире и подчеркивания, первый символ обязательно должен быть буквой. В шаблоне для указания идентификатора элементу воспользуйтесь специальным синтаксисом *id. По аналогии с @RootElement ссылка присваивается на хуке onViewInit.

import { Component, Child, Define, OnInit, OnViewInit } from "@akb2/layouts-generator/core";

@Component({
  selector: "app-title",
  templateSrc: "./title.component.pug",
  styleSrc: "./title.component.scss"
})
export class TitleComponent implements OnInit, OnViewInit {
  @Child("root_elm")
  rootElement: HTMLDivElement | undefined;

  @Child("id-element")
  subTitleElement: HTMLSpanElement | undefined;

  @Define()
  title = "My title";

  @Define()
  subTitle = "My sub title";

  constructor() {
    console.log(this.rootElement); // undefined
    console.log(this.subTitleElement); // undefined
  }

  onInit(): void {
    console.log(this.rootElement); // undefined
    console.log(this.subTitleElement); // undefined
  }

  onViewInit(): void {
    console.log(this.rootElement); // <div>...</div>
    console.log(this.subTitleElement); // <span>My sub title</span>
  }
}
//- title.component.pug
*root_elm
  = title
  span*id-element= subTitle

Структура HTML документа. Поле isLayout

Декораторы @Page и @Component имеют необязательное поле isLayout. Необходимо указать его либо на странице, либо в одном из дочерних компонентов. В цепочке зависимостей @Page -> @Component's -> ... -> @Component может быть только одна сущность с isLayout со значением TRUE.

Этим полем вы указываете фреймворку, кто отвечает за отрисовку базового HTML документа: сама страница или специальный компонент.

Если за отрисовку документа отвечает компонент, то ему доступны все свойства компонента:

Единственное отличие, что такой компонент не будет иметь в документе своего тега, а декоратор @RootElement устанавливает document в назначенное свойство.

Проекция контента

В компонент по мимо пропсов можно передать шаблон через проекцию контента. Когда разрабатываете шаблон компонента укажите специальный тег g-content, а при вызове компонента в другом шаблоне просто укажите ему содержимое. Это содержимое отрисуется внутри компонента.

Пример:

//- children.component.pug
h1 Some title

div
  .children-div Children content
  g-content
//- parent.page.pug или parent.component.pug
#app
  app-children
    .parent-div Parent content
<div id="app">
  <app-children>
    <h1>Some title</h1>
    <div>
      <div class="children-div">Children content</div>
      <div class="parent-div">Parent content</div>
    </div>
  <app-children>
</div>

Инкапсуляция

Компоненты имеют инкапсуляцию стилей, поэтому стили одного компонента никак не повлияют на прочие стили.

В SCSS стилях можете использовать обычный SCSS подход, все что привносит фреймворк - это селектор :host. Вы можете писать стили и без него, они прекрасно применятся только к этому компоненту. Данный селектор вам понадобится, если захотите стилизовать саму обертку компонента, тег, указанный в selector свойстве декоратора @Component.

Хуки жизненного цикла

  • constructor - Cоздание экземпляра;
  • onBeforeStaticAttach() - Перед привязкой данных в PUG шаблон
  • onDefine() - После присвоения значений в @Define свойства
  • onInit() - После готовности DOM (безопасно для подписок/инициализации);
  • onViewInit() - После полной загрузки окна, с корневым элементом;

Не забудьте заимплементить класс компонента или страницы соответствующим интерфейсом хука, ниже список соответствия:

  • OnBeforeStaticAttach - onBeforeStaticAttach()
  • OnDefine - onDefine()
  • OnInit - onInit()
  • OnViewInit - onViewInit()

Структура компонентов

src/
  components/
    card/
      card.component.ts     // Класс + @Component
      card.component.pug    // Шаблон
      card.component.scss   // Стили
  pages/
    home/
      home.page.ts          // Класс + @Page
      home.page.pug         // Шаблон
      home.page.scss        // Стили

Фреймворк следит за **/*.ts и указанных в декораторе путях в папках pages и components.

Конфигурация Vite через gBuilder

Создайте vite.config.ts:

import { defineConfig } from "vite";
import { gBuilder } from "@akb2/layouts-generator/builder";

export default defineConfig(
  gBuilder({
    // Путь к компонентам страниц
    pagesPath: "./src/pages",
    // Путь к компонентам
    componentsPath: "./src/components",
    // Путь к выходной папке
    distSrc: ".dist",
    // Корень проекта
    root: ".",
    // Путь для открытия браузера в DEV режиме
    open: "/.dist/page-home/index.html",
    // Минификация FALSE или "terser"
    minify: false,
    // Каталог для отслеживания изменений
    watchDir: "./src",
  })
);

Что делает gBuilder:

  • Автоматически собирает точки входа: runtime, все *.page.ts и *.component.ts (имена формата page-\<name\>, component-\<name\>);
  • Настраивает build (outDir, rollupOptions.input и т.д.) и dev-server (порт 1984, строгий порт, watch с polling).
  • Подключает внутренние плагины: обработка @Page, @Component, @Define, рантайм, сервер и доп. вотчеры.

Настройки сборки

Фреймворк поддерживает гибкую систему сборки за счёт билдеров для контроллеров, стилей и шаблонов. Ниже представлен список билдеров с сылками на их документацию:

Сборщики стилей

Сборщики шаблонов

Краткий чек-лист

  1. Определите страницу через @Page({ templateSrc, styleSrc? });
  2. Создавайте переиспользуемые блоки через @Component({ selector, templateSrc, styleSrc? });
  3. Отмечайте входные параметры как @Define и задавайте дефолты инициализаторами полей;
  4. Используйте хуки onInit, onViewInit при необходимости;
  5. Настройте vite.config.ts через gBuilder(...);