A Simple, Extendable Markdown Renderer for Your Terminal

🎩 charMD

A simple, extendable markdown renderer for your terminal.

🚧 This module is in early developement, expect breaking changes 🚧

charMD enables you to render a markdown text into a string, which printed in the terminal provides a well formatted output, instead of plain text.

Showcase

Try it out

To see the general capabilities of this module run:

deno run https://deno.land/x/charmd/example.ts

To see, how a specific markdown gets rendered run:

deno run --allow-read https://deno.land/x/charmd/example.ts ./README.md

Usage

Simply import the module and call the renderMarkdown method with your markdown text.

import { renderMarkdown } from 'https://deno.land/x/charmd/mod.ts';

console.log(renderMarkdown('# Hello world 🌍!'));

🧩 Extensions

The module provides a way to extend it functionality with additional extensions, which can be provided in it’s options param.

An extension can implement any of the Extension interface’s methods, which are:

  • init: Called before AST generation, if a string is returned, it will override the input markdown for later extension’s init fn and processing steps.
  • postAST: Called with the generated AST’s root node, before any transformations
  • transformNode: Called with each node to do modifications on the node and it’s children in the AST.
  • postTransform: Called with root, after all the transformations ran for all nodes.
  • generateNode: Called with each node. It should return the string representation of the rendered node,if the extension handles that specific node, or void, if its not handled by the extension.
  • postGenerate: Called after the string representation is created.

A simple extension, that renders link with green and blue instead of the built-in cyan would look something like this:

const LinkExt = {
    generateNode(genFn, node: Node, parent: Node, options: Options) {
          if(node.type === 'link') {
            const linkText = node.children?.map(ch => genFn(ch, node, options)).join('') || '';
            const link = `Link with text '${colors.blue(linkText)}' points to ${colors.cyan(node.url!)}`
            return colors.green(link);
          }
      }
}

console.log(renderMarkdown(
    '[charMD](https://github.com/littletof/charmd)',
    { extensions: [LinkExt] }
));

Direct use - cli.ts

For direct use in the terminal run cli.ts:

deno run --allow-net https://deno.land/x/charmd/cli.ts -r https://raw.githubusercontent.com/denoland/deno/master/README.md

Or install it with deno install

It has three options:

  • -s for rendering a string directly: -s "# markdown string"
  • -l for rendering a local file: -l ./README.md
  • -r for rendering a remote file: -r https://raw.githubusercontent.com/denoland/deno/master/README.md

Permissions

The module itself requires no permissions to run.

If --unstable is provided, horizontal separators will consider the terminal’s width.

Limitations

  • No syntax highlight
  • No strikethrough or underline
  • No multiline tables cells
  • Possible hiccups with more complex markdowns

These could change in the future, but the aim is to keep the module’s complexity minimal.

Also, many of these should also be solvable using extensions.

Notes

  • The main functions are also exported from the module, so for example you can use the toAST function to get your ast for the markdown and process it yourself.

  • As its core, it currently uses mdast-util-from-markdown, to get the AST, you can also provide extensions to it in the options unstable mdast property.

  • This module’s core structure draws from @dephraims work with https://github.com/dephraiim/termd.

Contributions

Feedback and contributions are always welcome. Open an issue or a PR, or contact me on the Deno discord.

TODO

  • [x] fix lists
  • [x] remove dots from codeblock backgrounds
  • [x] links with images
  • [x] # Header with *italic*
  • [ ] tests
  • [ ] fmt, lint
  • [ ] strikethrough, underline and combinations
  • [ ] Look into alternatives for the AST generation.

Download Details:

Author: littletof

Source Code: https://github.com/littletof/charmd

#deno #node #nodejs #javascript

What is GEEK

Buddha Community

A Simple, Extendable Markdown Renderer for Your Terminal
Beth  Cooper

Beth Cooper

1659694200

Easy Activity Tracking for Models, Similar to Github's Public Activity

PublicActivity

public_activity provides easy activity tracking for your ActiveRecord, Mongoid 3 and MongoMapper models in Rails 3 and 4.

Simply put: it can record what happens in your application and gives you the ability to present those recorded activities to users - in a similar way to how GitHub does it.

!! WARNING: README for unreleased version below. !!

