Lookup and verify toc links

This commit is contained in:
Johannes Zillmann 2021-04-25 14:41:50 +02:00
parent 25f23ee0e4
commit 94a7405671
114 changed files with 3639 additions and 11 deletions

View File

@ -9,6 +9,8 @@ The interesting thing is that rendering with pdfjs (online) looks good. So maybe
- out of order items [Safe-Communication](examples/Safe-Communication.pdf)
- items in wrong lines + numbers are not numbers [Life-Of-God-In-Soul-Of-Man](examples/Life-Of-God-In-Soul-Of-Man.pdf)
- CC-NC_Leitfaden.pdf: un-verified toc entries (and/und/&... etc...)
- Closed-Syllables.pdf: unverified toc entries
## Not yet reviewed test PDFS

View File

@ -1,7 +1,24 @@
enum FontType {
BOLD = 'BOLD',
OBLIQUE = 'OBLIQUE',
//TODO remove bold/oblique
BOLD_OBLIQUE = 'BOLD_OBLIQUE',
}
export default FontType;
namespace FontType {
export function declaredFontTypes(fontName: string): FontType[] {
const fontNameLowerCase = fontName.toLowerCase();
const bold = fontNameLowerCase.includes('bold') || fontNameLowerCase.includes('heavy');
const italic = fontNameLowerCase.includes('oblique') || fontNameLowerCase.includes('italic');
const fontTypes: FontType[] = [];
if (bold) {
fontTypes.push(FontType.BOLD);
}
if (italic) {
fontTypes.push(FontType.OBLIQUE);
}
return fontTypes;
}
}

View File

