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 🙏

© 2024 – Pkg Stats / Ryan Hefner

tortue

v1.0.14

Published

Website development made easy

Downloads

6

Readme

Tortue /tɔʁ.ty/

License: MIT npm npm type definitions swtf

Website development made easy

Table of content



System requirements

The following software should be installed on your system and added to the PATH environment variable.

  • Node.js v14 or higher (https://nodejs.org/en/)
  • npm (https://www.npmjs.com/package/npm)
  • git (https://git-scm.com/downloads)


Concepts

Tortue is a flexible website building framework with an educative nature, mainly meant for static website development. The core concept of Tortue lies in defining contexts to parts of a website that are reusable and easier to organize in a granular way - think of it as a templating engine with the ability to scale. Defining contexts through the Tortue hierarchy (Components, Layouts, Pages) provides an easier way to maintain the codebase and reuse some of its parts in other projects. Tortue’s educative nature consists of allowing entry-level web developers to practice abstraction by using only HTML. Because Tortue should be flexible as mentioned, it provides its own plugin system named Tortue Shells. In the end, Tortue is opinionated on many things, but will try to provide as many features as long as they don't stray away from the Tortue philosophy.



Quick start

Install tortue globally:

npm i -g tortue

See help:

tortue -h

Create a new project:

tortue new my-project

Run a development environment:

cd my-project
npm install
npm run dev

Create a new component Home-Hero-Section:

tortue create comp Home-Hero-Section

By default, a new component comes only with the index.html file. If you want to include style, script or documentation use flags -s, -j or -d respectively.

This command creates the Home-Hero-Section component with the style.css and script.js files as well:

tortue create comp Home-Hero-Section -s -d

Create a new page AboutUs:

tortue create page AboutUs

For more info on create command run:

tortue create -h

Run production build after finishing development:

npm run build

Install tortue locally:

npm i -D tortue

If you are using VS Code, update your .vscode/settings.json with the following options.

{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "[html]": {
    "editor.defaultFormatter": "vscode.html-language-features"
  }
}


Tortue processes

There are two main Tortue processes exposed through CLI application.

  • Watch
  • Export

You can run the following command to start watch process.

tortue watch

Watch process is used for development environment.

You can run the following command to start export process.

tortue export

Export process is used for production build.



Tortue Configuration

Configuration interface

interface TortueConfig {
  componentsDir: string;
  pagesDir: string;
  layoutsDir: string;
  shellsConfig: TortueShellConfig[];
}

Default configuration

{
  "componentsDir": "components",
  "layoutsDir": "layouts",
  "pagesDir": "pages"
}

Example of custom configuration

{
  "componentsDir": "./subdir/components",
  "layoutsDir": "./subdir/layouts",
  "pagesDir": "./subdir/pages",
  "shellsConfig": [
    {
      "name": "intellisense-vsc"
    },
    {
      "name": "export-assets"
    },
    {
      "name": "export-html",
      "args": {
        "exportDir": "./subdir/dist-html"
      }
    }
  ]
}

Tortue Shell Configuration


Configuration interface

interface TortueShellConfig {
  name: string;
  path: string;
  args: any;
  events: TortuePipelineEvent[];
}


Tortue Shells

Tortue Shells are the way to enhance your Tortue environment. Shells are just plain Javascript objects.

Example:

const customShell = {
  name: "custom-shell",
  actions: {
    configLoaded: async (data) => {
      //your code here...

      return data;
    },
    componentsBuilt: async (data) => {
      //your code here...

      return data;
    },
    layoutsBuilt: async (data) => {
      //your code here...
      return data;
    },
    pagesBuilt: async (data) => {
      //your code here...

      return data;
    },
    renderFinished: async (data) => {
      //your code here...

      return data;
    },
  },
};

Every action is callback that receives data and can interact with it and change it. Every action as a result must return same type of object as data is.

data object interface:

export interface TortueShellActionData {
  registry: ComponentRegistry;
  pages: Page[];
  layouts: Layout[];
  config: TortueConfig;
}


Standard Shells

List of standard preloaded shells is:



Terminology

Context


Definition

Context is a named abstract or concrete part of the website we're building. Examples?

  • Header
  • Navigation
  • Home
  • Page
  • Image

We see different levels of abstraction in these items. The point is that anything can be a context.

The need for structuring contexts resolves in the context’s recursive nature. A context can have sub-contexts (children). Example?

  • Home
    • Navigation
    • Header
      • Image

Representation

We "physically" represent contexts using the following folder structure:

📂 Home/
  📂 Navigation
  📂 Header/
    📂 Image

To represent this hierarchy in a humanly comprehensible way, context names are represented by the context's full path in the hierarchy. Every level in the context name is delimited by -(minus), so context names shouldn't contain that character.

Context names from the above example:

Home
Home-Navigation
Home-Header
Home-Header-Image

In code we can represent context through the interface (js like pseudo-code):

interface Context {
  name: string;
  children: Context[];
}

We can separate contexts into two groups, abstract and concrete contexts. The only difference between these two groups is that concrete contexts doesn't have children.


Component


Definition

A component is a concrete context that represents the minimal building block of every website. Components can be used to build other components. Every component consists of its:

  • Name (Context)
  • Structure (HTML)
  • Style (CSS)
  • Logic (JS)
  • Documentation (MD)

Including one component into another means including its structure, style, and logic together.

Representation

We "physically" represent component using a following folder and file structure:

📂 Home/
  📂 Header/
    📂Section/
      📄 index.html
      📄 style.css
      📄 script.js
      📄 doc.md

In code we can represent components through interface (js like pseudo code):

interface Component {
  name: string;
  html: string;
  css: string;
  js: string;
  doc: string;
}

Calling component

Components include another component by including the HTML tag in its structure, with the context name of the component it wants to include. Example?

Home/Header/Image/index.html

<div class="home-header-image">
  <img src="/assets/images/home-header-bg.png" />
</div>

Home/Header/Section/index.html

<div class="home-header-section">
  <h1>Main header</h1>

  <!-- This is a component call -->
  <Home-Header-Image></Home-Header-Image>

  <p>Some short description</p>
</div>

Props

Components have ability to receive custom properties named props. Props are passed to component while calling the component. To pass a prop into comp

Home/Info/Box/index.html

<section class="home-info-box">
  <a href="tel:{{phone}}"> {{phone}}</a>
  <a href="mailto:{{mail}}"> {{mail}}</a>
</section>

Home/Header/Section/index.html

<div class="home-header-section">
  <!-- This is a component call that include passing props to component -->
  <Home-Info-Box
    tp-mail="[email protected]"
    tp-phone="(253) 616-4991"
  ></Home-Info-Box>

  <h1>Main header</h1>
  <Home-Header-Image></Home-Header-Image>
  <p>Some short description</p>
</div>

Note that field we used eariler in HTML {{phone}} is propagated to Common-Info-Box component by adding tp-phone attribute. So prefix for sending prosp to component is tp-;

Prop naming must follow:

  • follow snake case syntax in HTML (example: tp-info-email)
  • in rendering use same syntax (example: {{info-email}})
  • props should only contain letters and numbers

Content

Components can render passed children through by using special prop named innerContent. To display this prop we use {{{innerContent}}} in our components.

Home/Info/Box/index.html

<section class="home-info-box">
  {{{innerContent}}}
  <a href="tel:{{phone}}"> {{phone}}</a>
  <a href="mailto:{{mail}}"> {{mail}}</a>
</section>
<div class="home-header-section">
  <Home-Info-Box tp-mail="[email protected]" tp-phone="(253) 616-4991">
    <p>Here is custom text before mail and phone</p>
    <!-- Everythin between component tags represent children passed as innerContent -->
  </Home-Info-Box>

  <h1>Main header</h1>
  <Home-Header-Image></Home-Header-Image>
  <p>Some short description</p>
</div>

NOTICE: Props are rendered using Mustache templating engine.


Page


Definition

A page is a concrete context that consists of components and represents a website page. Think of it as a template for components. Every page consists of:

  • Name (Context)
  • Structure (HTML)
  • Style (CSS)
  • Logic (JS)

Representation

We "physically" represent pages using the following folder and file structure:

📂 Home/
  📄 index.html
  📄 style.css
  📄 script.js

In code we can represent pages through the interface (js like pseudo code):

interface Page {
  name: string;
  html: string;
  css: string;
  js: string;
}

A page can include components in the same way components include each other (read Component).


Layout


Definition

A layout represents a context(abstract or concrete) that is a template for one or multiple pages. If layout represents concrete context it will be used as a template for only one page. If layout represents abstract context, it will serve as a template for all the children pages of that context. Every layout consists of:

  • Name (Context)
  • Structure (HTML)

Representation

We "physically" represent layouts using the following folder and file structure:

📂 Blogs/
  📄 layout.html

In code we can represent layouts through the interface (js like pseudo code):

interface Layout {
  name: string;
  html: string;
}

Finidng layout for page

Every page by default uses default layout(layouts/layout.html) if defined. If you want to create layout for specific page or context of pages create layout that follow context hierarchy of that page.

Example:

Pages:

  • Home (pages/Home)
  • Blogs-FirstBlog (pages/Blogs/FirstBlog)
  • Blogs-SecondBlog (pages/Blogs/SecondBlog)

Layouts:

  • DEFAULT (layouts/layout.html)
  • Blogs (layouts/Blogs/layout.html)

Pages Blogs-FirstBlog and Blogs-SecondBlog will use Blogs layout, while Home page will use DEFAULT layout.

Head and Content

Example:

layout.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    {{{head}}}
  </head>
  <body>
    {{{content}}}
  </body>
</html>

{{{head}}} represents place where pages <head> tag will be included. {{{content}}} represents place where pages <body> tag will be included.

NOTICE: Layouts are rendered using Mustache templating engine.


Tortue


Tortue is a set of tools that provides the following actions:

  • Load configuration
  • Load shells
  • Build components
  • Build layouts
  • Build pages
  • Render pages

and provides the following data:

  • Configuration
  • Shells
  • Components
  • Pages
  • Layouts

In code we can represent tortue through the interface (js like pseudo code):

interface Tortue {
  //actions
  loadConfig(): Promise<void>;
  loadShells(): Promise<void>;
  buildComponents(): Promise<void>;
  buildLayouts(): Promise<void>;
  buildPages(): Promise<void>;
  renderPages(): Promise<void>;
  //data
  config: TortueConfiguration; //Configuration
  shells: TortueShell[]; //Shells
  componentRegistry: ComponentRegistry; //Components
  pages: Page[]; //Pages
  layouts: Layout[]; //Layouts
}

Pipeline


Definition

Pipeline represents Tortue actions and data flow orchestration.

Pipeline defines states that can occur while running pipeline.

Example of the Tortue export pipeline:

  • COMPONENTS_BUILT
  • PAGES_BUILT
  • LAYOUTS_BUILT
  • CONFIG_LOADED
  • RENDER_FINISHED

  TORTUE PIPELINE EXAMPLE
  ────────────────────────


 ┌─────────────┐   ┌─────────────┐                ┌──────────────────┐
 │             │   │             │ configLoaded   │                  │
 │ Load Config ├───► Load Shells ├────────────────► Build Components ├─┐
 │             │   │             │                │                  │ │
 └─────────────┘   └─────────────┘                └──────────────────┘ │
                                                                       │
                          componentsBuilt                              │
  ┌────────────────────────────────────────────────────────────────────┘
  │
  │
  │  ┌───────────────┐               ┌─────────────┐              ┌──────────────┐
  │  │               │ layoutsBuilt  │             │ pagesBuilt   │              │
  └──► Build Layouts ├───────────────► Build Pages ├──────────────► Render Pages ├──┐
     │               │               │             │              │              │  │
     └───────────────┘               └─────────────┘              └──────────────┘  │
                                ~+                                                  │
                                                                                    │
                                         *       +                                  │
                                   '                  |           renderFinished    │
                               ()    .-.,="``"=.    - o -   ◄───────────────────────┘
                                     '=/_       \     |
                                  *   |  '=._    |
                                       \     `=./`,        '
                                    .   '=.__.=' `='      *
                           +                         +
                                O      *        '       .

Tortue currently uses only one Pipeline and that's the one shown above.

Pipeline provides abbility to create plugins(Shells) that can interact with Tortue data in some of the Pipeline states.


Process


Process represents a way of using a pipeline.

Export process

Export process uses export pipeline to provide a way for building and exporting your website in wanted structure.

Watch process

Watch process uses export pipeline to ease a website development process by running export pipeline every time some of the website parts are created, removed or modified.


Shell


Definition

Tortue Shell is a plugin system around Tortue Pipeline. Every Shell is consisted of:

  • Name
  • Actions

Actions are callbacks that can process and change tortue data every time pipeline finds in a state that represent an action name.

Representation

In code we can represent tortue shell through the interface (js like pseudo code):

interface ActionData {
  registry: ComponentRegistry;
  pages: Page[];
  layouts: Layout[];
  config: TortueConfig;
}

interface TortueShell {
  name: string;
  actions: {
    configLoaded: (data: ActionData) => Promise<ActionData>;
    componentsBuilt: (data: ActionData) => Promise<ActionData>;
    layoutsBuilt: (data: ActionData) => Promise<ActionData>;
    pagesBuilt: (data: ActionData) => Promise<ActionData>;
    renderFinished: (data: ActionData) => Promise<ActionData>;
  };
}


Contributors

Sponsors