You probably don't want to read the docs for this unreleased version 2.0.

For the stable 1.5.X readme see: https://github.com/chaps-io/public_activity/blob/1-5-stable/README.md

About

Here is a simple example showing what this gem is about:

Example usage

Tutorials

Screencast

Ryan Bates made a great screencast describing how to integrate Public Activity.

Tutorial

A great step-by-step guide on implementing activity feeds using public_activity by Ilya Bodrov.

Online demo

You can see an actual application using this gem here: http://public-activity-example.herokuapp.com/feed

The source code of the demo is hosted here: https://github.com/pokonski/activity_blog

Setup

Gem installation

You can install public_activity as you would any other gem:

gem install public_activity

or in your Gemfile:

gem 'public_activity'

Database setup

By default public_activity uses Active Record. If you want to use Mongoid or MongoMapper as your backend, create an initializer file in your Rails application with the corresponding code inside:

For Mongoid:

# config/initializers/public_activity.rb
PublicActivity.configure do |config|
  config.orm = :mongoid
end

For MongoMapper:

# config/initializers/public_activity.rb
PublicActivity.configure do |config|
  config.orm = :mongo_mapper
end

(ActiveRecord only) Create migration for activities and migrate the database (in your Rails project):

rails g public_activity:migration
rake db:migrate

Model configuration

Include PublicActivity::Model and add tracked to the model you want to keep track of:

For ActiveRecord:

class Article < ActiveRecord::Base
  include PublicActivity::Model
  tracked
end

For Mongoid:

class Article
  include Mongoid::Document
  include PublicActivity::Model
  tracked
end

For MongoMapper:

class Article
  include MongoMapper::Document
  include PublicActivity::Model
  tracked
end

And now, by default create/update/destroy activities are recorded in activities table. This is all you need to start recording activities for basic CRUD actions.

Optional: If you don't need #tracked but still want the comfort of #create_activity, you can include only the lightweight Common module instead of Model.

Custom activities

You can trigger custom activities by setting all your required parameters and triggering create_activity on the tracked model, like this:

@article.create_activity key: 'article.commented_on', owner: current_user

See this entry http://rubydoc.info/gems/public_activity/PublicActivity/Common:create_activity for more details.

Displaying activities

To display them you simply query the PublicActivity::Activity model:

# notifications_controller.rb
def index
  @activities = PublicActivity::Activity.all
end

And in your views:

<%= render_activities(@activities) %>

Note: render_activities is an alias for render_activity and does the same.

Layouts

You can also pass options to both activity#render and #render_activity methods, which are passed deeper to the internally used render_partial method. A useful example would be to render activities wrapped in layout, which shares common elements of an activity, like a timestamp, owner's avatar etc:

<%= render_activities(@activities, layout: :activity) %>

The activity will be wrapped with the app/views/layouts/_activity.html.erb layout, in the above example.

Important: please note that layouts for activities are also partials. Hence the _ prefix.

Locals

Sometimes, it's desirable to pass additional local variables to partials. It can be done this way:

<%= render_activity(@activity, locals: {friends: current_user.friends}) %>

Note: Before 1.4.0, one could pass variables directly to the options hash for #render_activity and access it from activity parameters. This functionality is retained in 1.4.0 and later, but the :locals method is preferred, since it prevents bugs from shadowing variables from activity parameters in the database.

Activity views

public_activity looks for views in app/views/public_activity.

For example, if you have an activity with :key set to "activity.user.changed_avatar", the gem will look for a partial in app/views/public_activity/user/_changed_avatar.html.(|erb|haml|slim|something_else).

Hint: the "activity." prefix in :key is completely optional and kept for backwards compatibility, you can skip it in new projects.

If you would like to fallback to a partial, you can utilize the fallback parameter to specify the path of a partial to use when one is missing:

<%= render_activity(@activity, fallback: 'default') %>

When used in this manner, if a partial with the specified :key cannot be located it will use the partial defined in the fallback instead. In the example above this would resolve to public_activity/_default.html.(|erb|haml|slim|something_else).

If a view file does not exist then ActionView::MisingTemplate will be raised. If you wish to fallback to the old behaviour and use an i18n based translation in this situation you can specify a :fallback parameter of text to fallback to this mechanism like such:

