or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-parser.mdindex.mdlinkify.mdrendering.mdrule-system.mdutilities.md

rule-system.mddocs/

0

# Rule System

1

2

Remarkable uses a sophisticated rule-based system for parsing markdown. The system consists of three main parsers (core, block, inline) each with their own set of configurable rules managed by Ruler instances.

3

4

## Capabilities

5

6

### Ruler Class

7

8

The Ruler class manages rule chains and execution order for parsing operations.

9

10

```javascript { .api }

11

/**

12

* Rule manager for organizing and controlling parsing rules

13

*/

14

class Ruler {

15

/** Add rule to the end of chain */

16

push(name: string, fn: RuleFunction, options?: RuleOptions): void;

17

/** Add rule before specified rule */

18

before(beforeName: string, ruleName: string, fn: RuleFunction, options?: RuleOptions): void;

19

/** Add rule after specified rule */

20

after(afterName: string, ruleName: string, fn: RuleFunction, options?: RuleOptions): void;

21

/** Replace rule function */

22

at(name: string, fn: RuleFunction, options?: RuleOptions): void;

23

/** Enable rules by name */

24

enable(names: string | string[], ignoreInvalid?: boolean): string[];

25

/** Disable rules by name */

26

disable(names: string | string[], ignoreInvalid?: boolean): string[];

27

/** Get active rules for chain */

28

getRules(chainName: string): RuleFunction[];

29

}

30

31

interface RuleOptions {

32

/** Alternative rule names this rule can replace */

33

alt?: string[];

34

}

35

36

type RuleFunction = (state: StateCore | StateBlock | StateInline) => boolean | void;

37

```

38

39

**Usage Examples:**

40

41

```javascript

42

import { Remarkable } from "remarkable";

43

44

const md = new Remarkable();

45

46

// Add custom rule to block parser

47

md.block.ruler.push('custom_block', function(state, start, end, silent) {

48

// Custom block parsing logic

49

return false;

50

});

51

52

// Insert rule before 'paragraph'

53

md.block.ruler.before('paragraph', 'custom_before', customRule);

54

55

// Enable/disable rules

56

md.core.ruler.enable(['abbr', 'footnote_tail']);

57

md.inline.ruler.disable(['autolink']);

58

```

59

60

### Core Parser Rules

61

62

Core processing rules that handle document-level operations.

63

64

```javascript { .api }

65

interface CoreRules {

66

/** Process block-level elements */

67

block: RuleFunction;

68

/** Process inline elements within blocks */

69

inline: RuleFunction;

70

/** Resolve link references */

71

references: RuleFunction;

72

/** Apply typographic replacements */

73

replacements: RuleFunction;

74

/** Apply smart quotes */

75

smartquotes: RuleFunction;

76

/** Process abbreviations */

77

abbr: RuleFunction;

78

/** Finalize abbreviation processing */

79

abbr2: RuleFunction;

80

/** Process footnote tails */

81

footnote_tail: RuleFunction;

82

}

83

```

84

85

**Default Core Rule Chain:**

86

1. `block` - Parse block elements

87

2. `inline` - Parse inline elements

88

3. `references` - Resolve references

89

4. `replacements` - Typography replacements

90

5. `smartquotes` - Smart quotes

91

6. `abbr2` - Finalize abbreviations

92

7. `footnote_tail` - Process footnotes

93

94

### Block Parser Rules

95

96

Rules for parsing block-level markdown elements.

97

98

```javascript { .api }

99

interface BlockRules {

100

/** Code blocks (indented) */

101

code: RuleFunction;

102

/** Fenced code blocks */

103

fences: RuleFunction;

104

/** Blockquotes */

105

blockquote: RuleFunction;

106

/** Horizontal rules */

107

hr: RuleFunction;

108

/** Lists (ordered and unordered) */

109

list: RuleFunction;

110

/** Footnote definitions */

111

footnote: RuleFunction;

112

/** ATX headings (# ## ###) */

113

heading: RuleFunction;

114

/** Setext headings (underlined) */

115

lheading: RuleFunction;

116

/** HTML blocks */

117

htmlblock: RuleFunction;

118

/** Tables */

119

table: RuleFunction;

120

/** Definition lists */

121

deflist: RuleFunction;

122

/** Paragraphs */

123

paragraph: RuleFunction;

124

}

125

```

126

127

**Default Block Rule Chain:**

128

1. `code` - Indented code blocks

129

2. `fences` - Fenced code blocks

130

3. `blockquote` - Blockquotes

131

4. `hr` - Horizontal rules

132

5. `list` - Lists

133

6. `footnote` - Footnote definitions

134

7. `heading` - ATX headings

135

8. `lheading` - Setext headings

136

9. `htmlblock` - HTML blocks

137

10. `table` - Tables

138

11. `deflist` - Definition lists

139

12. `paragraph` - Paragraphs

140

141

### Inline Parser Rules

142

143

Rules for parsing inline markdown elements.

144

145

