or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

backends.mdcli.mdconfig.mdindex.mdpreprocessors.mdutils.md

config.mddocs/

0

# Configuration System

1

2

Foliant's configuration system provides flexible YAML-based project configuration with extensible tag support for includes, path resolution, and environment variables. The modular parser architecture allows custom configuration features through plugin extensions.

3

4

## Capabilities

5

6

### Main Configuration Parser

7

8

Dynamic parser class that inherits from all available configuration parsers, providing unified access to all configuration features.

9

10

```python { .api }

11

class Parser(*get_available_config_parsers().values()):

12

"""

13

Main configuration parser that combines all available parsers.

14

Provides unified interface for parsing foliant.yml files.

15

"""

16

```

17

18

### Base Configuration Parser

19

20

Foundation class for all configuration parsers providing core YAML parsing functionality.

21

22

```python { .api }

23

class BaseParser:

24

"""Base configuration parser with core YAML functionality."""

25

26

_defaults = {

27

'src_dir': Path('./src'),

28

'tmp_dir': Path('./__folianttmp__')

29

}

30

31

def __init__(self, project_path: Path, config_file_name: str,

32

logger: Logger, quiet: bool = False):

33

"""

34

Initialize configuration parser.

35

36

Parameters:

37

- project_path (Path): Path to project directory

38

- config_file_name (str): Name of configuration file

39

- logger (Logger): Logger instance for parsing messages

40

- quiet (bool): Suppress parsing output

41

"""

42

43

def parse(self) -> dict:

44

"""

45

Parse configuration file into Python dictionary.

46

Applies defaults and converts paths to Path objects.

47

48

Returns:

49

dict: Parsed configuration with defaults applied

50

51

Raises:

52

FileNotFoundError: If configuration file not found

53

yaml.YAMLError: If YAML parsing fails

54

"""

55

```

56

57

### Include Parser

58

59

Handles `!include` YAML tags for including external configuration files or sections.

60

61

```python { .api }

62

class Parser(BaseParser):

63

"""Parser for !include YAML tags."""

64

65

def _resolve_include_tag(self, _, node) -> str | dict:

66

"""

67

Replace !include tag with content from referenced file.

68

69

Supports two formats:

70

- !include file.yml (includes entire file)

71

- !include file.yml#section (includes specific section)

72

73

Parameters:

74

- _ (unused): YAML loader parameter

75

- node: YAML node containing include path

76

77

Returns:

78

str | dict: Content from included file

79

80

Raises:

81

ValueError: If include syntax has more than one # separator

82

FileNotFoundError: If included file not found

83

"""

84

85

def __init__(self, *args, **kwargs):

86

"""

87

Initialize include parser and register !include constructor.

88

89

Parameters:

90

- *args: Arguments passed to BaseParser

91

- **kwargs: Keyword arguments passed to BaseParser

92

"""

93

```

94

95

### Path Parser

96

97

Handles path-related YAML tags for flexible path resolution relative to project directory.

98

99

```python { .api }

100

class Parser(BaseParser):

101

"""Parser for path-related YAML tags."""

102

103

def _resolve_path_tag(self, _, node) -> str:

104

"""

105

Convert !path tag to absolute POSIX path.

106

Relative paths are resolved relative to project directory.

107

108

Parameters:

109

- _ (unused): YAML loader parameter

110

- node: YAML node containing path value

111

112

Returns:

113

str: Absolute POSIX path

114

115

Raises:

116

FileNotFoundError: If path does not exist (strict=True)

117

"""

118

119

def _resolve_project_path_tag(self, _, node) -> Path:

120

"""

121

Convert !project_path tag to absolute path relative to project.

122

Does not check for file existence.

123

124

Parameters:

125

- _ (unused): YAML loader parameter

126

- node: YAML node containing path value

127

128

Returns:

129

Path: Absolute path object

130

"""

131

132

@staticmethod

133

def _resolve_rel_path_tag(_, node) -> Path:

134

"""

135

Convert !rel_path tag to Path object without resolution.

136

137

Parameters:

138

- _ (unused): YAML loader parameter

139

- node: YAML node containing path value

140

141

Returns:

142

Path: Path object from node value

143

"""

144

145

def __init__(self, *args, **kwargs):

146

"""

147

Initialize path parser and register path-related constructors.

148

149

Parameters:

150

- *args: Arguments passed to BaseParser

151

- **kwargs: Keyword arguments passed to BaseParser

152

"""

153

```

154

155

### Environment Variable Parser

156

157

Handles `!env` YAML tags for including environment variable values in configuration.