<%= render_activity(@activity, fallback: :text) %>

i18n

Translations are used by the #text method, to which you can pass additional options in form of a hash. #render method uses translations when view templates have not been provided. You can render pure i18n strings by passing {display: :i18n} to #render_activity or #render.

Translations should be put in your locale .yml files. To render pure strings from I18n Example structure:

activity:
  article:
    create: 'Article has been created'
    update: 'Someone has edited the article'
    destroy: 'Some user removed an article!'

This structure is valid for activities with keys "activity.article.create" or "article.create". As mentioned before, "activity." part of the key is optional.

Testing

For RSpec you can first disable public_activity and add require helper methods in the rails_helper.rb with:

#rails_helper.rb
require 'public_activity/testing'

PublicActivity.enabled = false

In your specs you can then blockwise decide whether to turn public_activity on or off.

# file_spec.rb
PublicActivity.with_tracking do
  # your test code goes here
end

PublicActivity.without_tracking do
  # your test code goes here
end

Documentation

For more documentation go here

Common examples

Set the Activity's owner to current_user by default

You can set up a default value for :owner by doing this:

  1. Include PublicActivity::StoreController in your ApplicationController like this:
class ApplicationController < ActionController::Base
  include PublicActivity::StoreController
end
  1. Use Proc in :owner attribute for tracked class method in your desired model. For example:
class Article < ActiveRecord::Base
  tracked owner: Proc.new{ |controller, model| controller.current_user }
end

Note: current_user applies to Devise, if you are using a different authentication gem or your own code, change the current_user to a method you use.

Disable tracking for a class or globally

If you need to disable tracking temporarily, for example in tests or db/seeds.rb then you can use PublicActivity.enabled= attribute like below:

# Disable p_a globally
PublicActivity.enabled = false

# Perform some operations that would normally be tracked by p_a:
Article.create(title: 'New article')

# Switch it back on
PublicActivity.enabled = true

You can also disable public_activity for a specific class:

# Disable p_a for Article class
Article.public_activity_off

# p_a will not do anything here:
@article = Article.create(title: 'New article')

# But will be enabled for other classes:
# (creation of the comment will be recorded if you are tracking the Comment class)
@article.comments.create(body: 'some comment!')

# Enable it again for Article:
Article.public_activity_on

Create custom activities

Besides standard, automatic activities created on CRUD actions on your model (deactivatable), you can post your own activities that can be triggered without modifying the tracked model. There are a few ways to do this, as PublicActivity gives three tiers of options to be set.

Instant options

Because every activity needs a key (otherwise: NoKeyProvided is raised), the shortest and minimal way to post an activity is:

@user.create_activity :mood_changed
# the key of the action will be user.mood_changed
@user.create_activity action: :mood_changed # this is exactly the same as above

