{"id":24083355,"url":"https://github.com/mitranim/foliant","last_synced_at":"2026-06-13T11:31:16.938Z","repository":{"id":28681749,"uuid":"32201609","full_name":"mitranim/foliant","owner":"mitranim","description":"[NEEDS REWRITE] Generator of random synthetic words or names","archived":false,"fork":false,"pushed_at":"2015-10-18T15:54:05.000Z","size":196,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-24T06:44:38.525Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mitranim.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-14T08:00:58.000Z","updated_at":"2017-04-11T08:02:30.000Z","dependencies_parsed_at":"2022-08-02T12:12:23.304Z","dependency_job_id":null,"html_url":"https://github.com/mitranim/foliant","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Ffoliant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Ffoliant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Ffoliant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Ffoliant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mitranim","download_url":"https://codeload.github.com/mitranim/foliant/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240959115,"owners_count":19884911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-09T23:56:26.956Z","updated_at":"2026-06-13T11:31:11.918Z","avatar_url":"https://github.com/mitranim.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Description\n\nGenerator of random synthetic words or names. Port\n[`from Go`](https://github.com/Mitranim/codex). Takes sample words, analyses\nthem, and lazily produces a set of similar derived words. Works for\n[any language](#traitsexamine).\n\nPackaged in a format compatible with CommonJS / Node.js and AngularJS.\n\n## Contents\n\n* [Description](#description)\n* [Contents](#contents)\n* [Installation](#installation)\n* [Usage](#usage)\n* [API Reference](#api-reference)\n  * [Traits](#traits)\n    * [Traits#examine](#traitsexamine)\n    * [Traits#generator](#traitsgenerator)\n* [ToDo / WIP](#todo--wip)\n\n## Installation\n\n### CommonJS\n\nIn a shell:\n\n```sh\nnpm i --save foliant\n# or\nnpm i --save-dev foliant\n```\n\nIn your program:\n\n```javascript\nvar Traits = require('foliant')\n```\n\n### AngularJS\n\nAssuming you have a [bower](http://bower.io)-centric build system, in a shell:\n\n```sh\nbower i --save foliant\n# or\nbower i --save-dev foliant\n```\n\nIn your program:\n\n```javascript\nangular.module('MyGenerator', ['foliant'])\n.factory('MyGenerator', ['Traits', function(Traits) {\n  /* do things with Traits */\n}])\n```\n\nfoliant depends on [lodash](http://lodash.com), so make sure you have `window._`\navailable. It's specified as a bower dependency, but not bundled. You might want\nto use [`main-bower-files`](https://github.com/ck86/main-bower-files) to\nautomatically read dependencies and organise their order.\n\n## Usage\n\n```javascript\n// Examine source words and get their shared traits.\nvar traits = new Traits(['several', 'source', 'words'])\nvar gen = traits.generator()\n\n// Print twelve random results.\nfor (var i = 0; i \u003c 12; i++) {\n  console.log(gen())\n}\n\n/*\nworal\nordora\neverdo\nverdser\nverand\nandora\nandoran\nveral\nsever\nrandser\nseral\nveran\n*/\n\n// Find out how many words may be derived from this sample.\nvar gen = traits.generator()\ni = 0\nwhile (gen()) i++\nconsole.log(i)\n// -\u003e 213\n```\n\nExample with names:\n\n```javascript\n// Examine source names and get their shared traits.\nvar traits = new Traits(['jasmine', 'katie', 'nariko', 'karen'])\nvar gen = traits.generator()\n\n// Print twelve random results.\nfor (var i = 0; i \u003c 12; i++) {\n  console.log(gen())\n}\n\n/*\njarik\nsmiko\nikatik\narinat\nnasmin\nkatie\nrikatin\nsmikas\nminena\nikatin\njasmika\nrinaren\n*/\n\n// Find out how many names may be derived from this sample.\nvar gen = traits.generator()\ni = 0\nwhile (gen()) i++\nconsole.log(i)\n// -\u003e 428\n```\n\nTo run tests, clone the repo, `cd` to its directory, run `npm i`, and use:\n\n```sh\nnpm test\n```\n\nTo watch files and rerun tests while tinkering with the source, use:\n\n```sh\nnpm run autotest\n```\n\nTo run benchmarks:\n\n```sh\nnode bench/index.bench.js\n```\n\n## API Reference\n\n### `Traits`\n\nThe `Traits` class is the package's entry point.\n\n```javascript\n// Transcript of the constructor, using ES5 syntax for accessibility.\nfunction Traits(words) {\n  // Minimum and maximum number of sounds.\n  this.minNSounds = 0\n  this.maxNSounds = 0\n  // Minimum and maximum number of vowels.\n  this.minNVowels = 0\n  this.maxNVowels = 0\n  // Maximum number of consequtive vowels.\n  this.maxConseqVow = 0\n  // Maximum number of consequtive consonants.\n  this.maxConseqCons = 0\n  // Set of sounds that occur in the words.\n  this.soundSet = new StringSet()\n  // Set of pairs of sounds that occur in the words.\n  this.pairSet = new PairSet()\n\n  // Replacement sound set to use instead of the default `knownSounds`.\n  this.knownSounds = null\n  // Replacement sound set to use instead of the default `knownVowels`.\n  this.knownVowels = null\n\n  if (words instanceof Array) this.examine(words)\n}\n```\n\n`Traits` represent rudimental characteristics of a word or group of words. A\ntraits object unequivocally defines a set of synthetic words that may be derived\nfrom it.\n\nThe constructor optionally takes existing words as input and examines them with\n[`Traits#examine()`](#traitsexamine). The resulting characteristics are assigned to the newly created Traits object. Words must consist of known glyphs, as\ndefined by the default\n[sound sets](https://github.com/Mitranim/foliant/blob/master/src/index.js#L463)\nor by custom sets assigned to a traits object (see below). If an invalid word\nis encountered, an error is thrown.\n\nThe optional fields `knownSounds` and `knownVowels` specify custom sets of\nsounds and vowels. This lets you use `foliant` with any character set,\nincluding non-Latin alphabets.\n\n#### `Traits#examine()`\n\nAnalyses the given words and merges their characteristics into self.\n\n```javascript\nvar traits = new Traits()\ntraits.examine(['mountain', 'waterfall', 'grotto'])\n```\n\nBy default, this uses the sets of known sounds and vowels defined in\n[index.js](https://github.com/Mitranim/foliant/blob/master/src/index.js#L463).\nThis includes the 26 letters of the standard US English alphabet and some\ncommon digraphs like `th`, which are treated as single phonemes.\n\nHowever, `foliant` is language-independent. Assign custom `knownSounds` and\n`knownVowels` to teach it a sound system of your choosing. It can be Greek or\nCyrillic or Elvish or Clingon — doesn't matter as long as the given sounds and\nvowels cover the words in your input. Refer to\n[index.js](https://github.com/Mitranim/foliant/blob/master/src/index.js#L463)\nas an example.\n\nHere's how to teach it Greek:\n\n```javascript\nvar traits = new Traits()\n\ntraits.knownSounds = new Traits.StringSet([\n  'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ',\n  'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'ς', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'\n])\n\ntraits.knownVowels = new Traits.StringSet([\n  'α', 'ε', 'η', 'ι', 'ο', 'υ', 'ω'\n])\n\ntraits.examine(['ελ', 'διδασκω', 'ελληνικο', 'αλφαβητο'])\n\nvar gen = traits.generator()\nfor (var word = gen(); word != ''; word = gen()) {\n  console.log(word)\n}\n\n// ιδαλφ\n// κο\n// ηνικο\n// ...\n```\n\n#### `Traits#generator()`\n\nCreates a generator function that yields a new random synthetic word on each\ncall. The words are guaranteed to never repeat, and to be randomly distributed\nacross the total set of possible words for these traits.\n\nAfter a generator is exhausted, subsequent calls return `''`.\n\nA traits object is stateless, and `generator()` produces a completely new\ngenerator on each call. Generators don't affect each other.\n\nGenerators are [lazy](https://en.wikipedia.org/wiki/Lazy_evaluation) and\nindividual calls are very fast, making foliant suitable for web clients and\nNode.js servers. See [bench/index.bench.js](bench/index.bench.js).\n\n```javascript\nvar traits = new Traits(['goblin', 'smoke'])\nvar gen = traits.generator()\n\nvar words = [], word\nwhile (word = gen()) words.push(word)\n\nconsole.log(words.join(' '))\n\n// oblin smobli smoke goblin gobli moblin mobli\n// this generator is exhausted\n```\n\n## ToDo / WIP\n\n* Port more tests from the Go version, particularly the randomness test.\n* In a large dataset, the last few words returned by a generator are too\n  similar; random distribution needs improvement.\n* Consider restricting repeated triples in `Traits#validComplete()`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitranim%2Ffoliant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmitranim%2Ffoliant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitranim%2Ffoliant/lists"}