rustdoc: Represent item types as a small number in the search index.
Has negligible improvements with gzip, but saves about 7% without it. This also has an effect of changing the tie-breaking order of item types.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
@@ -24,6 +24,8 @@ use syntax::ast;
|
|||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
|
|
||||||
use clean;
|
use clean;
|
||||||
|
use html::item_type;
|
||||||
|
use html::item_type::ItemType;
|
||||||
use html::render;
|
use html::render;
|
||||||
use html::render::{cache_key, current_location_key};
|
use html::render::{cache_key, current_location_key};
|
||||||
|
|
||||||
@@ -172,17 +174,17 @@ fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool,
|
|||||||
},
|
},
|
||||||
|_cache| {
|
|_cache| {
|
||||||
Some((Vec::from_slice(fqn), match kind {
|
Some((Vec::from_slice(fqn), match kind {
|
||||||
clean::TypeStruct => "struct",
|
clean::TypeStruct => item_type::Struct,
|
||||||
clean::TypeEnum => "enum",
|
clean::TypeEnum => item_type::Enum,
|
||||||
clean::TypeFunction => "fn",
|
clean::TypeFunction => item_type::Function,
|
||||||
clean::TypeTrait => "trait",
|
clean::TypeTrait => item_type::Trait,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
|
fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
|
||||||
root: |&render::Cache, &[~str]| -> Option<~str>,
|
root: |&render::Cache, &[~str]| -> Option<~str>,
|
||||||
info: |&render::Cache| -> Option<(Vec<~str> , &'static str)>)
|
info: |&render::Cache| -> Option<(Vec<~str> , ItemType)>)
|
||||||
-> fmt::Result
|
-> fmt::Result
|
||||||
{
|
{
|
||||||
// The generics will get written to both the title and link
|
// The generics will get written to both the title and link
|
||||||
@@ -252,12 +254,12 @@ fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
|
|||||||
url.push_str("/");
|
url.push_str("/");
|
||||||
}
|
}
|
||||||
match shortty {
|
match shortty {
|
||||||
"mod" => {
|
item_type::Module => {
|
||||||
url.push_str(*fqp.last().unwrap());
|
url.push_str(*fqp.last().unwrap());
|
||||||
url.push_str("/index.html");
|
url.push_str("/index.html");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
url.push_str(shortty);
|
url.push_str(shortty.to_static_str());
|
||||||
url.push_str(".");
|
url.push_str(".");
|
||||||
url.push_str(*fqp.last().unwrap());
|
url.push_str(*fqp.last().unwrap());
|
||||||
url.push_str(".html");
|
url.push_str(".html");
|
||||||
|
|||||||
97
src/librustdoc/html/item_type.rs
Normal file
97
src/librustdoc/html/item_type.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Item types.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use clean;
|
||||||
|
|
||||||
|
/// Item type. Corresponds to `clean::ItemEnum` variants.
|
||||||
|
///
|
||||||
|
/// The search index uses item types encoded as smaller numbers which equal to
|
||||||
|
/// discriminants. JavaScript then is used to decode them into the original value.
|
||||||
|
/// Consequently, every change to this type should be synchronized to
|
||||||
|
/// the `itemTypes` mapping table in `static/main.js`.
|
||||||
|
#[deriving(Eq, Clone)]
|
||||||
|
pub enum ItemType {
|
||||||
|
Module = 0,
|
||||||
|
Struct = 1,
|
||||||
|
Enum = 2,
|
||||||
|
Function = 3,
|
||||||
|
Typedef = 4,
|
||||||
|
Static = 5,
|
||||||
|
Trait = 6,
|
||||||
|
Impl = 7,
|
||||||
|
ViewItem = 8,
|
||||||
|
TyMethod = 9,
|
||||||
|
Method = 10,
|
||||||
|
StructField = 11,
|
||||||
|
Variant = 12,
|
||||||
|
ForeignFunction = 13,
|
||||||
|
ForeignStatic = 14,
|
||||||
|
Macro = 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ItemType {
|
||||||
|
pub fn to_static_str(&self) -> &'static str {
|
||||||
|
match *self {
|
||||||
|
Module => "mod",
|
||||||
|
Struct => "struct",
|
||||||
|
Enum => "enum",
|
||||||
|
Function => "fn",
|
||||||
|
Typedef => "typedef",
|
||||||
|
Static => "static",
|
||||||
|
Trait => "trait",
|
||||||
|
Impl => "impl",
|
||||||
|
ViewItem => "viewitem",
|
||||||
|
TyMethod => "tymethod",
|
||||||
|
Method => "method",
|
||||||
|
StructField => "structfield",
|
||||||
|
Variant => "variant",
|
||||||
|
ForeignFunction => "ffi",
|
||||||
|
ForeignStatic => "ffs",
|
||||||
|
Macro => "macro",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Show for ItemType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
self.to_static_str().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Unsigned for ItemType {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
(*self as uint).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shortty(item: &clean::Item) -> ItemType {
|
||||||
|
match item.inner {
|
||||||
|
clean::ModuleItem(..) => Module,
|
||||||
|
clean::StructItem(..) => Struct,
|
||||||
|
clean::EnumItem(..) => Enum,
|
||||||
|
clean::FunctionItem(..) => Function,
|
||||||
|
clean::TypedefItem(..) => Typedef,
|
||||||
|
clean::StaticItem(..) => Static,
|
||||||
|
clean::TraitItem(..) => Trait,
|
||||||
|
clean::ImplItem(..) => Impl,
|
||||||
|
clean::ViewItemItem(..) => ViewItem,
|
||||||
|
clean::TyMethodItem(..) => TyMethod,
|
||||||
|
clean::MethodItem(..) => Method,
|
||||||
|
clean::StructFieldItem(..) => StructField,
|
||||||
|
clean::VariantItem(..) => Variant,
|
||||||
|
clean::ForeignFunctionItem(..) => ForeignFunction,
|
||||||
|
clean::ForeignStaticItem(..) => ForeignStatic,
|
||||||
|
clean::MacroItem(..) => Macro,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -52,6 +52,8 @@ use rustc::util::nodemap::NodeSet;
|
|||||||
use clean;
|
use clean;
|
||||||
use doctree;
|
use doctree;
|
||||||
use fold::DocFolder;
|
use fold::DocFolder;
|
||||||
|
use html::item_type;
|
||||||
|
use html::item_type::{ItemType, shortty};
|
||||||
use html::format::{VisSpace, Method, FnStyleSpace};
|
use html::format::{VisSpace, Method, FnStyleSpace};
|
||||||
use html::layout;
|
use html::layout;
|
||||||
use html::markdown;
|
use html::markdown;
|
||||||
@@ -138,7 +140,7 @@ pub struct Cache {
|
|||||||
/// URLs when a type is being linked to. External paths are not located in
|
/// URLs when a type is being linked to. External paths are not located in
|
||||||
/// this map because the `External` type itself has all the information
|
/// this map because the `External` type itself has all the information
|
||||||
/// necessary.
|
/// necessary.
|
||||||
pub paths: HashMap<ast::NodeId, (Vec<~str> , &'static str)>,
|
pub paths: HashMap<ast::NodeId, (Vec<~str> , ItemType)>,
|
||||||
|
|
||||||
/// This map contains information about all known traits of this crate.
|
/// This map contains information about all known traits of this crate.
|
||||||
/// Implementations of a crate should inherit the documentation of the
|
/// Implementations of a crate should inherit the documentation of the
|
||||||
@@ -193,7 +195,7 @@ struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, }
|
|||||||
/// Struct representing one entry in the JS search index. These are all emitted
|
/// Struct representing one entry in the JS search index. These are all emitted
|
||||||
/// by hand to a large JS file at the end of cache-creation.
|
/// by hand to a large JS file at the end of cache-creation.
|
||||||
struct IndexItem {
|
struct IndexItem {
|
||||||
ty: &'static str,
|
ty: ItemType,
|
||||||
name: ~str,
|
name: ~str,
|
||||||
path: ~str,
|
path: ~str,
|
||||||
desc: ~str,
|
desc: ~str,
|
||||||
@@ -311,7 +313,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
try!(write!(&mut w, ","));
|
try!(write!(&mut w, ","));
|
||||||
}
|
}
|
||||||
try!(write!(&mut w, "\\{ty:\"{}\",name:\"{}\",path:\"{}\",desc:{}",
|
try!(write!(&mut w, "\\{ty:{:u},name:\"{}\",path:\"{}\",desc:{}",
|
||||||
item.ty, item.name, item.path,
|
item.ty, item.name, item.path,
|
||||||
item.desc.to_json().to_str()));
|
item.desc.to_json().to_str()));
|
||||||
match item.parent {
|
match item.parent {
|
||||||
@@ -330,7 +332,7 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
try!(write!(&mut w, ","));
|
try!(write!(&mut w, ","));
|
||||||
}
|
}
|
||||||
try!(write!(&mut w, "\\{type:'{}',name:'{}'\\}",
|
try!(write!(&mut w, "\\{type:{:u},name:'{}'\\}",
|
||||||
short, *fqp.last().unwrap()));
|
short, *fqp.last().unwrap()));
|
||||||
}
|
}
|
||||||
try!(write!(&mut w, "];"));
|
try!(write!(&mut w, "];"));
|
||||||
@@ -622,12 +624,13 @@ impl DocFolder for Cache {
|
|||||||
} else {
|
} else {
|
||||||
let last = self.parent_stack.last().unwrap();
|
let last = self.parent_stack.last().unwrap();
|
||||||
let path = match self.paths.find(last) {
|
let path = match self.paths.find(last) {
|
||||||
Some(&(_, "trait")) =>
|
Some(&(_, item_type::Trait)) =>
|
||||||
Some(self.stack.slice_to(self.stack.len() - 1)),
|
Some(self.stack.slice_to(self.stack.len() - 1)),
|
||||||
// The current stack not necessarily has correlation for
|
// The current stack not necessarily has correlation for
|
||||||
// where the type was defined. On the other hand,
|
// where the type was defined. On the other hand,
|
||||||
// `paths` always has the right information if present.
|
// `paths` always has the right information if present.
|
||||||
Some(&(ref fqp, "struct")) | Some(&(ref fqp, "enum")) =>
|
Some(&(ref fqp, item_type::Struct)) |
|
||||||
|
Some(&(ref fqp, item_type::Enum)) =>
|
||||||
Some(fqp.slice_to(fqp.len() - 1)),
|
Some(fqp.slice_to(fqp.len() - 1)),
|
||||||
Some(..) => Some(self.stack.as_slice()),
|
Some(..) => Some(self.stack.as_slice()),
|
||||||
None => None
|
None => None
|
||||||
@@ -687,7 +690,7 @@ impl DocFolder for Cache {
|
|||||||
clean::VariantItem(..) => {
|
clean::VariantItem(..) => {
|
||||||
let mut stack = self.stack.clone();
|
let mut stack = self.stack.clone();
|
||||||
stack.pop();
|
stack.pop();
|
||||||
self.paths.insert(item.id, (stack, "enum"));
|
self.paths.insert(item.id, (stack, item_type::Enum));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -845,7 +848,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
title.push_str(" - Rust");
|
title.push_str(" - Rust");
|
||||||
let page = layout::Page {
|
let page = layout::Page {
|
||||||
ty: shortty(it),
|
ty: shortty(it).to_static_str(),
|
||||||
root_path: cx.root_path.as_slice(),
|
root_path: cx.root_path.as_slice(),
|
||||||
title: title.as_slice(),
|
title: title.as_slice(),
|
||||||
};
|
};
|
||||||
@@ -899,27 +902,6 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shortty(item: &clean::Item) -> &'static str {
|
|
||||||
match item.inner {
|
|
||||||
clean::ModuleItem(..) => "mod",
|
|
||||||
clean::StructItem(..) => "struct",
|
|
||||||
clean::EnumItem(..) => "enum",
|
|
||||||
clean::FunctionItem(..) => "fn",
|
|
||||||
clean::TypedefItem(..) => "typedef",
|
|
||||||
clean::StaticItem(..) => "static",
|
|
||||||
clean::TraitItem(..) => "trait",
|
|
||||||
clean::ImplItem(..) => "impl",
|
|
||||||
clean::ViewItemItem(..) => "viewitem",
|
|
||||||
clean::TyMethodItem(..) => "tymethod",
|
|
||||||
clean::MethodItem(..) => "method",
|
|
||||||
clean::StructFieldItem(..) => "structfield",
|
|
||||||
clean::VariantItem(..) => "variant",
|
|
||||||
clean::ForeignFunctionItem(..) => "ffi",
|
|
||||||
clean::ForeignStaticItem(..) => "ffs",
|
|
||||||
clean::MacroItem(..) => "macro",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Item<'a> {
|
impl<'a> Item<'a> {
|
||||||
fn ismodule(&self) -> bool {
|
fn ismodule(&self) -> bool {
|
||||||
match self.item.inner {
|
match self.item.inner {
|
||||||
@@ -1009,7 +991,7 @@ impl<'a> fmt::Show for Item<'a> {
|
|||||||
fn item_path(item: &clean::Item) -> ~str {
|
fn item_path(item: &clean::Item) -> ~str {
|
||||||
match item.inner {
|
match item.inner {
|
||||||
clean::ModuleItem(..) => *item.name.get_ref() + "/index.html",
|
clean::ModuleItem(..) => *item.name.get_ref() + "/index.html",
|
||||||
_ => shortty(item) + "." + *item.name.get_ref() + ".html"
|
_ => shortty(item).to_static_str() + "." + *item.name.get_ref() + ".html"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1095,13 +1077,13 @@ fn item_module(w: &mut Writer, cx: &Context,
|
|||||||
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
|
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
|
||||||
|
|
||||||
debug!("{:?}", indices);
|
debug!("{:?}", indices);
|
||||||
let mut curty = "";
|
let mut curty = None;
|
||||||
for &idx in indices.iter() {
|
for &idx in indices.iter() {
|
||||||
let myitem = &items[idx];
|
let myitem = &items[idx];
|
||||||
|
|
||||||
let myty = shortty(myitem);
|
let myty = Some(shortty(myitem));
|
||||||
if myty != curty {
|
if myty != curty {
|
||||||
if curty != "" {
|
if curty.is_some() {
|
||||||
try!(write!(w, "</table>"));
|
try!(write!(w, "</table>"));
|
||||||
}
|
}
|
||||||
curty = myty;
|
curty = myty;
|
||||||
@@ -1704,8 +1686,9 @@ impl<'a> fmt::Show for Sidebar<'a> {
|
|||||||
};
|
};
|
||||||
try!(write!(w, "<div class='block {}'><h2>{}</h2>", short, longty));
|
try!(write!(w, "<div class='block {}'><h2>{}</h2>", short, longty));
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
|
let curty = shortty(cur).to_static_str();
|
||||||
let class = if cur.name.get_ref() == item &&
|
let class = if cur.name.get_ref() == item &&
|
||||||
short == shortty(cur) { "current" } else { "" };
|
short == curty { "current" } else { "" };
|
||||||
try!(write!(w, "<a class='{ty} {class}' href='{curty, select,
|
try!(write!(w, "<a class='{ty} {class}' href='{curty, select,
|
||||||
mod{../}
|
mod{../}
|
||||||
other{}
|
other{}
|
||||||
@@ -1716,7 +1699,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
|
|||||||
ty = short,
|
ty = short,
|
||||||
tysel = short,
|
tysel = short,
|
||||||
class = class,
|
class = class,
|
||||||
curty = shortty(cur),
|
curty = curty,
|
||||||
name = item.as_slice()));
|
name = item.as_slice()));
|
||||||
}
|
}
|
||||||
try!(write!(w, "</div>"));
|
try!(write!(w, "</div>"));
|
||||||
@@ -1735,7 +1718,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
|
|||||||
fn build_sidebar(m: &clean::Module) -> HashMap<~str, Vec<~str> > {
|
fn build_sidebar(m: &clean::Module) -> HashMap<~str, Vec<~str> > {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
for item in m.items.iter() {
|
for item in m.items.iter() {
|
||||||
let short = shortty(item);
|
let short = shortty(item).to_static_str();
|
||||||
let myname = match item.name {
|
let myname = match item.name {
|
||||||
None => continue,
|
None => continue,
|
||||||
Some(ref s) => s.to_owned(),
|
Some(ref s) => s.to_owned(),
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
function execQuery(query, max, searchWords) {
|
function execQuery(query, max, searchWords) {
|
||||||
var valLower = query.query.toLowerCase(),
|
var valLower = query.query.toLowerCase(),
|
||||||
val = valLower,
|
val = valLower,
|
||||||
typeFilter = query.type,
|
typeFilter = itemTypeFromName(query.type),
|
||||||
results = [],
|
results = [],
|
||||||
split = valLower.split("::");
|
split = valLower.split("::");
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
for (var i = 0; i < nSearchWords; i += 1) {
|
for (var i = 0; i < nSearchWords; i += 1) {
|
||||||
if (searchWords[i] === val) {
|
if (searchWords[i] === val) {
|
||||||
// filter type: ... queries
|
// filter type: ... queries
|
||||||
if (!typeFilter || typeFilter === searchIndex[i].ty) {
|
if (typeFilter < 0 || typeFilter === searchIndex[i].ty) {
|
||||||
results.push({id: i, index: -1});
|
results.push({id: i, index: -1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
searchWords[j].replace(/_/g, "").indexOf(val) > -1)
|
searchWords[j].replace(/_/g, "").indexOf(val) > -1)
|
||||||
{
|
{
|
||||||
// filter type: ... queries
|
// filter type: ... queries
|
||||||
if (!typeFilter || typeFilter === searchIndex[j].ty) {
|
if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
|
||||||
results.push({id: j, index: searchWords[j].replace(/_/g, "").indexOf(val)});
|
results.push({id: j, index: searchWords[j].replace(/_/g, "").indexOf(val)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@
|
|||||||
|
|
||||||
shown.push(item);
|
shown.push(item);
|
||||||
name = item.name;
|
name = item.name;
|
||||||
type = item.ty;
|
type = itemTypes[item.ty];
|
||||||
|
|
||||||
output += '<tr class="' + type + ' result"><td>';
|
output += '<tr class="' + type + ' result"><td>';
|
||||||
|
|
||||||
@@ -427,7 +427,7 @@
|
|||||||
output += item.path + '::' + myparent.name +
|
output += item.path + '::' + myparent.name +
|
||||||
'::<a href="' + rootPath +
|
'::<a href="' + rootPath +
|
||||||
item.path.replace(/::/g, '/') +
|
item.path.replace(/::/g, '/') +
|
||||||
'/' + myparent.type +
|
'/' + itemTypes[myparent.type] +
|
||||||
'.' + myparent.name +
|
'.' + myparent.name +
|
||||||
'.html' + anchor +
|
'.html' + anchor +
|
||||||
'" class="' + type +
|
'" class="' + type +
|
||||||
@@ -505,6 +505,32 @@
|
|||||||
showResults(results);
|
showResults(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This mapping table should match the discriminants of
|
||||||
|
// `rustdoc::html::item_type::ItemType` type in Rust.
|
||||||
|
var itemTypes = ["mod",
|
||||||
|
"struct",
|
||||||
|
"enum",
|
||||||
|
"fn",
|
||||||
|
"typedef",
|
||||||
|
"static",
|
||||||
|
"trait",
|
||||||
|
"impl",
|
||||||
|
"viewitem",
|
||||||
|
"tymethod",
|
||||||
|
"method",
|
||||||
|
"structfield",
|
||||||
|
"variant",
|
||||||
|
"ffi",
|
||||||
|
"ffs",
|
||||||
|
"macro"];
|
||||||
|
|
||||||
|
function itemTypeFromName(typename) {
|
||||||
|
for (var i = 0; i < itemTypes.length; ++i) {
|
||||||
|
if (itemTypes[i] === typename) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
function buildIndex(rawSearchIndex) {
|
function buildIndex(rawSearchIndex) {
|
||||||
searchIndex = [];
|
searchIndex = [];
|
||||||
var searchWords = [];
|
var searchWords = [];
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ pub mod fold;
|
|||||||
pub mod html {
|
pub mod html {
|
||||||
pub mod highlight;
|
pub mod highlight;
|
||||||
pub mod escape;
|
pub mod escape;
|
||||||
|
pub mod item_type;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod markdown;
|
pub mod markdown;
|
||||||
|
|||||||
Reference in New Issue
Block a user