Code Monkey home page Code Monkey logo

tableau's Introduction

Tableau

Discord Hex.pm Hex Docs GitHub Discussions

Static Site Generator for Elixir.

Goals

  • Good code and browser reloading on file change
  • Easy to use the current Node.js JS/CSS tooling
  • Extensions
  • Ability to work with "data" (either dynamic data or static files)
    • YAML Files
    • Elixir scripts (.exs files)
  • Handles stuff like Posts, RSS, sitemap, SEO.
    • Posts
    • RSS
    • Sitemap
    • SEO
  • Project generator

Installation

The easiest way to get started is to generate a new project using the tableau.new mix task.

Currently the generator can create a website using several different template syntaxes and assets frameworks.

Please run mix help tableau.new or mix tableau.new --help to see all of the possible flags.

mix archive.install hex tableau_new

mix tableau.new my_awesome_site

Otherwise, you can just install Tableau into a new mix project.

def deps do
  [
    {:tableau, "~> 0.14"}
  ]
end

Documentation can be found at https://hexdocs.pm/tableau.

Built with Tableau

Site Template Styling Source
www.elixir-tools.dev Temple Tailwind elixir-tools/elixir-tools.dev
www.mitchellhanberg.com Liquid Tailwind mhanberg/blog
pdx.su Temple CSS paradox460/pdx.su
Xmeyers HEEx Tailwind andyl/xmeyers
0x7f HEEx magick.css 0x7fdev/site

Getting Started

The examples in the README use the Temple library to demonstrate that Tableau can be used with any markup language of your choice. You could easily use the builtin EEx, or use HEEx, Surface, or HAML.

Layouts

Layouts are modules that use the use Tableau.Layout macro.

Layouts have access to the @site and @page assign.

The @site assign contains your site's config.

The @page assign contains all the options passed to the use Tableau.Page macro.

defmodule MySite.RootLayout do
  use Tableau.Layout

  import Temple

  def template(assigns) do
    temple do
      "<!DOCTYPE html>"

      html lang: "en" do
        head do
          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 do
            @page.some_assign
          end

          link rel: "stylesheet", href: "/css/site.css"
        end

        body class: "font-sans" do
          main class: "container mx-auto px-2" do
            div class: "border-4 border-green-500" do
              a class: "text-blue-500 hover:underline", href: "/about" do
                "About"
              end

              a class: "text-blue-500 hover:underline", href: "/posts" do
                "Posts"
              end

              render @inner_content
            end
          end
        end

        if Mix.env() == :dev do
          c &Tableau.live_reload/1
        end
      end
    end
  end
end

Page

Pages are modules that use the use Tableau.Page macro.

Required options:

  • :layout - which layout module to use.
  • :permalink - the permalink of the page

Any remaining options are arbitrary and will be available under the @page assign available to layout and page templates.

defmodule MySite.AboutPage do
  use Tableau.Page,
    layout: MySite.RootLayout,
    permalink: "/about",
    some_assign: "foo"

  import Temple

  def template(assigns) do
    temple do
      span class: "text-red-500 font-bold" do
        "i'm a super cool and smart!"
      end
    end
  end
end

Live Reloading

You can specify a set of directories/files to watch for changes, and the browser will automatically refresh.

# config/config.exs
import Config

config :tableau, :reloader,
  patterns: [
    ~r"lib/layouts/.*.ex",
    ~r"lib/pages/.*.ex",
    ~r"lib/components.ex",
    ~r"_site/.*.css"
  ]

All you need to do is render the Tableau.live_reload/1 component right after your body tag.

# lib/layouts/app.ex

defmodule YourApp.Layouts.App do
  use Tableau.Layout

  import Temple

  def template(assigns) do
    temple do
      "<!DOCTYPE html>"

      html lang: "en" do
        head do
          meta charset: "utf-8"
          meta http_equiv: "X-UA-Compatible", content: "IE=edge"
          meta name: "viewport", content: "width=device-width, initial-scale=1.0"

          link rel: "stylesheet", href: "/css/site.css"
        end

        body class: "font-sans" do
          main class: "container mx-auto px-2" do
            render(@inner_content)
          end
        end

        if Mix.env() == :dev do
          c &Tableau.live_reload/1
        end
      end
    end
  end
end

JS/CSS

You can arbitrarily start other build tools as "watchers". This is inspired by the way Phoenix does it.

# config/config.exs

import Config

config :tableau, :assets,
  npx: [
    "tailwindcss",
    "-o",
    "_site/css/site.css",
    "--watch"
  ]

# or if you are using a package similar to the TailwindCSS hex package

config :tableau, :assets, tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}

import_config "#{config_env()}.exs"

This will start a long running process that will independently build your CSS as it sees files change.

These are started automatically when you run mix tableau.server.

Static Assets

Other static assets can be copied into the "out" directory by placing them in an extra directory in the root of your project.

This directory can be configured.

config :tableau, :config,
  include_dir: "static"

Development

The dev server can be started with mix tableau.server. On file change, a browser reload will be triggered and the page your requesting will be re-built during the request.

tableau's People

Contributors

03juan avatar andreicek avatar andyl avatar github-actions[bot] avatar kevinschweikert avatar mhanberg avatar paradox460 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

tableau's Issues

Live reload is not working

Description

Not entirely sure why, but the filesystem watcher seems to not be picking up file changes on macOS or Linux.

Need to investigate further.

Allow creating arbitrary pages using markdown

Description

Currently, the only way (other than making a custom extension) to create a page with markdown is to put it in your _posts directory and create a post.

This is not ideal, because those pages require dates and will show up in the rss feed.

Vhost Path Prefix for the Development Server ?