@ -19,6 +19,7 @@ export default class TOC {
export interface TocEntry {
level: number;
text: string;
verified: boolean;
linkedPage: number;
items: Item[];
}

View File

@ -1,6 +1,30 @@
import { FontType } from 'pdfjs-dist/types/shared/util';
import { assertDefined } from '../assert';
import Item from '../Item';
import ItemType from '../ItemType';
function get(item: Item, name: string): any {
const value = item.data[name];
assertDefined(value, `No '${name}' defined in ${JSON.stringify(item)}`);
return value;
}
export function getHeight(item: Item): number {
return get(item, 'height');
}
export function getText(item: Item): string {
return get(item, 'str');
}
export function getFontName(fontMap: Map<string, object>, item: Item): string {
const fontId = item.data['fontName'];
const fontObject = fontMap.get(fontId);
if (!fontObject) {
return fontId;
}
return assertDefined(fontObject['name'], `No 'name' found in ${JSON.stringify(fontObject)}`);
}
export function itemWithType(item: Item, type: ItemType): Item {
const existingTypes = item.data['types'] || [];
return item.withDataAddition({ types: [...existingTypes, type] });

View File

@ -1,5 +1,7 @@
import { assert } from '../assert';
const TAB_CHAR_CODE = 9;
const WHITESPACE_CHAR_CODE = 32;
const MIN_DIGIT_CHAR_CODE = 48;
const MAX_DIGIT_CHAR_CODE = 57;
@ -19,6 +21,12 @@ export function filterOutDigits(text: string): string {
return String.fromCharCode(...toCharcodes(text).filter((code) => !isDigit(code)));
}
export function filterOutWhitespaces(text: string): string {
return String.fromCharCode(
...toCharcodes(text).filter((code) => code != TAB_CHAR_CODE && code != WHITESPACE_CHAR_CODE),
);
}
export function extractNumbers(text: string): number[] {
return (text.match(/\d+/g) || []).map(Number);
}

View File

@ -15,6 +15,7 @@ export const MAX_X = new GlobalDefinition<number>('maxX');
export const MIN_Y = new GlobalDefinition<number>('minY');
export const MAX_Y = new GlobalDefinition<number>('maxY');
export const MAX_HEIGHT = new GlobalDefinition<number>('maxHeight');
export const MOST_USED_HEIGHT = new GlobalDefinition<number>('mostUsedHeight');
export const PAGE_MAPPING = new GlobalDefinition<PageMapping>('pageMapping');
const config = {
@ -115,6 +116,7 @@ export default class CalculateStatistics extends ItemTransformer {
items: items,
globals: [
MAX_HEIGHT.value(maxHeight),
MOST_USED_HEIGHT.value(mostUsedHeight),
MIN_X.value(minX),
MAX_X.value(maxX),
MIN_Y.value(minY),

View File

@ -5,13 +5,14 @@ import ItemResult from '../ItemResult';
import TransformContext from './TransformContext';
import LineItemMerger from '../debug/LineItemMerger';
import { groupByLine, groupByPage, onlyUniques, transformGroupedByPage } from '../support/groupingUtils';
import { PAGE_MAPPING } from './CacluclateStatistics';
import { extractEndingNumber } from '../support/stringFunctions';
import { MOST_USED_HEIGHT, PAGE_MAPPING } from './CacluclateStatistics';
import { extractEndingNumber, filterOutWhitespaces } from '../support/stringFunctions';
import ItemType from '../ItemType';
import { numbersAreConsecutive } from '../support/numberFunctions';
import TOC, { TocEntry } from '../TOC';
import FontType from '../FontType';
import { flatten, groupBy } from '../support/functional';
import { itemWithType } from '../support/items';
import { getHeight, getText, getFontName, itemWithType } from '../support/items';
const config = {
// How many characters a line with a ending number needs to have minimally to be a valid link
@ -45,6 +46,7 @@ export default class DetectToc extends ItemTransformer {
transform(context: TransformContext, inputItems: Item[]): ItemResult {
const pageMapping = context.getGlobal(PAGE_MAPPING);
const mostUsedHeight = context.getGlobal(MOST_USED_HEIGHT);
const maxPageToEvaluate = Math.min(context.pageCount / 2, 5 + Math.abs(pageMapping.pageFactor));
const pagesToEvaluate = groupByPage(inputItems.filter((item) => item.page <= maxPageToEvaluate));
const maxPageToBeLinkedTo = context.pageCount + pageMapping.pageFactor - 1;
@ -59,12 +61,27 @@ export default class DetectToc extends ItemTransformer {
const tocItemUuids: Set<string> = new Set(
flatten(flatten(rawTocEntries.map((e) => e.entryLines))).map((item) => item.uuid),
);
const tocEntries: TocEntry[] = rawTocEntries.map((rawEntry) => ({
level: 0,
text: 'string',
linkedPage: rawEntry.linkedPage,
items: flatten(rawEntry.entryLines),
}));
const tocEntries: TocEntry[] = rawTocEntries.map((rawEntry) => {
const headline = findHeadline(
context.fontMap,
inputItems,
mostUsedHeight,
rawEntry.linkedPage - pageMapping.pageFactor,
rawEntry.entryLines,
);
return {
level: 0,
text:
headline ||
flatten(rawEntry.entryLines)
.map((item) => getText(item))
.join('')
.replace(/[\s.]+\w+$/, ''),
verified: !!headline,
linkedPage: rawEntry.linkedPage,
items: flatten(rawEntry.entryLines),
};
});
return {
items: inputItems.map((item) => {
@ -228,6 +245,40 @@ function selectRawTocEntries(tocArea: TocArea, inputItems: Item[]): RawTocEntry[
return rawTocEntries;
}
function findHeadline(
fontMap: Map<string, object>,
items: Item[],
mostUsedHeight: number,
targetPage: number,
entryLines: Item[][],
): string | undefined {
const tocEntryText = normalizeHeadlineChars(
entryLines.map((lineItems) => lineItems.map((item) => getText(item)).join('')).join(''),
);
const pageItems = items.filter((item) => item.page == targetPage);
const possibleHeadlines = pageItems.filter(
(item) =>
getHeight(item) > mostUsedHeight + config.minHeadlineDistance ||
FontType.declaredFontTypes(getFontName(fontMap, item)).includes(FontType.BOLD),
);
let hits = possibleHeadlines.filter((item) => {
return tocEntryText.includes(normalizeHeadlineChars(getText(item)));
});
if (hits.length > 0) {
return hits
.map((hit) => getText(hit))
.join('')
.trim();
}
return undefined;
}
function normalizeHeadlineChars(text: string) {
return filterOutWhitespaces(text).toLowerCase();
}
/**
* Pointer to pages/items which classified as TOC.
*/

View File

@ -27,4 +27,8 @@ export default class TransformContext {
getGlobal<T>(definition: GlobalDefinition<T>): T {
return this.globals.get(definition);
}
getGlobalOptionally<T>(definition: GlobalDefinition<T>): T | undefined {
return this.globals.getOptional(definition);
}
}

View File

@ -139,8 +139,12 @@ function globalsToString(globals: Globals): object {
if (key === TOC_GLOBAL.key) {
value = {
...value,
entries: value.entries.map((entry: TocEntry) => {
const filteredEntry = { ...entry } as any;
delete filteredEntry.items;
return filteredEntry;
}),
};
delete value.entries;
}
obj[key] = value;
return obj;

View File

@ -1,4 +1,9 @@
import { filterOutDigits, extractNumbers, extractEndingNumber } from 'src/support/stringFunctions';
import {
filterOutDigits,
filterOutWhitespaces,
extractNumbers,
extractEndingNumber,
} from 'src/support/stringFunctions';
test('filterOutDigits', async () => {
expect(filterOutDigits('')).toEqual('');
@ -6,6 +11,12 @@ test('filterOutDigits', async () => {
expect(filterOutDigits('a1b 2c 3')).toEqual('ab c ');
});
test('filterOutWhitespaces', async () => {
expect(filterOutWhitespaces('')).toEqual('');
expect(filterOutWhitespaces('a b c')).toEqual('abc');
expect(filterOutWhitespaces('ab c ')).toEqual('abc');
});
test('extractNumbers', async () => {
expect(extractNumbers('')).toEqual([]);
expect(extractNumbers('a b c')).toEqual([]);

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 66,
"mostUsedHeight": 8,
"minX": 41.38153078000005,
"maxX": 400.56930541,
"minY": 36.71720123,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 66,
"mostUsedHeight": 8,
"minX": 41.38153078000005,
"maxX": 400.56930541,
"minY": 36.71720123,

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 66,
"mostUsedHeight": 8,
"minX": 41.38153078000005,
"maxX": 400.56930541,
"minY": 36.71720123,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 66,
"mostUsedHeight": 8,
"minX": 41.38153078000005,
"maxX": 400.56930541,
"minY": 36.71720123,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 59.7758,
"mostUsedHeight": 10,
"minX": 117.8279999999999,
"maxX": 471.0319307,
"minY": 95.28300000000016,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 59.7758,
"mostUsedHeight": 10,
"minX": 117.8279999999999,
"maxX": 471.0319307,
"minY": 95.28300000000016,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 59.7758,
"mostUsedHeight": 10,
"minX": 117.8279999999999,
"maxX": 471.0319307,
"minY": 95.28300000000016,
@ -46,6 +47,80 @@
"toc": {
"pages": [
3
],
"entries": [
{
"level": 0,
"text": "A Scandal In BohemiaI",
"verified": true,
"linkedPage": 3
},
{
"level": 0,
"text": "The Red-Headed League",
"verified": true,
"linkedPage": 21
},
{
"level": 0,
"text": "A Case Of Identity",
"verified": true,
"linkedPage": 38
},
{
"level": 0,
"text": "The Boscombe Valley Mystery",
"verified": true,
"linkedPage": 51
},
{
"level": 0,
"text": "The Five Orange Pips",
"verified": true,
"linkedPage": 69
},
{
"level": 0,
"text": "The Man With The Twisted LipI",
"verified": true,
"linkedPage": 83
},
{
"level": 0,
"text": "The Adventure Of The BlueCarbuncle",
"verified": true,
"linkedPage": 100
},
{
"level": 0,
"text": "The Adventure Of The SpeckledBandO",
"verified": true,
"linkedPage": 115
},
{
"level": 0,
"text": "The Adventure Of TheEngineers ThumbO",
"verified": true,
"linkedPage": 133
},
{
"level": 0,
"text": "The Adventure Of The NobleBachelorT",
"verified": true,
"linkedPage": 148
},
{
"level": 0,
"text": "The Adventure Of The BerylCoronetH",
"verified": true,
"linkedPage": 164
},
{
"level": 0,
"text": "The Adventure Of The CopperBeechesT",
"verified": true,
"linkedPage": 182
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 59.7758,
"mostUsedHeight": 10,
"minX": 117.8279999999999,
"maxX": 471.0319307,
"minY": 95.28300000000016,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 59.7758,
"mostUsedHeight": 10,
"minX": 117.8279999999999,
"maxX": 471.0319307,
"minY": 95.28300000000016,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 24.787,
"mostUsedHeight": 11,
"minX": 102.88399999999984,
"maxX": 488.43800000000005,
"minY": 95.545,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 24.787,
"mostUsedHeight": 11,
"minX": 102.88399999999984,
"maxX": 488.43800000000005,
"minY": 95.545,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 24.787,
"mostUsedHeight": 11,
"minX": 102.88399999999984,
"maxX": 488.43800000000005,
"minY": 95.545,
@ -46,6 +47,86 @@
"toc": {
"pages": [
1
],
"entries": [
{
"level": 0,
"text": "Poem",
"verified": true,
"linkedPage": 3
},
{
"level": 0,
"text": "Down the Rabbit-Hole",
"verified": true,
"linkedPage": 4
},
{
"level": 0,
"text": "The Pool of Tears",
"verified": true,
"linkedPage": 9
},
{
"level": 0,
"text": "A Caucus-Race and a Long Tale",
"verified": true,
"linkedPage": 14
},
{
"level": 0,
"text": "The Rabbit Sends in a Little Bill",
"verified": true,
"linkedPage": 19
},
{
"level": 0,
"text": "Advice from a Caterpillar",
"verified": true,
"linkedPage": 25
},
{
"level": 0,
"text": "Pig and Pepper",
"verified": true,
"linkedPage": 32
},
{
"level": 0,
"text": "A Mad Tea-Party",
"verified": true,
"linkedPage": 39
},
{
"level": 0,
"text": "The Queens Croquet-Ground",
"verified": true,
"linkedPage": 46
},
{
"level": 0,
"text": "The Mock Turtles Story",
"verified": true,
"linkedPage": 53
},
{
"level": 0,
"text": "The Lobster Quadrille",
"verified": true,
"linkedPage": 59
},
{
"level": 0,
"text": "Who Stole the Tarts?",
"verified": true,
"linkedPage": 65
},
{
"level": 0,
"text": "Alices Evidence",
"verified": true,
"linkedPage": 70
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 24.787,
"mostUsedHeight": 11,
"minX": 102.88399999999984,
"maxX": 488.43800000000005,
"minY": 95.545,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 24.787,
"mostUsedHeight": 11,
"minX": 102.88399999999984,
"maxX": 488.43800000000005,
"minY": 95.545,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 9,
"minX": 34.01229999999998,
"maxX": 380.3863,
"minY": 26.9291,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 9,
"minX": 34.01229999999998,
"maxX": 380.3863,
"minY": 26.9291,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 9,
"minX": 34.01229999999998,
"maxX": 380.3863,
"minY": 26.9291,
@ -46,6 +47,152 @@
"toc": {
"pages": [
3
],
"entries": [
{
"level": 0,
"text": "vorWort",
"verified": true,
"linkedPage": 3
},
{
"level": 0,
"text": "einFührung",
"verified": true,
"linkedPage": 5
},
{
"level": 0,
"text": "1Was versteht man unter Open COntent?",
"verified": true,
"linkedPage": 6
},
{
"level": 0,
"text": "2Warum Werden Inhalte unter eIneCC-lIzenz gestellt?",
"verified": true,
"linkedPage": 8
},
{
"level": 0,
"text": "3sChIedlIChe CC-lIzenzen?",
"verified": true,
"linkedPage": 9
},
{
"level": 0,
"text": "4WIe WIrkt sICh das nC-mOdul darauf aus, WIe Inhalte verbreItet Werden?",
"verified": true,
"linkedPage": 10
},
{
"level": 0,
"text": "5Was Ist kOmmerzIell?",
"verified": true,
"linkedPage": 11
},
{
"level": 0,
"text": "6kann eIne CC-lIzenz mIt nC-mOdul verhIndern, dass meIne Inhalte durCh reChtsradIkale Oder andere extremIsten genutzt Werden?",
"verified": true,
"linkedPage": 12
},
{
"level": 0,
"text": "7ICh WIll, dass meIn Inhalt unter eIner CC-lIzenz freIzugänglICh bleIbt. Ist das lIChkeIt, eIner aneIgnung merzIelle unternehmen vOrzubeugen?",
"verified": true,
"linkedPage": 13
},
{
"level": 0,
"text": "8kann eIn CC-nC lIzenzIerter gestellt Werden?",
"verified": true,
"linkedPage": 14
},
{
"level": 0,
"text": "9kann man eInen nC-lIzenzIerten Inhalt kung gesOndert für WIkI pedIa freIgeben?",
"verified": true,
"linkedPage": 15
},
{
"level": 0,
"text": "10verhIndert das nC-mOdul, dass Inhalte kOmmerzIell genutzt Werden?",
"verified": true,
"linkedPage": 15
},
{
"level": 0,
"text": "11bIn ICh bereIt, gegen eIne ner Inhalte vOrzugehen?",
"verified": true,
"linkedPage": 16
},
{
"level": 0,
"text": "12können nC-lIzenzIerteInhalte In zeItungenabgedruCkt Werden?",
"verified": true,
"linkedPage": 16
},
{
"level": 0,
"text": "13Inhalte In allen sChulen, sItäten genutzt Werden?",
"verified": true,
"linkedPage": 17
},
{
"level": 0,
"text": "14WIe Ist es zu beWerten, te zunäChst In der sChule verWendet, dann aber auCh nutzt Werden sOllen?",
"verified": true,
"linkedPage": 17
},
{
"level": 0,
"text": "15WIe WIrkt sICh nC auf mashups aus?",
"verified": true,
"linkedPage": 18
},
{
"level": 0,
"text": "16darf ICh als gema-mItglIed ter eIne CC-lIzenz mIt nC-mOdul stellen?",
"verified": true,
"linkedPage": 19
},
{
"level": 0,
"text": "17kann eIne kOmmerzIelle nutzung durCh drItte dem urheber nutzen?",
"verified": true,
"linkedPage": 20
},
{
"level": 0,
"text": "18darf eIn nutzer vOn CC-lIzenzIerten Inhalten den eIndruCk erWeCken, der urheber Würde dIe lICh unterstützen?",
"verified": true,
"linkedPage": 20
},
{
"level": 0,
"text": "19kann das nC-mOdul beI CC-lIzenzen sInnvOll seIn?",
"verified": true,
"linkedPage": 21
},
{
"level": 0,
"text": "20unter WelCher CC-lIzenz stehen WIkIpedIa-Inhalte?",
"verified": true,
"linkedPage": 21
},
{
"level": 0,
"text": "Literatur und Links zur Vertiefung",
"verified": false,
"linkedPage": 22
},
{
"level": 0,
"text": "impressum",
"verified": true,
"linkedPage": 23
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 9,
"minX": 34.01229999999998,
"maxX": 380.3863,
"minY": 26.9291,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 9,
"minX": 34.01229999999998,
"maxX": 380.3863,
"minY": 26.9291,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 16.02,
"mostUsedHeight": 13,
"minX": 25.86,
"maxX": 535.44,
"minY": 38.1,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 16.02,
"mostUsedHeight": 13,
"minX": 25.86,
"maxX": 535.44,
"minY": 38.1,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 16.02,
"mostUsedHeight": 13,
"minX": 25.86,
"maxX": 535.44,
"minY": 38.1,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 16.02,
"mostUsedHeight": 13,
"minX": 25.86,
"maxX": 535.44,
"minY": 38.1,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 16.02,
"mostUsedHeight": 13,
"minX": 25.86,
"maxX": 535.44,
"minY": 38.1,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 18,
"mostUsedHeight": 11,
"minX": 72.024,
"maxX": 534.58,
"minY": 63.144,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 18,
"mostUsedHeight": 11,
"minX": 72.024,
"maxX": 534.58,
"minY": 63.144,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 18,
"mostUsedHeight": 11,
"minX": 72.024,
"maxX": 534.58,
"minY": 63.144,
@ -46,6 +47,44 @@
"toc": {
"pages": [
1
],
"entries": [
{
"level": 0,
"text": "“short a”",
"verified": false,
"linkedPage": 3
},
{
"level": 0,
"text": "“short I”",
"verified": false,
"linkedPage": 8
},
{
"level": 0,
"text": "“short o”",
"verified": false,
"linkedPage": 10
},
{
"level": 0,
"text": "“short u”",
"verified": false,
"linkedPage": 12
},
{
"level": 0,
"text": "E",
"verified": false,
"linkedPage": 14
},
{
"level": 0,
"text": "Y",
"verified": false,
"linkedPage": 16
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 18,
"mostUsedHeight": 11,
"minX": 72.024,
"maxX": 534.58,
"minY": 63.144,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 18,
"mostUsedHeight": 11,
"minX": 72.024,
"maxX": 534.58,
"minY": 63.144,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 30,
"mostUsedHeight": 11,
"minX": 56.69069,
"maxX": 507.3787,
"minY": 45,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 30,
"mostUsedHeight": 11,
"minX": 56.69069,
"maxX": 507.3787,
"minY": 45,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 30,
"mostUsedHeight": 11,
"minX": 56.69069,
"maxX": 507.3787,
"minY": 45,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 30,
"mostUsedHeight": 11,
"minX": 56.69069,
"maxX": 507.3787,
"minY": 45,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 30,
"mostUsedHeight": 11,
"minX": 56.69069,
"maxX": 507.3787,
"minY": 45,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 29,
"mostUsedHeight": 11,
"minX": 37.1206,
"maxX": 542.2816,
"minY": 36.1763,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 29,
"mostUsedHeight": 11,
"minX": 37.1206,
"maxX": 542.2816,
"minY": 36.1763,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 29,
"mostUsedHeight": 11,
"minX": 37.1206,
"maxX": 542.2816,
"minY": 36.1763,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 29,
"mostUsedHeight": 11,
"minX": 37.1206,
"maxX": 542.2816,
"minY": 36.1763,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 29,
"mostUsedHeight": 11,
"minX": 37.1206,
"maxX": 542.2816,
"minY": 36.1763,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 48,
"mostUsedHeight": 12,
"minX": 62.03970999999996,
"maxX": 536.37986,
"minY": 22.6801,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 48,
"mostUsedHeight": 12,
"minX": 62.03970999999996,
"maxX": 536.37986,
"minY": 22.6801,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 48,
"mostUsedHeight": 12,
"minX": 62.03970999999996,
"maxX": 536.37986,
"minY": 22.6801,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 48,
"mostUsedHeight": 12,
"minX": 62.03970999999996,
"maxX": 536.37986,
"minY": 22.6801,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 48,
"mostUsedHeight": 12,
"minX": 62.03970999999996,
"maxX": 536.37986,
"minY": 22.6801,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 45.974399999999996,
"mostUsedHeight": 7,
"minX": 26.29161,
"maxX": 273.69135,
"minY": 15.08535,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 45.974399999999996,
"mostUsedHeight": 7,
"minX": 26.29161,
"maxX": 273.69135,
"minY": 15.08535,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 45.974399999999996,
"mostUsedHeight": 7,
"minX": 26.29161,
"maxX": 273.69135,
"minY": 15.08535,
@ -48,6 +49,302 @@
14,
15,
16
],
"entries": [
{
"level": 0,
"text": "THEOFOF",
"verified": true,
"linkedPage": 3
},
{
"level": 0,
"text": "MISTAKESABOUTT",
"verified": true,
"linkedPage": 4
},
{
"level": 0,
"text": "WHATRELIGION",
"verified": true,
"linkedPage": 6
},
{
"level": 0,
"text": "AndTHEPERMANENCYANDOFTpermanencyandmanand",
"verified": true,
"linkedPage": 7
},
{
"level": 0,
"text": "RELIGIONAandandAndandmanand",
"verified": true,
"linkedPage": 13
},
{
"level": 0,
"text": "WHATTHENATURALThe",
"verified": true,
"linkedPage": 14
},
{
"level": 0,
"text": "ofTHEDIFFERENTOFTHERAL",
"verified": true,
"linkedPage": 15
},
{
"level": 0,
"text": "THEDOTH",
"verified": true,
"linkedPage": 20
},
{
"level": 0,
"text": "RELIGIONBETTERUNDERSTOODBYACTIONSTHANBYby",
"verified": true,
"linkedPage": 24
},
{
"level": 0,
"text": "LOVEEXEMPLIFIEDOUR",
"verified": true,
"linkedPage": 26
},
{
"level": 0,
"text": "IOURCONSTANTA",
"verified": true,
"linkedPage": 28
},
{
"level": 0,
"text": "OURCHARITYTO",
"verified": true,
"linkedPage": 29
},
{
"level": 0,
"text": "TOUR",
"verified": true,
"linkedPage": 31
},
{
"level": 0,
"text": "andandTHEANDADVANTAGEOFAND",
"verified": true,
"linkedPage": 38
},
{
"level": 0,
"text": "TheLTHEEXCELLENCYOF",
"verified": true,
"linkedPage": 39
},
{
"level": 0,
"text": "THEADVANTAGESOFThe",
"verified": true,
"linkedPage": 44
},
{
"level": 0,
"text": "THEWORTHOFTHE",
"verified": true,
"linkedPage": 45
},
{
"level": 0,
"text": "THECERTAINTYTOBELOVEDA",
"verified": true,
"linkedPage": 46
},
{
"level": 0,
"text": "HeLoveTHEOFTHEBELOVED",
"verified": true,
"linkedPage": 48
},
{
"level": 0,
"text": "makesTHELOVEMAKESUSPARTAKEOFANmakes",
"verified": true,
"linkedPage": 49
},
{
"level": 0,
"text": "HETHATLOVETHGODSWEETNESSEVERYNeverI",
"verified": true,
"linkedPage": 51
},
{
"level": 0,
"text": "himTHEDUTIESOFRELIGIONAREDELIGHTFULTOof",
"verified": true,
"linkedPage": 52
},
{
"level": 0,
"text": "THEOFThe",
"verified": true,
"linkedPage": 54
},
{
"level": 0,
"text": "THEPLEASURETHATATTENDSA",
"verified": true,
"linkedPage": 56
},
{
"level": 0,
"text": "THEEXCELLENCYOF",
"verified": true,
"linkedPage": 58
},
{
"level": 0,
"text": "THEDELIGHTAFFORDEDBYA",
"verified": true,
"linkedPage": 59
},
{
"level": 0,
"text": "THEEXCELLENCYOF",
"verified": true,
"linkedPage": 60
},
{
"level": 0,
"text": "THEPLEASUREANDSWEETNESSOFANHUMBLETEMPER.AandandandHeTheandandhumbleAnd",
"verified": true,
"linkedPage": 62
},
{
"level": 0,
"text": "A",
"verified": true,
"linkedPage": 65
},
{
"level": 0,
"text": "mememememeOOTHEDESPONDENTTHOUGHTSOFSOMELYAWAKENEDTOARIGHTSENSEOFT",
"verified": true,
"linkedPage": 66
},
{
"level": 0,
"text": "THEUNREASONABLENESSOFTHESE",
"verified": true,
"linkedPage": 69
},
{
"level": 0,
"text": "weandTheAndandandAndweandMUSTDOWHATWEANDDEPENDONTHEASSISTANCEandand",
"verified": true,
"linkedPage": 74
},
{
"level": 0,
"text": "weWEMUSTSHUNALLMANNEROFwewewewewewe",
"verified": true,
"linkedPage": 78
},
{
"level": 0,
"text": "weweweWEMUSTTHETEMPTATIONSOFBYTHETHEYWILLDRAWONweweweWewe",
"verified": true,
"linkedPage": 82
},
{
"level": 0,
"text": "weweTORESTRAINOURSELVESMANYLAWFULweweweweWemany",
"verified": true,
"linkedPage": 91
},
{
"level": 0,
"text": "MUSTTOPUTOURSELVESOUTOFLOVEWITHTHE",
"verified": true,
"linkedPage": 93
},
{
"level": 0,
"text": "WEMUSTDOTHOSEOUTWARDACTIONSTHATAREweweweweandwewe",
"verified": true,
"linkedPage": 98
},
{
"level": 0,
"text": "tion,Charity,&c",
"verified": false,
"linkedPage": 100
},
{
"level": 0,
"text": "TOBEGETWEMUSTCONSIDERTHEOFTHE",
"verified": true,
"linkedPage": 104
},
{
"level": 0,
"text": "GodweweandandweWESHOULDMEDITATEONGOODNESSANDwewe",
"verified": true,
"linkedPage": 108
},
{
"level": 0,
"text": "TOBEGETCHARITYWEMUSTREMEMBERTHATALLMENARENEARLYRELATEDUNTOweGod",
"verified": true,
"linkedPage": 113
},
{
"level": 0,
"text": "GodTHATTHEYCARRYIMAGEUPONAimageuponthemimage",
"verified": true,
"linkedPage": 114
},
{
"level": 0,
"text": "TOBEGETWESHOULDCONSIDERTHEDIGNITYOFOURwewewe",
"verified": true,
"linkedPage": 116
},
{
"level": 0,
"text": "WESHOULDMEDITATEOFTENONTHEJOYSOFHEAVEN.wewewewewe",
"verified": true,
"linkedPage": 117
},
{
"level": 0,
"text": "HUMILITYFROMTHECONSIDERATIONOFOUR",
"verified": true,
"linkedPage": 118
},
{
"level": 0,
"text": "THOUGHTSOFGODUSTHELOWESTTHOUGHTSOFOurwewewewe",
"verified": true,
"linkedPage": 120
},
{
"level": 0,
"text": "PRAYER,ANOTHEROFANDTHEADVANTAGESOFMENTALandand",
"verified": true,
"linkedPage": 121
},
{
"level": 0,
"text": "RELIGIONTOBYTHESAMEMEANSBYWHICHBEGUN;ANDTHEUSEOFTHEHOLYTOWARDSwhichandsamemeanswhichwhichwhichand",
"verified": true,
"linkedPage": 124
},
{
"level": 0,
"text": "AA",
"verified": true,
"linkedPage": 126
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 45.974399999999996,
"mostUsedHeight": 7,
"minX": 26.29161,
"maxX": 273.69135,
"minY": 15.08535,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 45.974399999999996,
"mostUsedHeight": 7,
"minX": 26.29161,
"maxX": 273.69135,
"minY": 15.08535,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 190,
"mostUsedHeight": 11,
"minX": -97.924,
"maxX": 566.7790999999999,
"minY": 21.3071,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 190,
"mostUsedHeight": 11,
"minX": -97.924,
"maxX": 566.7790999999999,
"minY": 21.3071,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 190,
"mostUsedHeight": 11,
"minX": -97.924,
"maxX": 566.7790999999999,
"minY": 21.3071,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 190,
"mostUsedHeight": 11,
"minX": -97.924,
"maxX": 566.7790999999999,
"minY": 21.3071,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 190,
"mostUsedHeight": 11,
"minX": -97.924,
"maxX": 566.7790999999999,
"minY": 21.3071,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 53.88,
"maxX": 797.38,
"minY": 23.04,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 53.88,
"maxX": 797.38,
"minY": 23.04,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 53.88,
"maxX": 797.38,
"minY": 23.04,
@ -46,6 +47,62 @@
"toc": {
"pages": [
1
],
"entries": [
{
"level": 0,
"text": "Acknowledgements",
"verified": true,
"linkedPage": 3
},
{
"level": 0,
"text": "References",
"verified": true,
"linkedPage": 3
},
{
"level": 0,
"text": "Distribution & reproductionpage",
"verified": false,
"linkedPage": 3
},
{
"level": 0,
"text": "Executive summary",
"verified": true,
"linkedPage": 4
},
{
"level": 0,
"text": "Introduction",
"verified": true,
"linkedPage": 5
},
{
"level": 0,
"text": "Where can things go wrong?",
"verified": true,
"linkedPage": 6
},
{
"level": 0,
"text": "P",
"verified": true,
"linkedPage": 8
},
{
"level": 0,
"text": "Useful resources",
"verified": true,
"linkedPage": 40
},
{
"level": 0,
"text": "Appendices",
"verified": true,
"linkedPage": 42
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 53.88,
"maxX": 797.38,
"minY": 23.04,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 53.88,
"maxX": 797.38,
"minY": 23.04,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 12,
"minX": 6.487999999999971,
"maxX": 815.833,
"minY": 16.345999999999947,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 12,
"minX": 6.487999999999971,
"maxX": 815.833,
"minY": 16.345999999999947,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 12,
"minX": 6.487999999999971,
"maxX": 815.833,
"minY": 16.345999999999947,
@ -46,6 +47,98 @@
"toc": {
"pages": [
2
],
"entries": [
{
"level": 0,
"text": "Introduction",
"verified": true,
"linkedPage": 5
},
{
"level": 0,
"text": "History",
"verified": true,
"linkedPage": 7
},
{
"level": 0,
"text": "Setting and context",
"verified": true,
"linkedPage": 10
},
{
"level": 0,
"text": "Witneys people",
"verified": true,
"linkedPage": 12
},
{
"level": 0,
"text": "Health",
"verified": true,
"linkedPage": 14
},
{
"level": 0,
"text": "Witney at work",
"verified": true,
"linkedPage": 15
},
{
"level": 0,
"text": "Housing",
"verified": true,
"linkedPage": 16
},
{
"level": 0,
"text": "Crime and safety",
"verified": true,
"linkedPage": 17
},
{
"level": 0,
"text": "Education",
"verified": true,
"linkedPage": 18
},
{
"level": 0,
"text": "Transport",
"verified": true,
"linkedPage": 20
},
{
"level": 0,
"text": "Lifestyle and deprivation",
"verified": true,
"linkedPage": 21
},
{
"level": 0,
"text": "Conclusions",
"verified": true,
"linkedPage": 23
},
{
"level": 0,
"text": "What St Marys offers",
"verified": true,
"linkedPage": 25
},
{
"level": 0,
"text": "Recommendations",
"verified": true,
"linkedPage": 27
},
{
"level": 0,
"text": "Further information and links",
"verified": true,
"linkedPage": 28
}
]
}
}

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 12,
"minX": 6.487999999999971,
"maxX": 815.833,
"minY": 16.345999999999947,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 12,
"minX": 6.487999999999971,
"maxX": 815.833,
"minY": 16.345999999999947,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 28.799999999999997,
"mostUsedHeight": 14,
"minX": 72,
"maxX": 537.4124748000004,
"minY": 75.60000000000002,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 28.799999999999997,
"mostUsedHeight": 14,
"minX": 72,
"maxX": 537.4124748000004,
"minY": 75.60000000000002,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 28.799999999999997,
"mostUsedHeight": 14,
"minX": 72,
"maxX": 537.4124748000004,
"minY": 75.60000000000002,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 28.799999999999997,
"mostUsedHeight": 14,
"minX": 72,
"maxX": 537.4124748000004,
"minY": 75.60000000000002,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 28.799999999999997,
"mostUsedHeight": 14,
"minX": 72,
"maxX": 537.4124748000004,
"minY": 75.60000000000002,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 74.904,
"maxX": 518.5,
"minY": 99.864,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 74.904,
"maxX": 518.5,
"minY": 99.864,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 74.904,
"maxX": 518.5,
"minY": 99.864,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 74.904,
"maxX": 518.5,
"minY": 99.864,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 36,
"mostUsedHeight": 11,
"minX": 74.904,
"maxX": 518.5,
"minY": 99.864,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 11,
"mostUsedHeight": 11,
"minX": 72.025,
"maxX": 536.73,
"minY": 75.025,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 11,
"mostUsedHeight": 11,
"minX": 72.025,
"maxX": 536.73,
"minY": 75.025,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 11,
"mostUsedHeight": 11,
"minX": 72.025,
"maxX": 536.73,
"minY": 75.025,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 11,
"mostUsedHeight": 11,
"minX": 72.025,
"maxX": 536.73,
"minY": 75.025,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 11,
"mostUsedHeight": 11,
"minX": 72.025,
"maxX": 536.73,
"minY": 75.025,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 12,
"minX": 57.59999999999991,
"maxX": 312.78,
"minY": 44.76,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 12,
"minX": 57.59999999999991,
"maxX": 312.78,
"minY": 44.76,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 12,
"minX": 57.59999999999991,
"maxX": 312.78,
"minY": 44.76,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 12,
"minX": 57.59999999999991,
"maxX": 312.78,
"minY": 44.76,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 24,
"mostUsedHeight": 12,
"minX": 57.59999999999991,
"maxX": 312.78,
"minY": 44.76,

View File

@ -28,6 +28,7 @@
],
"globals": {
"maxHeight": 22.5,
"mostUsedHeight": 11,
"minX": 13.799999999999926,
"maxX": 550.2000000000003,
"minY": 1.4400099999998357,

View File

@ -32,6 +32,7 @@
],
"globals": {
"maxHeight": 22.5,
"mostUsedHeight": 11,
"minX": 13.799999999999926,
"maxX": 550.2000000000003,
"minY": 1.4400099999998357,

View File

@ -35,6 +35,7 @@
],
"globals": {
"maxHeight": 22.5,
"mostUsedHeight": 11,
"minX": 13.799999999999926,
"maxX": 550.2000000000003,
"minY": 1.4400099999998357,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 22.5,
"mostUsedHeight": 11,
"minX": 13.799999999999926,
"maxX": 550.2000000000003,
"minY": 1.4400099999998357,

View File

@ -31,6 +31,7 @@
],
"globals": {
"maxHeight": 22.5,
"mostUsedHeight": 11,
"minX": 13.799999999999926,
"maxX": 550.2000000000003,
"minY": 1.4400099999998357,

Some files were not shown because too many files have changed in this diff Show More