ai-nevermore 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,18 +32,24 @@ Commands:
32
32
  nevermore pseudotext [input-file] process the input
33
33
 
34
34
  Options:
35
- --version Show version number [boolean]
36
- -U, --unified-output File to generate html + css into [string]
37
- -C, --css-output File to generate css into [string]
38
- -H, --html-output File to generate html into [string]
39
- -r, --raw-output Do not wrap the ouput [boolean]
40
- -s, --size The size of the font in pixels [number] [default: 12]
41
- -f, --font The font in question (only webfonts are supported)
35
+ --version Show version number [boolean]
36
+ -U, --unified-output File to generate html + css into [string]
37
+ -C, --css-output File to generate css into [string]
38
+ -H, --html-output File to generate html into [string]
39
+ -r, --raw-output Do not wrap the ouput [boolean]
40
+ -m, --render-mode output mode
41
+ [string] [choices: "fixed-mode", "inline-mode"] [default: "inline-mode"]
42
+ -s, --size The size of the font in pixels (required for
43
+ fixed-width) [number] [default: 12]
44
+ -d, --custom-dictionary A json map of replacement words [string]
45
+ -f, --font The font in question (required for fixed-width; only
46
+ webfonts are supported)
42
47
  [string] [choices: "Andale Mono", "Arial", "Avenir", "Avenir Next", "Comic
43
48
  Sans MS", "Courier New", "Georgia", "Helvetica", "Impact", "Inter", "Times New
44
49
  Roman", "Trebuchet MS", "Verdana", "Webdings", "Open Sans", "Tahoma"]
45
50
  [default: "Arial"]
46
- --help Show help [boolean]
51
+ --help Show help [boolean]
52
+
47
53
  ```
48
54
 
49
55
  Roadmap
@@ -53,6 +59,7 @@ Roadmap
53
59
  - [x] stdin, stdout support
54
60
  - [x] custom dictionary
55
61
  - [ ] self randomizing dictionary
62
+ - [ ] add a replacement mode (opposed to a tokenizer based solution)
56
63
 
57
64
  Development
58
65
  -----------
package/bin/nevermore CHANGED
@@ -9,7 +9,7 @@ const { cwd } = process;
9
9
 
10
10
  const formatHTML = (html, css, isRaw=false)=>{
11
11
  if(isRaw) return `${css?`<style>${css}</style>`:''}${html}`;
12
- return `<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >${css?`<style>${css}</style>`:''}</head><body>${html}</body></html>`;
12
+ return `<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >${css.indexOf('\n')===-1?`<link rel="stylesheet" href="${css}">`:`<style>${css}</style>`}</head><body>${html}</body></html>`;
13
13
  };
14
14
 
15
15
  yargs(hideBin(process.argv))
@@ -45,9 +45,13 @@ yargs(hideBin(process.argv))
45
45
  idx = result.toString();
46
46
  }
47
47
  //const { index, root } = await computeIndexKeys(input);
48
- console.log(idx);
49
- process.exit();
50
- const { html, css } = await generateHTMLAndCSS(root, idx);
48
+ const { html, css } = await generateHTMLAndCSS(
49
+ root, idx, {
50
+ mode: argv['render-mode'],
51
+ font: argv['font'],
52
+ size: argv['size']
53
+ }
54
+ );
51
55
  if(argv['unified-output']){
52
56
  const output = formatHTML(html, css, argv['raw-output']);
53
57
  await writeFile(argv['unified-output'], output);
@@ -55,7 +59,11 @@ yargs(hideBin(process.argv))
55
59
  if(argv['css-output'] && argv['html-output']){
56
60
  const cssLocation = join(cwd(), argv['css-output']);
57
61
  const htmlLocation = join(cwd(), argv['html-output']);
58
- const output = formatHTML(html, null, argv['raw-output']);
62
+ const output = formatHTML(
63
+ html,
64
+ `./${argv['css-output']}`,
65
+ argv['raw-output']
66
+ );
59
67
  await writeFile(htmlLocation, output);
60
68
  await writeFile(cssLocation, css);
61
69
 
@@ -80,11 +88,19 @@ yargs(hideBin(process.argv))
80
88
  alias: 'r',
81
89
  type: 'boolean',
82
90
  description: 'Do not wrap the ouput'
91
+ }).option('render-mode', {
92
+ alias: 'm',
93
+ type: 'string',
94
+ description: 'output mode',
95
+ default: 'inline-mode',
96
+ choices: [
97
+ 'fixed-mode', 'inline-mode'
98
+ ],
83
99
  }).option('size', {
84
100
  alias: 's',
85
101
  type: 'number',
86
102
  default: 12,
87
- description: 'The size of the font in pixels'
103
+ description: 'The size of the font in pixels (required for fixed-width)'
88
104
  }).option('custom-dictionary', {
89
105
  alias: 'd',
90
106
  type: 'string',
@@ -99,5 +115,5 @@ yargs(hideBin(process.argv))
99
115
  'Open Sans', 'Tahoma'
100
116
  ],
101
117
  default: 'Arial',
102
- description: 'The font in question (only webfonts are supported)'
118
+ description: 'The font in question (required for fixed-width; only webfonts are supported)'
103
119
  }).help().parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-nevermore",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "keywords": [
5
5
  "adversarial",
6
6
  "content",
@@ -31,7 +31,8 @@
31
31
  "scripts":{
32
32
  "single-file-demo": "./bin/nevermore pseudotext -U output.html nevermore.txt",
33
33
  "pipe-demo": "cat nevermore.txt | ./bin/nevermore pseudotext",
34
- "demo": "./bin/nevermore pseudotext -H out.html -C out.css nevermore.txt"
34
+ "demo": "./bin/nevermore pseudotext -H out.html -C out.css nevermore.txt",
35
+ "help": "./bin/nevermore --help"
35
36
  },
36
37
  "dependencies": {
37
38
  "@environment-safe/file": "^0.4.0",
package/src/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { ParseEnglish } from 'parse-english'
2
2
  import { inspect } from 'unist-util-inspect'
3
3
  import { define } from 'self-dict';
4
+ import pixelWidth from 'string-pixel-width';
4
5
  import { thesaurus } from './thesaurus.mjs';
5
6
  import { hash } from './hash.mjs';
6
- import pixelWidth from 'string-pixel-width';
7
-
7
+ import { modes } from './render-modes.mjs';
8
8
 
9
9
  let wordlist = null;
10
10
 
@@ -24,8 +24,6 @@ const randomWord = async ()=>{
24
24
  while((!word) || word.split(' ').length > 1){
25
25
  word = wordlist[Math.floor(wordlist.length * Math.random())];
26
26
  }
27
- //console.log(word);
28
- //process.exit();
29
27
  return word;
30
28
  }
31
29
 
@@ -40,97 +38,30 @@ const traverse = async (node, handler)=>{
40
38
  }
41
39
  };
42
40
 
43
- const render = async (node, index, fnt, sz)=>{
41
+ const render = async (node, index, modeName, fnt, sz)=>{
42
+ const mode = modes[modeName];
44
43
  let html = '';
45
44
  let css = '';
46
45
  let className = null;
47
46
  let width = null;
48
47
  const font = fnt || 'Arial';
49
48
  const size = sz || 12;
50
- switch(node.type){
51
- case 'RootNode':
52
- css += `span{
53
- font-family: ${font};
54
- font-size: ${size}px;
55
- display:inline-block;
56
- vertical-align: baseline;
57
- }\n`;
58
- break;
59
- case 'ParagraphNode':
60
- html += '<p>';
61
- break;
62
- case 'SentenceNode': break;
63
- case 'WordNode': break;
64
- case 'TextNode':
65
- if(node.replacement){
66
- width = pixelWidth(node.word, {
67
- size: size,
68
- font
69
- });
70
- className = 'R'+hash(node.word);
71
- css += `.${className}{
72
- visibility: hidden;
73
- position: relative;
74
- overflow:none;
75
- vertical-align: text-bottom;
76
- display:inline-block;
77
- font-size: ${size}px;
78
- height: ${size}px;
79
- width: ${width}px;
80
- }
81
- `;
82
- css += `.${className}::after{
83
- visibility: visible;
84
- position: absolute;
85
- vertical-align: text-bottom;
86
- font-family: ${font};
87
- font-size: ${size}px;
88
- display:inline-block;
89
- margin-top: -${Math.round(size/4)}px;
90
- top: 0;
91
- left: 0;
92
- width: ${width}px;
93
- height: ${size}px;
94
- content : '${node.value}'
95
- }
96
- `;
97
- html += `<span class="guarded ${
98
- className
99
- } ">${node.replacement}</span>`;
100
- }else{
101
- //console.log(node); process.exit();
102
- html += `<span>${node.value}</span>`;
103
- }
104
- break;
105
- case 'WhiteSpaceNode':
106
- break;
107
- case 'PunctuationNode':
108
- break;
109
- default: {console.log(node); process.exit()}
49
+ if(mode[node.type] && mode[node.type].pre){
50
+ html += mode[node.type].pre({font, size, node});
51
+ }
52
+ if(mode[node.type] && mode[node.type].style){
53
+ css += mode[node.type].style({font, size, node});
110
54
  }