Besides assigning your key (which is obvious from the code), it will take global options from User class (given in #tracked method during class definition) and overwrite them with instance options (set on @user by #activity method). You can read more about options and how PublicActivity inherits them for you here.

Note the action parameter builds the key like this: "#{model_name}.#{action}". You can read further on options for #create_activity here.

To provide more options, you can do:

@user.create_activity action: 'poke', parameters: {reason: 'bored'}, recipient: @friend, owner: current_user

In this example, we have provided all the things we could for a standard Activity.

Use custom fields on Activity

Besides the few fields that every Activity has (key, owner, recipient, trackable, parameters), you can also set custom fields. This could be very beneficial, as parameters are a serialized hash, which cannot be queried easily from the database. That being said, use custom fields when you know that you will set them very often and search by them (don't forget database indexes :) ).

Set owner and recipient based on associations

class Comment < ActiveRecord::Base
  include PublicActivity::Model
  tracked owner: :commenter, recipient: :commentee

  belongs_to :commenter, :class_name => "User"
  belongs_to :commentee, :class_name => "User"
end

Resolve parameters from a Symbol or Proc

class Post < ActiveRecord::Base
  include PublicActivity::Model
  tracked only: [:update], parameters: :tracked_values
  
  def tracked_values
   {}.tap do |hash|
     hash[:tags] = tags if tags_changed?
   end
  end
end

Setup

Skip this step if you are using ActiveRecord in Rails 4 or Mongoid

The first step is similar in every ORM available (except mongoid):

PublicActivity::Activity.class_eval do
  attr_accessible :custom_field
end

place this code under config/initializers/public_activity.rb, you have to create it first.

To be able to assign to that field, we need to move it to the mass assignment sanitizer's whitelist.

Migration

If you're using ActiveRecord, you will also need to provide a migration to add the actual field to the Activity. Taken from our tests:

class AddCustomFieldToActivities < ActiveRecord::Migration
  def change
    change_table :activities do |t|
      t.string :custom_field
    end
  end
end

Assigning custom fields

Assigning is done by the same methods that you use for normal parameters: #tracked, #create_activity. You can just pass the name of your custom variable and assign its value. Even better, you can pass it to #tracked to tell us how to harvest your data for custom fields so we can do that for you.

class Article < ActiveRecord::Base
  include PublicActivity::Model
  tracked custom_field: proc {|controller, model| controller.some_helper }
end

Help

If you need help with using public_activity please visit our discussion group and ask a question there:

https://groups.google.com/forum/?fromgroups#!forum/public-activity

Please do not ask general questions in the Github Issues.


Author: public-activity
Source code: https://github.com/public-activity/public_activity
License: MIT license

#ruby  #ruby-on-rails 

Cells: View Components for Ruby and Rails

Cells

View Components for Ruby and Rails.   

Overview

Cells allow you to encapsulate parts of your UI into components into view models. View models, or cells, are simple ruby classes that can render templates.

Nevertheless, a cell gives you more than just a template renderer. They allow proper OOP, polymorphic builders, nesting, view inheritance, using Rails helpers, asset packaging to bundle JS, CSS or images, simple distribution via gems or Rails engines, encapsulated testing, caching, and integrate with Trailblazer.

Full Documentation

Cells is part of the Trailblazer framework. Full documentation is available on the project site.

Cells is completely decoupled from Rails. However, Rails-specific functionality is to be found here.

Rendering Cells

You can render cells anywhere and as many as you want, in views, controllers, composites, mailers, etc.

Rendering a cell in Rails ironically happens via a helper.

<%= cell(:comment, @comment) %>

This boils down to the following invocation, that can be used to render cells in any other Ruby environment.

CommentCell.(@comment).()

You can also pass the cell class in explicitly:

<%= cell(CommentCell, @comment) %>

In Rails you have the same helper API for views and controllers.

class DashboardController < ApplicationController
  def dashboard
    @comments = cell(:comment, collection: Comment.recent)
    @traffic  = cell(:report, TrafficReport.find(1)).()
  end

Usually, you'd pass in one or more objects you want the cell to present. That can be an ActiveRecord model, a ROM instance or any kind of PORO you fancy.

Cell Class

A cell is a light-weight class with one or multiple methods that render views.

class CommentCell < Cell::ViewModel
  property :body
  property :author

  def show
    render
  end

private
  def author_link
    link_to "#{author.email}", author
  end
end

Here, show is the only public method. By calling render it will invoke rendering for the show view.

Logicless Views

Views come packaged with the cell and can be ERB, Haml, or Slim.

<h3>New Comment</h3>
  <%= body %>

By <%= author_link %>

The concept of "helpers" that get strangely copied from modules to the view does not exist in Cells anymore.

Methods called in the view are directly called on the cell instance. You're free to use loops and deciders in views, even instance variables are allowed, but Cells tries to push you gently towards method invocations to access data in the view.

File Structure

In Rails, cells are placed in app/cells or app/concepts/. Every cell has their own directory where it keeps views, assets and code.

app
├── cells
│   ├── comment_cell.rb
│   ├── comment
│   │   ├── show.haml
│   │   ├── list.haml

The discussed show view would reside in app/cells/comment/show.haml. However, you can set any set of view paths you want.

Invocation Styles

In order to make a cell render, you have to call the rendering methods. While you could call the method directly, the preferred way is the call style.

cell(:comment, @song).()       # calls CommentCell#show.
cell(:comment, @song).(:index) # calls CommentCell#index.

The call style respects caching.

Keep in mind that cell(..) really gives you the cell object. In case you want to reuse the cell, need setup logic, etc. that's completely up to you.

Parameters

You can pass in as many parameters as you need. Per convention, this is a hash.

cell(:comment, @song, volume: 99, genre: "Jazz Fusion")

Options can be accessed via the @options instance variable.

Naturally, you may also pass arbitrary options into the call itself. Those will be simple method arguments.

cell(:comment, @song).(:show, volume: 99)

Then, the show method signature changes to def show(options).

Testing

A huge benefit from "all this encapsulation" is that you can easily write tests for your components. The API does not change and everything is exactly as it would be in production.

html = CommentCell.(@comment).()
Capybara.string(html).must_have_css "h3"

It is completely up to you how you test, whether it's RSpec, MiniTest or whatever. All the cell does is return HTML.

In Rails, there's support for TestUnit, MiniTest and RSpec available, along with Capybara integration.

Properties

The cell's model is available via the model reader. You can have automatic readers to the model's fields by using ::property.

class CommentCell < Cell::ViewModel
  property :author # delegates to model.author

  def author_link
    link_to author.name, author
  end
end

HTML Escaping

Cells per default does no HTML escaping, anywhere. Include Escaped to make property readers return escaped strings.

class CommentCell < Cell::ViewModel
  include Escaped

  property :title
end

song.title                 #=> "<script>Dangerous</script>"
Comment::Cell.(song).title #=> &lt;script&gt;Dangerous&lt;/script&gt;

Properties and escaping are documented here.

Installation

Cells runs with any framework.

gem "cells"

For Rails, please use the cells-rails gem. It supports Rails >= 4.0.

gem "cells-rails"

Lower versions of Rails will still run with Cells, but you will get in trouble with the helpers. (Note: we use Cells in production with Rails 3.2 and Haml and it works great.)

Various template engines are supported but need to be added to your Gemfile.

gem "cells-erb"

In Rails, this is all you need to do. In other environments, you need to include the respective module into your cells.

class CommentCell < Cell::ViewModel
  include ::Cell::Erb # or Cell::Hamlit, or Cell::Haml, or Cell::Slim
end

Namespaces

Cells can be namespaced as well.

module Admin
  class CommentCell < Cell::ViewModel

Invocation in Rails would happen as follows.

cell("admin/comment", @comment).()

Views will be searched in app/cells/admin/comment per default.

Rails Helper API

Even in a non-Rails environment, Cells provides the Rails view API and allows using all Rails helpers.

You have to include all helper modules into your cell class. You can then use link_to, simple_form_for or whatever you feel like.

class CommentCell < Cell::ViewModel
  include ActionView::Helpers::UrlHelper
  include ActionView::Helpers::CaptureHelper

  def author_link
    content_tag :div, link_to(author.name, author)
  end

As always, you can use helpers in cells and in views.

You might run into problems with wrong escaping or missing URL helpers. This is not Cells' fault but Rails suboptimal way of implementing and interfacing their helpers. Please open the actionview gem helper code and try figuring out the problem yourself before bombarding us with issues because helper xyz doesn't work.

View Paths

In Rails, the view path is automatically set to app/cells/ or app/concepts/. You can append or set view paths by using ::view_paths. Of course, this works in any Ruby environment.

class CommentCell < Cell::ViewModel
  self.view_paths = "lib/views"
end

Asset Packaging

Cells can easily ship with their own JavaScript, CSS and more and be part of Rails' asset pipeline. Bundling assets into a cell allows you to implement super encapsulated widgets that are stand-alone. Asset pipeline is documented here.

Render API

Unlike Rails, the #render method only provides a handful of options you gotta learn.

def show
  render
end

Without options, this will render the state name, e.g. show.erb.

You can provide a view name manually. The following calls are identical.

render :index
render view: :index

If you need locals, pass them to #render.

render locals: {style: "border: solid;"}

Layouts

Every view can be wrapped by a layout. Either pass it when rendering.

render layout: :default

Or configure it on the class-level.

class CommentCell < Cell::ViewModel
  layout :default

The layout is treated as a view and will be searched in the same directories.

Nested Cells

Cells love to render. You can render as many views as you need in a cell state or view.

<%= render :index %>

The #render method really just returns the rendered template string, allowing you all kind of modification.

def show
  render + render(:additional)
end

You can even render other cells within a cell using the exact same API.

def about
  cell(:profile, model.author).()
end

This works both in cell views and on the instance, in states.

View Inheritance

You can not only inherit code across cell classes, but also views. This is extremely helpful if you want to override parts of your UI, only. It's documented here.

Collections

In order to render collections, Cells comes with a shortcut.

comments = Comment.all #=> three comments.
cell(:comment, collection: comments).()

This will invoke cell(:comment, comment).() three times and concatenate the rendered output automatically.

Learn more about collections here.

Builder

Builders allow instantiating different cell classes for different models and options. They introduce polymorphism into cells.

class CommentCell < Cell::ViewModel
  include ::Cell::Builder

  builds do |model, options|
    case model
    when Post; PostCell
    when Comment; CommentCell
    end
  end

The #cell helper takes care of instantiating the right cell class for you.

cell(:comment, Post.find(1)) #=> creates a PostCell.

Learn more about builders here.

Caching

For every cell class you can define caching per state. Without any configuration the cell will run and render the state once. In following invocations, the cached fragment is returned.

class CommentCell < Cell::ViewModel
  cache :show
  # ..
end

The ::cache method will forward options to the caching engine.

cache :show, expires_in: 10.minutes

You can also compute your own cache key, use dynamic keys, cache tags, and conditionals using :if. Caching is documented here and in chapter 8 of the Trailblazer book.

The Book

Cells is part of the Trailblazer project. Please buy my book to support the development and to learn all the cool stuff about Cells. The book discusses many use cases of Cells.

![](https://raw.githubusercontent.com/apotonick/trailblazer/master/doc/trb.jpg) 

  • Basic view models, replacing helpers, and how to structure your view into cell components (chapter 2 and 4).
  • Advanced Cells API (chapter 4 and 6).
  • Testing Cells (chapter 4 and 6).
  • Cells Pagination with AJAX (chapter 6).
  • View Caching and Expiring (chapter 8).

The book picks up where the README leaves off. Go grab a copy and support us - it talks about object- and view design and covers all aspects of the API.

This is not Cells 3.x!

Temporary note: This is the README and API for Cells 4. Many things have improved. If you want to upgrade, follow this guide. When in trouble, join the Zulip channel.


Author:  trailblazer
Source code: https://github.com/trailblazer/cells

#ruby  #ruby-on-rails 

Arvel  Parker

Arvel Parker

1591627260

How to Use the Screen Command in Linux

Screen is a terminal program in Linux which allows us to use a virtual (VT100 terminal) as full-screen window manager which multiplexes an open physical terminal between multiple processes, which are typically, interactive shells. It allows us to access multiple terminal sessions within a single terminal or a remote terminal session. It is most useful when addressing multiple Linux shell commands on the command line, as well as separating commands from the shell that started the commands.

Screen also allows a user to initiate a command from one terminal, disconnect from that terminal, and then reconnect from a different location to that same terminal, while using a different terminal without having to restart the command. This simply lets a user better control multiple and separate command windows.

Screen also lets multiple remote computers connect to the same screen session at once. This allows multiple users to connect to the same screen session allowing a second user to follow along with another administrator working on a server.

#tutorials #attach #cli #command line #detach #key bindings #logging #multiplex #multiuser #multiuser mode #remote access #remote management #remote session #remote terminal #screen #screen logging #screen session #screenlog #screens #scrollback #shell #terminal #terminal session #terminal window #tty #vt100

A Simple, Extendable Markdown Renderer for Your Terminal

🎩 charMD

A simple, extendable markdown renderer for your terminal.

🚧 This module is in early developement, expect breaking changes 🚧

charMD enables you to render a markdown text into a string, which printed in the terminal provides a well formatted output, instead of plain text.

Showcase

Try it out

To see the general capabilities of this module run:

deno run https://deno.land/x/charmd/example.ts

To see, how a specific markdown gets rendered run:

deno run --allow-read https://deno.land/x/charmd/example.ts ./README.md

Usage

Simply import the module and call the renderMarkdown method with your markdown text.

import { renderMarkdown } from 'https://deno.land/x/charmd/mod.ts';

console.log(renderMarkdown('# Hello world 🌍!'));

🧩 Extensions

The module provides a way to extend it functionality with additional extensions, which can be provided in it’s options param.

An extension can implement any of the Extension interface’s methods, which are:

  • init: Called before AST generation, if a string is returned, it will override the input markdown for later extension’s init fn and processing steps.
  • postAST: Called with the generated AST’s root node, before any transformations
  • transformNode: Called with each node to do modifications on the node and it’s children in the AST.
  • postTransform: Called with root, after all the transformations ran for all nodes.
  • generateNode: Called with each node. It should return the string representation of the rendered node,if the extension handles that specific node, or void, if its not handled by the extension.
  • postGenerate: Called after the string representation is created.

A simple extension, that renders link with green and blue instead of the built-in cyan would look something like this:

const LinkExt = {
    generateNode(genFn, node: Node, parent: Node, options: Options) {
          if(node.type === 'link') {
            const linkText = node.children?.map(ch => genFn(ch, node, options)).join('') || '';
            const link = `Link with text '${colors.blue(linkText)}' points to ${colors.cyan(node.url!)}`
            return colors.green(link);
          }
      }
}

console.log(renderMarkdown(
    '[charMD](https://github.com/littletof/charmd)',
    { extensions: [LinkExt] }
));

Direct use - cli.ts

For direct use in the terminal run cli.ts:

deno run --allow-net https://deno.land/x/charmd/cli.ts -r https://raw.githubusercontent.com/denoland/deno/master/README.md

Or install it with deno install

It has three options:

  • -s for rendering a string directly: -s "# markdown string"
  • -l for rendering a local file: -l ./README.md
  • -r for rendering a remote file: -r https://raw.githubusercontent.com/denoland/deno/master/README.md

Permissions

The module itself requires no permissions to run.

If --unstable is provided, horizontal separators will consider the terminal’s width.

Limitations

  • No syntax highlight
  • No strikethrough or underline
  • No multiline tables cells
  • Possible hiccups with more complex markdowns

These could change in the future, but the aim is to keep the module’s complexity minimal.

Also, many of these should also be solvable using extensions.

Notes

  • The main functions are also exported from the module, so for example you can use the toAST function to get your ast for the markdown and process it yourself.

  • As its core, it currently uses mdast-util-from-markdown, to get the AST, you can also provide extensions to it in the options unstable mdast property.

  • This module’s core structure draws from @dephraims work with https://github.com/dephraiim/termd.

Contributions

Feedback and contributions are always welcome. Open an issue or a PR, or contact me on the Deno discord.

TODO

  • [x] fix lists
  • [x] remove dots from codeblock backgrounds
  • [x] links with images
  • [x] # Header with *italic*
  • [ ] tests
  • [ ] fmt, lint
  • [ ] strikethrough, underline and combinations
  • [ ] Look into alternatives for the AST generation.

Download Details:

Author: littletof

Source Code: https://github.com/littletof/charmd

#deno #node #nodejs #javascript

Jackson  Watson

Jackson Watson

1625649840

How to create a Simple Website with Markdown and Bash - Beyond Code Live 008

Tonight we’re going to marry our Markdown, Bash, Domain, and Server skills into a simple website!

Digital Ocean ($100 or 60 days Free): https://m.do.co/c/18ec10e74dae
Name.com: https://www.name.com/referral/13d0ac

Live Stream:
Facebook: https://facebook.com/coolaj86
YouTube: https://youtube.com/coolaj86
Twitch: https://twitch.tv/coolaj86

Follow Beyond Code:(Learn to Code in 15 Minutes a Day)
Facebook: https://www.facebook.com/beyondcodebootcamp
YouTube: https://www.youtube.com/channel/UC2KJHARTj6KRpKzLU1sVxBA
Twitter: https://twitter.com/_beyondcode

Follow Health, Wealth, Commitment
(Daily Lifestyle Chat)
Facebook: https://www.facebook.com/groups/5406824179391158
YouTube: https://www.youtube.com/channel/UCbw2SbqD0OofAEVF_T61wCQ

Facebook: https://facebook.com/coolaj86
YouTube: https://youtube.com/coolaj86
Twitch: https://twitch.tv/coolaj86

#softwaredevelopment #softwareengineer #webdevelopment #webdeveloper

#markdown #bash #softwareengineer #webdevelopment #webdeveloper #simple website