158

159

```python { .api }

160

class Parser(BaseParser):

161

"""Parser for !env YAML tags."""

162

163

@staticmethod

164

def _resolve_env_tag(_, node) -> str | int | bool | dict | list | None:

165

"""

166

Replace !env tag with environment variable value.

167

168

Parameters:

169

- _ (unused): YAML loader parameter

170

- node: YAML node containing environment variable name

171

172

Returns:

173

Any: Environment variable value parsed as YAML, or None if not found

174

"""

175

176

def __init__(self, *args, **kwargs):

177

"""

178

Initialize environment parser and register !env constructor.

179

180

Parameters:

181

- *args: Arguments passed to BaseParser

182

- **kwargs: Keyword arguments passed to BaseParser

183

"""

184

```

185

186

## Usage Examples

187

188

### Basic Configuration Parsing

189

190

```python

191

from foliant.config import Parser

192

from pathlib import Path

193

import logging

194

195

# Set up logger

196

logger = logging.getLogger('foliant')

197

198

# Parse configuration

199

parser = Parser(

200

project_path=Path('./my-project'),

201

config_file_name='foliant.yml',

202

logger=logger,

203

quiet=False

204

)

205

206

config = parser.parse()

207

print(f"Source directory: {config['src_dir']}")

208

print(f"Temp directory: {config['tmp_dir']}")

209

print(f"Project title: {config.get('title', 'Untitled')}")

210

```

211

212

### Configuration with Include Tags

213

214

Example `foliant.yml`:

215

```yaml

216

title: My Documentation

217

chapters:

218

- !include chapters.yml

219

preprocessors:

220

- !include config/preprocessors.yml#development

221

```

222

223

Example usage:

224

```python

225

from foliant.config import Parser

226

from pathlib import Path

227

import logging

228

229

parser = Parser(Path('.'), 'foliant.yml', logging.getLogger())

230

config = parser.parse()

231

232

# chapters.yml and preprocessors.yml content is merged

233

print(config['chapters'])

234

print(config['preprocessors'])

235

```

236

237

### Configuration with Path Tags

238

239

Example `foliant.yml`:

240

```yaml

241

title: Documentation

242

src_dir: !path ./sources

243

custom_path: !project_path ./assets/images

244

relative_path: !rel_path ./templates

245

```

246

247

Example usage:

248

```python

249

config = parser.parse()

250

251

# Paths are resolved appropriately

252

print(config['src_dir']) # Absolute path to ./sources

253

print(config['custom_path']) # Absolute path to ./assets/images

254

print(config['relative_path']) # Path object for ./templates

255

```

256

257

### Configuration with Environment Variables

258

259

Example `foliant.yml`:

260

```yaml

261

title: !env PROJECT_TITLE

262

debug: !env DEBUG_MODE

263

api_key: !env API_KEY

264

```

265

266

Example usage:

267

```python

268

import os

269

270

# Set environment variables

271

os.environ['PROJECT_TITLE'] = 'My Project'

272

os.environ['DEBUG_MODE'] = 'true'

273

os.environ['API_KEY'] = 'secret123'

274

275

config = parser.parse()

276

print(config['title']) # 'My Project'

277

print(config['debug']) # True (parsed as YAML boolean)

278

print(config['api_key']) # 'secret123'

279

```

280

281

### Custom Configuration Parser

282

283

```python

284

from foliant.config.base import BaseParser

285

from yaml import add_constructor

286

287

class CustomParser(BaseParser):

288

"""Custom parser with additional YAML tags."""

289

290

def _resolve_custom_tag(self, _, node):

291

"""Handle custom !mytag syntax."""

292

return f"processed: {node.value}"

293

294

def __init__(self, *args, **kwargs):

295

super().__init__(*args, **kwargs)

296

add_constructor('!mytag', self._resolve_custom_tag)

297

298

# Use custom parser

299

parser = CustomParser(Path('.'), 'foliant.yml', logger)

300

config = parser.parse()

301

```

302

303

## Configuration File Structure

304

305

Default configuration structure:

306

```yaml

307

# Required

308

title: Project Title

309

310

# Optional with defaults

311

src_dir: ./src # Source directory

312

tmp_dir: ./__folianttmp__ # Temporary build directory

313

314

# Backend configuration

315

backend_config:

316

mkdocs:

317

theme: material

318

pandoc:

319

template: custom.tex

320

321

# Preprocessors

322

preprocessors:

323

- includes

324

- plantuml:

325

format: png

326

327

# Custom settings

328

chapters:

329

- index.md

330

- guide.md

331

```