111
55
  if(node.children){
112
56
  let vals = null;
113
57
  for(let lcv=0; lcv< node.children.length; lcv++){
114
- vals = await render(node.children[lcv]);
58
+ vals = await render(node.children[lcv], index, modeName, fnt, sz);
115
59
  html += vals.html;
116
60
  css += vals.css;
117
61
  }
118
62
  }
119
- switch(node.type){
120
- case 'RootNode': break;
121
- case 'ParagraphNode':
122
- html += '</p>';
123
- break;
124
- case 'SentenceNode':
125
- break;
126
- case 'WordNode': break;
127
- case 'TextNode': break;
128
- case 'WhiteSpaceNode':
129
- html += `${node.value}`;
130
- break;
131
- case 'PunctuationNode':
132
- html += `<span>${node.value}</span>`;
133
- break;
63
+ if(mode[node.type] && mode[node.type].post){
64
+ html += mode[node.type].post({font, size, node});
134
65
  }
135
66
  return {html, css};
136
67
  };
@@ -166,8 +97,10 @@ export const computeIndexKeys = async (textBody)=>{
166
97
  return { index, root: node };
167
98
  };
168
99
 
169
- export const generateHTMLAndCSS = async (node, index, fnt, sz)=>{
100
+ export const generateHTMLAndCSS = async (node, index, options)=>{
170
101
  await checkThesaurusInit();
171
- const { html, css } = await render(node, index, fnt, sz);
102
+ const { html, css } = await render(
103
+ node, index, options.mode, options.font, options.size
104
+ );
172
105
  return { html, css };
173
106
  };
@@ -0,0 +1,120 @@
1
+ import pixelWidth from 'string-pixel-width';
2
+ import { thesaurus } from './thesaurus.mjs';
3
+ import { hash } from './hash.mjs';
4
+
5
+ export const fixedMode = {
6
+ RootNode : {
7
+ style : ({font, size, node})=>{
8
+ return `span{
9
+ font-family: ${font};
10
+ font-size: ${size}px;
11
+ display:inline-block;
12
+ vertical-align: baseline;
13
+ }\n`;
14
+ }
15
+ },
16
+ ParagraphNode : {
17
+ pre : ({font, size, node})=>{
18
+ return `<p>`;
19
+ },
20
+ post : ({font, size, node})=>{
21
+ return `</p>`;
22
+ }
23
+ },
24
+ TextNode: {
25
+ style : ({font, size, node})=>{
26
+ if(node.replacement){
27
+ const width = pixelWidth(node.word, {
28
+ size: size,
29
+ font
30
+ });
31
+ const className = 'R'+hash(node.word);
32
+ return `.${className}{
33
+ visibility: hidden;
34
+ position: relative;
35
+ overflow:none;
36
+ vertical-align: text-bottom;
37
+ display:inline-block;
38
+ font-size: ${size}px;
39
+ height: ${size}px;
40
+ width: ${width}px;
41
+ }
42
+ .${className}::after{
43
+ content : '${node.value}'
44
+ }
45
+ `;
46
+ }else{
47
+ return '';
48
+ }
49
+ },
50
+ pre : ({font, size, node})=>{
51
+ if(node.replacement){
52
+ const className = 'R'+hash(node.word);
53
+ return `<span class="guarded ${
54
+ className
55
+ } ">${node.replacement}</span>`;
56
+ }else{
57
+ return `<span>${node.value}</span>`;
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ export const inlineMode = {
64
+ RootNode : {
65
+ style : ({font, size, node})=>{
66
+ return `.guarded{
67
+ visibility: hidden;
68
+ font-size: 0;
69
+ }
70
+ .guarded::after{
71
+ visibility: visible;
72
+ display: inline-block;
73
+ font-size: 1.0rem;
74
+ }
75
+ \n`;
76
+ }
77
+ },
78
+ ParagraphNode : {
79
+ pre : ({font, size, node})=>{
80
+ return `<p>`;
81
+ },
82
+ post : ({font, size, node})=>{
83
+ return `</p>`;
84
+ }
85
+ },
86
+ WhiteSpaceNode :{
87
+ post : ({font, size, node})=>{
88
+ return `${node.value}`;
89
+ }
90
+ },
91
+ TextNode: {
92
+ style : ({font, size, node})=>{
93
+ if(node.replacement){
94
+ const width = pixelWidth(node.word, {
95
+ size: size,
96
+ font
97
+ });
98
+ const className = 'R'+hash(node.word);
99
+ return `.${className}::after{ content : '${node.value}'; }`;
100
+ }else{
101
+ return '';
102
+ }
103
+ },
104
+ pre : ({font, size, node})=>{
105
+ if(node.replacement){
106
+ const className = 'R'+hash(node.word);
107
+ return `<span class="guarded ${
108
+ className
109
+ } ">${node.replacement}</span>`;
110
+ }else{
111
+ return `<span>${node.value}</span>`;
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ export const modes = {
118
+ 'fixed-mode' : fixedMode,
119
+ 'inline-mode' : inlineMode
120
+ }