Skip to content

Commit

Permalink
Outline analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Jul 4, 2015
1 parent a3256ff commit 74a781a
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/smm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import './smm/metadata';
import './smm/scoper';
import './smm/numberer';
import './smm/parser';
import './smm/outline';
import './smm/verifier-standard';
54 changes: 54 additions & 0 deletions lib/smm/outline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { MMOMDatabase, MMOMStatement } from './mmom';
const { COMMENT } = MMOMStatement;

const LEADS = new Map().set('####',1).set('#*#*',2).set('=-=-',3).set('....',4);

class MMOMOutline {
constructor(db) {
this._db = db;
this._dirty = true;
this._outline = [];
this._db._observer.push(this);
}

notifyChanged(rec) {
this._dirty = true;
}

_update() {
if (this._dirty) this._scan();
return this;
}

_scan() {
this._dirty = false;
this._outline.length = 0;

for (let i = 0; i < this._db.statements.length; i++) {
let stmt = this._db.statements[i];
if (stmt.type !== COMMENT) continue;
let text = stmt.commentText;
if (text.length < 5) continue;
if (text.charCodeAt(0) >= 32) continue;
text = text.replace(/\r\n?/g, '\n');
let level = LEADS.get(text.slice(1,5));
if (level === undefined) continue;

// 2nd line is title, 3rd line is ignored (if present), remainder is prologue
// format is not precisely specced anywhere :(

let lines = text.split('\n');
let title = (lines[2] || '').trim();
if (!title) continue;
lines.splice(0,4);
let prologue = lines.join('').trim();
this._outline.push({ statement: stmt, level: level, title: title, prologue: prologue });
}
}
}

Object.defineProperty(MMOMDatabase.prototype, 'outlineEntries', { get: function () {
return this.outline._update()._outline;
}});

MMOMDatabase.registerAnalyzer('outline', MMOMOutline);
47 changes: 47 additions & 0 deletions test/outline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describeDB } from './lib/util';
import { expect } from 'chai';
import '../lib/smm/outline';

describeDB('Outline extraction', `
$(
#####
A part
$)
$( Not outliney $)
$(
#####
Not outliney
$)
$(
#*#*
A chapter
#*#*
$)
$(
=-=-=-=-=-=-
A section, with prose
=-=-=-=-=-
This is commentary
$)
`, dbt => {
it('finds the outlines and only the outlines', () => expect(dbt().outlineEntries.length).to.equal(3));
describe('first outline comment', () => {
it('statement #', () => expect(dbt().outlineEntries[0].statement.index).to.equal(0));
it('title', () => expect(dbt().outlineEntries[0].title).to.equal('A part'));
it('no prologue', () => expect(dbt().outlineEntries[0].prologue).to.equal(''));
})
describe('second outline comment', () => {
it('statement #', () => expect(dbt().outlineEntries[1].statement.index).to.equal(3));
it('title', () => expect(dbt().outlineEntries[1].title).to.equal('A chapter'));
it('no prologue', () => expect(dbt().outlineEntries[1].prologue).to.equal(''));
});;
describe('third outline comment', () => {
it('statement #', () => expect(dbt().outlineEntries[2].statement.index).to.equal(4));
it('title', () => expect(dbt().outlineEntries[2].title).to.equal('A section, with prose'));
it('prologue', () => expect(dbt().outlineEntries[2].prologue).to.equal('This is commentary'));
});
});

0 comments on commit 74a781a

Please sign in to comment.