I'd like to host Tableau sites on google pages. Google Pages provides a base-url like https://andyl.github.io/stat1, where the stat1 prefix is a virtual host identifier tied to the repo at https://github.com/andyl/stat1.

Also: in NGINX it is common to use a location prefix for Vhosts. Here is an example NGINX config snippet:

server {
    listen 80;
    server_name myhost.com;

    location /site1 {
        # Configuration for site1 - eg the root directive to a directory
        # root /var/www/site1;
    }

    location /site2 {
        # Configuration for site2
        # Similar configuration as site1, adjusted for site2 specifics
    }

    # Other configuration...
}

As a developer, I'd like to write my Tableau app with the Path Prefix built in to all my hard-coded hrefs. No problem in production. But in development, I don't know how to configure mix tableau.server to use a Vhost path prefix. So I can build a site that works in development, or production, but not both.

Is there a way to configure a path prefix for the development server?

HEEX Example?

Can anyone post a link to a tableau site that uses HEEX instead of temple? TIA

Site generator

Description

Ideally we have an escript similar to mix phx.new that can be run as mix tableau.new to bootstrap a new website.

This task should have some options that control different aspects of your project.

--template=<eex|heex|temple>
--css=<tailwind>, --no-css
--js=<esbuild>, --no-js

Lots of Telemetry Warnings

When I compile or run Tableau, I get many Telemetry Warnings

image

I get the same behavior on Elixir 1.15 and 1.16

I believe the warnings come from a library schematic in the telemetry_wrap function of schematic.ex.

Here's my workaround to remove the telemetry warnings:

image

Does anyone else see these warnings?

Are the telemetry metrics in Schematic necessary?

Is there a way to suppress the telemetry warnings without altering the Schematic code?

Consider a project name change?

Awesome project. I'd love to see it get more popular.

Perhaps the authors might consider a name change?

Tableau is popular business software now owned by Salesforce that has been trademarked globally.

US Trademark Registration Number | 6919884
International Registration Number | 1655549

Which means if this project becomes popular, Salesforce's lawyers are obligated to ask you to change the project name (or shut down) to protect their trademark.

If they don't protect it, the run the chance of losing it.

It's only a matter of time before that email arrives.

Plus there's a good chance most people will be confused the first time they see "powered by Tableau" and assume it's the business software (like I did).

perf: speed up post extension

The post extension (and probably the page extension) is pretty slow.

On my blog of 39 posts, they take roughly 500ms for the post extension to run. probably 2/3rds of this is when the extension is creating the nimble publisher module, the other third is writing creating the page modules for each post.

I'm not sure exactly the best approach here. Will need to figure out if creating the modules at runtime is the bottleneck first (it probably is), and then figure out how to move forward from there.

Might need to drop nimble publisher and just do it at runtime. Creating the module at runtime was sort of just a hack to get something running quickly.

Error when posts have non-English characters

I am trying to migrate my current website from Jekyll to Tableau and I've found a small bug when it tries to render a post that has non English characters in the title.

My post is called: ¿Qué es la programación funcional? and when Tableau tries to render it from Markdown into HTML I get the following error:

19:25:13.837 [error] GenServer #PID<0.2170.0> terminating
** (File.Error) could not make directory (with -p) <<95, 115, 105, 116, 101, 47, 50, 48, 49, 54, 47, 48, 53, 47, 49, 48, 47, 194, 113, 117, 195, 45, 101, 115, 45, 108, 97, 45, 112, 114, 111, 103, 114, 97, 109, 97, 99, 105, 195, 110, 45, 102, 117, 110, 99, 105, 111, 110, 97, 108>>: unknown POSIX error: eilseq
    (elixir 1.15.5) lib/file.ex:319: File.mkdir_p!/1
    (tableau 0.15.3) lib/mix/tasks/tableau.build.ex:72: anonymous fn/5 in Mix.Tasks.Tableau.Build.run/1
    (elixir 1.15.5) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
    (tableau 0.15.3) lib/mix/tasks/tableau.build.ex:67: Mix.Tasks.Tableau.Build.run/1
    (mix 1.15.5) lib/mix/task.ex:447: anonymous fn/3 in Mix.Task.run_task/5
    (tableau 0.15.3) lib/tableau/router.ex:42: Tableau.Router.rerender/2
    (tableau 0.15.3) lib/tableau/router.ex:1: Tableau.Router.plug_builder_call/2
    (bandit 1.3.0) lib/bandit/pipeline.ex:103: Bandit.Pipeline.call_plug/2
Last message: {:continue, :handle_connection}
State: {%ThousandIsland.Socket{socket: #Port<0.104>, transport_module: ThousandIsland.Transports.TCP, read_timeout: 60000, silent_terminate_on_error: false, span: %ThousandIsland.Telemetry{span_name: :connection, telemetry_span_context: #Reference<0.3843209265.873988097.141771>, start_time: -576460114413566402, start_metadata: %{remote_address: {127, 0, 0, 1}, remote_port: 52013, telemetry_span_context: #Reference<0.3843209265.873988097.141771>, parent_telemetry_span_context: #Reference<0.3843209265.873988105.121747>}}}, %{opts: %{websocket: [], http_1: [], http_2: []}, plug: {Tableau.Router, []}, handler_module: Bandit.InitialHandler, http_1_enabled: true, http_2_enabled: true, websocket_enabled: true}}

If I remove the opening question marks and the accents it seems to work just fine. The default permalink configuration that I am using is "/:year/:month/:day/:title".

Create a discussions page

I (and maybe others) would like to occasionally ask a question about using Tableau, and issues aren't the right place for that.

Suggestion: create a discussions page like in the Temple repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.