From 1fc5e7c01ab7addb7c96a8a5ed0bf02504b98830 Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Mon, 3 Apr 2023 23:35:18 +0800 Subject: [PATCH] Initialize chat block processor --- .../chat-block-processor/README.adoc | 105 ++++++++++++++++++ .../chat-block-processor/extension.rb | 55 +++++++++ lib/asciidoctor/foodogsquared-extensions.rb | 2 + 3 files changed, 162 insertions(+) create mode 100644 lib/asciidoctor/chat-block-processor/README.adoc create mode 100644 lib/asciidoctor/chat-block-processor/extension.rb diff --git a/lib/asciidoctor/chat-block-processor/README.adoc b/lib/asciidoctor/chat-block-processor/README.adoc new file mode 100644 index 0000000..fd1653e --- /dev/null +++ b/lib/asciidoctor/chat-block-processor/README.adoc @@ -0,0 +1,105 @@ += Chat block processor +:toc: + + +A link:https://docs.asciidoctor.org/asciidoctor/latest/extensions/block-processor/[block processor] that adds a a dialog box style to the block. +Exclusive to the HTML backend. + + +== Synopsis + +.... +[chat, $AVATARNAME, $AVATARSTATE, $ATTRS...] +==== +$CONTENT +==== +.... + +The avatar name is the name of the folder to be retrieved from the `avatarsdir` attribute. +The directory enforces a certain structure which can be seen in <>. + +Both the avatar name and the state are to be converted to snake case (e.g., `El Pablo` to `el_pablo`) for the image path. + + +== Attributes + +* `avatarsdir` is the folder containing the avatars' stickers. +This is explained in detail from the <> section. + +* `avatarstype` is similar to `icontype` attribute except this is used for the avatar stickers. +The default value is `webp`. + +* `state` is the sticker to be retrieved from the avatars directory. +It has a default value of `default`. +You could also use this attribute instead of the `$AVATARSTATE` positional argument for whatever reason. + +* `name` is the canonical name of the avatar. +This is used for titles and alts in the internal image block. +By default, this is the same as the given avatar. + + +[#extra-notes] +== Extra notes + +This component has some prerequisites for this to fully work specifically with `avatarsdir` attribute that contains a list of avatars and their stickers. +By default, this value is at the `avatars` subdirectory of the `iconsdir` attribute. +It is recommended to set this value yourself. ++ +-- +This enforces a certain structure where the root directory contains a list of folders representing the avatar with each of the folder containing stickers which represents their state. +For example, here's what `avatarsdir` could contain following the expected structure. + +[source] +---- +./static/icons/avatars/ +├── ezran/ +│ ├── crisis.webp +│ ├── default.webp +│ ├── sad.webp +│ └── shocked.webp +└── foodogsquared/ + ├── crisis.webp + ├── default.webp + ├── sad.webp + └── shocked.webp +---- +-- + + +== Example usage + +Let's assume `avatarsdir` is set to the `static/icons/avatars` with the following file structure. + +[source] +---- +./static/icons/avatars/ +├── ezran/ +│ ├── crisis.webp +│ ├── default.webp +│ ├── sad.webp +│ └── shocked.webp +├── el-pablo/ +│ ├── crisis.webp +│ ├── default.webp +│ ├── ghastly.webp +│ ├── melodramatic.webp +│ ├── sad.webp +│ └── shocked.webp +└── foodogsquared/ + ├── crisis.webp + ├── default.webp + ├── sad.webp + └── shocked.webp +---- + +- The following block should get the default image for `foodogsquared` which is in `./static/icons/avatars/foodogsquared/default.webp`. ++ +.... +[chat, foodogsquared] +==== +Hello there! +==== +.... + +- The following block should contain El Pablo's melodramatic dialog state. +Take note diff --git a/lib/asciidoctor/chat-block-processor/extension.rb b/lib/asciidoctor/chat-block-processor/extension.rb new file mode 100644 index 0000000..ea5d930 --- /dev/null +++ b/lib/asciidoctor/chat-block-processor/extension.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +class ChatBlock < Asciidoctor::Extensions::BlockProcessor + use_dsl + + named :chat + on_context :example + name_positional_attributes 'avatar', 'state' + default_attributes 'state' => 'default', 'avatarstype' => 'webp' + + def process(parent, reader, attrs) + block = create_block parent, :pass, nil, attrs, content_model: :compound + block.add_role('dialogblock') + + # You can think of this section as a pipeline constructing the HTML + # component for this block. Specifically, we're building one component that + # contains two output: the dialog image of our avatar and its content. + attrs['name'] ||= attrs['avatar'] + + block << (create_html_fragment block, %( +
+
+ )) + + attrs['avatarsdir'] ||= File.expand_path('./avatars', attrs['iconsdir']) + + avatar_sticker = "#{attrs['avatar'].to_snake}/#{attrs['state'].to_snake}.#{attrs['avatarstype']}" + avatar_img_attrs = { + 'target' => parent.image_uri(avatar_sticker, 'avatarsdir'), + 'alt' => attrs['name'] + } + avatar_imgblock = create_image_block block, avatar_img_attrs + + block << avatar_imgblock + block << (create_html_fragment block, %( +
+
+ )) + + parse_content block, reader + + block << (create_html_fragment block, %( +
+
+ )) + + block + end + + private + + def create_html_fragment(parent, html, attributes = nil) + create_block parent, :pass, html, attributes + end +end diff --git a/lib/asciidoctor/foodogsquared-extensions.rb b/lib/asciidoctor/foodogsquared-extensions.rb index 73dc9e4..4637e22 100644 --- a/lib/asciidoctor/foodogsquared-extensions.rb +++ b/lib/asciidoctor/foodogsquared-extensions.rb @@ -12,9 +12,11 @@ require_relative 'github-link-inline-macro/extension' require_relative 'github-raw-content-include-processor/extension' require_relative 'gitlab-link-inline-macro/extension' require_relative 'gitlab-raw-content-include-processor/extension' +require_relative 'chat-block-processor/extension' Asciidoctor::Extensions.register do inline_macro ManInlineMacro + block ChatBlock if @document.basebackend? 'html' inline_macro SWHInlineMacro include_processor SWHIDIncludeProcessor