```javascript { .api }

146

interface InlineRules {

147

/** Plain text */

148

text: RuleFunction;

149

/** Line breaks */

150

newline: RuleFunction;

151

/** Escape sequences */

152

escape: RuleFunction;

153

/** Code spans */

154

backticks: RuleFunction;

155

/** Strikethrough */

156

del: RuleFunction;

157

/** Insert/underline */

158

ins: RuleFunction;

159

/** Mark/highlight */

160

mark: RuleFunction;

161

/** Bold and italic */

162

emphasis: RuleFunction;

163

/** Subscript */

164

sub: RuleFunction;

165

/** Superscript */

166

sup: RuleFunction;

167

/** Links and images */

168

links: RuleFunction;

169

/** Inline footnotes */

170

footnote_inline: RuleFunction;

171

/** Footnote references */

172

footnote_ref: RuleFunction;

173

/** Autolinks <url> */

174

autolink: RuleFunction;

175

/** HTML tags */

176

htmltag: RuleFunction;

177

/** HTML entities */

178

entity: RuleFunction;

179

}

180

```

181

182

**Default Inline Rule Chain:**

183

1. `text` - Plain text

184

2. `newline` - Line breaks

185

3. `escape` - Escape sequences

186

4. `backticks` - Code spans

187

5. `del` - Strikethrough

188

6. `ins` - Insert/underline

189

7. `mark` - Mark/highlight

190

8. `emphasis` - Bold/italic

191

9. `sub` - Subscript

192

10. `sup` - Superscript

193

11. `links` - Links and images

194

12. `footnote_inline` - Inline footnotes

195

13. `footnote_ref` - Footnote references

196

14. `autolink` - Autolinks

197

15. `htmltag` - HTML tags

198

16. `entity` - HTML entities

199

200

### Custom Rule Development

201

202

Creating custom parsing rules for extending Remarkable functionality.

203

204

```javascript { .api }

205

/**

206

* State objects passed to rule functions

207

*/

208

interface StateCore {

209

src: string;

210

env: object;

211

options: RemarkableOptions;

212

tokens: Token[];

213

inlineMode: boolean;

214

inline: ParserInline;

215

block: ParserBlock;

216

renderer: Renderer;

217

}

218

219

interface StateBlock {

220

src: string;

221

md: Remarkable;

222

env: object;

223

tokens: Token[];

224

bMarks: number[];

225

eMarks: number[];

226

tShift: number[];

227

sCount: number[];

228

blkIndent: number;

229

line: number;

230

lineMax: number;

231

tight: boolean;

232

parentType: string;

233

ddIndent: number;

234

getLines(begin: number, end: number, indent: number, keepLastLF: boolean): string;

235

isEmpty(line: number): boolean;

236

skipEmptyLines(from: number): number;

237

skipSpaces(pos: number): number;

238

skipChars(pos: number, code: number): number;

239

skipCharsBack(pos: number, code: number, min: number): number;

240

push(token: Token): void;

241

}

242

243

interface StateInline {

244

src: string;

245

env: object;

246

md: Remarkable;

247

tokens: Token[];

248

pos: number;

249

posMax: number;

250

level: number;

251

pending: string;

252

pendingLevel: number;

253

cache: object;

254

delimiters: object[];

255

push(token: Token): void;

256

pushPending(): Token;

257

scanDelims(start: number, canSplitWord: boolean): object;

258

}

259

```

260

261

**Usage Examples:**

262

263

```javascript

264

// Custom block rule for special containers

265

function customContainer(state, start, end, silent) {

266

const marker = ':::';

267

let pos = state.bMarks[start] + state.tShift[start];

268

let max = state.eMarks[start];

269

270

// Check for marker

271

if (pos + marker.length > max) return false;

272

if (state.src.slice(pos, pos + marker.length) !== marker) return false;

273

274

if (silent) return true;

275

276

// Find closing marker

277

let nextLine = start + 1;

278

let found = false;

279

280

while (nextLine < end) {

281

pos = state.bMarks[nextLine] + state.tShift[nextLine];

282

max = state.eMarks[nextLine];

283

284

if (state.src.slice(pos, pos + marker.length) === marker) {

285

found = true;

286

break;

287

}

288

nextLine++;

289

}

290

291

if (!found) return false;

292

293

// Create tokens

294

const token_o = state.push({ type: 'container_open', level: state.level++ });

295

const token_c = state.push({ type: 'container_close', level: --state.level });

296

297

token_o.map = [start, nextLine];

298

token_c.map = [nextLine, nextLine + 1];

299

300

state.line = nextLine + 1;

301

return true;

302

}

303

304

// Add the rule

305

md.block.ruler.before('paragraph', 'container', customContainer);

306

```

307

308

### Rule Configuration

309

310

Configuring which rules are active through presets and manual configuration.

311

312

```javascript { .api }

313

interface PresetConfig {

314

options?: RemarkableOptions;

315

components?: {

316

core?: { rules: string[] };

317

block?: { rules: string[] };

318

inline?: { rules: string[] };

319

};

320

}

321

```

322

323

**Usage Examples:**

324

325

```javascript

326

// Enable specific rules only

327

md.configure({

328

components: {

329

core: { rules: ['block', 'inline'] },

330

block: { rules: ['paragraph', 'heading', 'list'] },

331

inline: { rules: ['text', 'emphasis', 'links'] }

332

}

333

});

334

335

// Enable/disable individual rules

336

md.block.ruler.enable(['table', 'footnote']);

337

md.inline.ruler.disable(['autolink', 'htmltag']);

338

```