Smart Page API

基本逻辑

1. 应用

一篇 Markdown 文档需要成为一个 SmartPage,必须要在 metadata 的声明中,使用app: page,这样系统最终才会使用 Smart Page 的逻辑完成全文的渲染。
当然,如果直接使用可视化的界面生成的 SmartPage,最终也是一个内部声明了 app: page 的 Markdown 文档。

2. 声明与匹配

Smart Page 实际上由多个片段组成的,不同片段可以呈现不同的模板。
// cover// cover(layout="lr", more_links_label="Download") 作为单独一行,作为一个 Smart Page 一部分的头部声明。
比如 cover 这个意思是使用 /template/cover.jade来渲染当前的片段,layout="lr", more_links_label="Download"则是作为额外的参数传递给/template/cover.jade完成渲染。

3. 样式微调

// cover
```css
p {line-height: 3.5 !important}
```
紧跟一个片段的头部声明之后,可以是一个css的代码片段,这个是对当前片段最终的 HTML 页面样式的微调。

模板将处理的参数

dom_id

这是一个随机生成的 id,一般可以作为 Dom 的 id,以方便 javascript 的调用 (如果有需要)。

parts_count

类型为整数,表示当前页面是由几个 Layout 共同的组成的。

humech (核心数据参数)

在后面的文档具体说明,是 SmartPage 中承载页面结构后的数据对象。

其它额外参数

// cover(layout="lr", more_links_label="Download")
额外参数是使用者使用时额外指定的,比如上行这样的声明,就会额外传递layoutmore_links_label这两个参数,以供模板调用。

humech的构建逻辑

这是将 Markdown 内容重新解析,从而获得的结构化数据,再通过模板的逻辑,渲染为新的 HTML 片段。
humech 分割的依据是层级标题

举例

hello world, head

## title 1
content1

## title2
content2

### I am a sub title
sub content

如上,大抵最终会分解为<head>, <children:[title1, title2]>

子属性

head: dict 型, 是 head 的原始内容解析后的结果。
children: list型,每个 child 和 head 一样,都是 dict 型,是内容的解构后相应的信息。
注意: head 以及 children 的组成 child 数据,都视为一个humech 对象,下文将做具体说明。

humech 对象

humech 对象是指一个具体的内容片段,进行分析后,形成的描述性信息数据。它本身是一个 dict 类型的数据。

content

形成 humech 对象的原始内容,默认为 HTML 格式。

words

content 的总字数,英文单词计为1,中日韩一字计为1,类型为整数

title

以 h1-h6 的标题层级分割时,标题的文本,(如果是 head 对象时,也可能为空)。

links

当前片段内包含的超级链接,类型为一个列表。
每个 link 都是 dict 类型,一般有以下属性:
text: 相当于 link的 innerHTML
href: 跳转的 URL
title: A类型 DOM元素的 title 属性
alt: A类型 DOM元素的 alt 属性
class: A类型 DOM元素的 class 属性
.etc

links_count

整数,即 links 包含几个元素。

images

当前片段内包含的图片,类型为一个列表。
每个 image 都是 dict 类型,一般有以下属性:
src: 图片的实际 URL 地址
title: IMG 类型 DOM元素的 title 属性
alt: IMG 类型 DOM元素的 alt 属性
class: IMG 类型 DOM元素的 class 属性
.etc

images_count

整数,即 images 包含几个元素。

lazy_list

如果内容片段内每一行都是key: value 的形式,可以提取到 lazy_list。是一个ListItem对象,该对象的数据类型为 dict。

lists

内容片段内,有序、无序列表分析得到的结构,类型为 list, 每个子元素本身是一个 dict 类型数据,也是一个ListItem对象。

head

当前内容片段分解后,仍然是 head+children 的结构,本身也是一个 humech 对象,相当于递归。不会出现 head.head 的情况,仅会出现 child.head的情况。

children

当前内容片段分解后,仍然是 head+children 的结构,children 的组成 child本身也是一个 humech 对象,相当于递归。也可能是空列表。

ListItem 对象

这是 ul/ol 分解获得的信息对象,也可能是 lazylist 自动推断获取的。
ListItem 是一个 dict 类型,有两个属性,elementsmeta

elements

elements是一个 list, 每个element是一个 dict 类型,视为 ListElement对象

meta

meta是一个 dict 类型,是描述 elements 中的属性,有以下属性:
key_is_number: 每个 element 的 key 都是 float or int 类型
value_is_number: 每个 element 的 value 都是 float or int 类型
has_values: 每个 element 的 sub_values 这个属性不为空

ListElement 对象

key

比如一个 element 的原始文本是key: value ,那么 key 的值就是 key

value

比如一个 element 的原始文本是key: value ,那么 value 的值就是 value

sub_values

这是一个 list 类型,可能为空。
比如一个 element 的原始文本是key: value @sub_value1 @sub_value2 ,那么 sub_values 就是['sub_value1', 'sub_value2']

extra

一个 dict 类型,是对当前 element 的特别属性补充。比如key(extra1=1, extra2=2): value, 就可以获得两个额外的参数 extra1 & extra2。

content

这个是 ul/ol 分解后特有的属性,lazy_list内的一个 element 并不会有这个属性,是一个 li 的原始内容,相当于 li 的 innerTEXT。
如果是 ul/ol 分解后的 element,也可能没有 key、value、sub_values、extra 四个属性。

其它解构属性

imagesimages_countlinkslinks_count是 ul/ol 分解的信息中可能存在的字段,跟humech 对象中的同名的类型、子属性一致。

限制

Smart Page 在解构 humech 对象的行为,会消耗比较多的计算资源,同时也会产生冗余几倍的存储空间,为了保证的基础性能,会有些限制:

  1. 单个片段不能超过 5000 字符;
  2. 如果完整文章作为一个 humech 的全生成 (比如fullpage/slide),全文不超过20000字符。
  3. 由于 Smart Page 本身会在一个完整的页面内会揉和很多不同的片段,引入当前片段的样式(scss、css)文件时,务必保证namespace 上的相对唯一性,避免产生对其它片段的干扰。

附件 Demo

Smart Page,或者说 humech,看起来比较复杂,也需要一点时间理解它的运作机制。但实际上的一个模板代码量一般都比较小……
点击下载附件smartpage.zip,可以下载得到系统内置的几个 Smart Page 模板 (样式文件是特别分离的),再放到自己的 template 内再尝试,或许就更容易理解了。