Skip to content

Commit

Permalink
test: quotes convert
Browse files Browse the repository at this point in the history
  • Loading branch information
Myllaume committed Oct 3, 2024
1 parent ff5234c commit 7051c7c
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 71 deletions.
73 changes: 2 additions & 71 deletions core/models/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { isAnImagePath, slugify } from '../utils/misc.js';
import langPck from './lang.js';
import { fileURLToPath } from 'url';
import convertWikilinks from '../utils/convertWikilinks.js';
import convertQuotes from '../utils/convertQuotes.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand Down Expand Up @@ -222,77 +223,7 @@ class Template {
input = convertWikilinks(input, graph.records, opts, idToHighlight);

if (bibliography) {
Citr.util.extractCitations(input).forEach((quoteText, index) => {
let citationItems;
try {
citationItems = Citr.parseSingle(quoteText);
} catch (error) {
citationItems = [];
}

/**
* @type {Map<string, string>}
* Dictionnary contains record id for each cluster
* @example
* ```
* "[@Fowler_2003, 2]"
* { 'Fowler 2003' => 'Fowler_2003' }
* ```
*/
const idsDictionnary = new Map();
for (const item of citationItems) {
const { id } = item;
if (!bibliography.library[id]) continue;

const idAsTextQuote = bibliography.citeproc
// get "(Fowler 2003)"
.processCitationCluster(
{
citationItems: [item],
properties: { noteIndex: index + 1 },
},
[],
[],
)[1][0][1]
// get "Fowler 2003"
.slice(1, -1);

idsDictionnary.set(idAsTextQuote, item.id);
}

/**
* Quoting marks to render on text
* @example
* ```
* "[@Fowler_2003, 2]" => "(Fowler 2003, p.2)"
* ```
*/
let cluster = bibliography.get({
quotesExtract: {
citationItems,
properties: { noteIndex: index + 1 },
},
text: quoteText,
ids: new Set(citationItems.map(({ id }) => id)),
}).cluster;

// Replace "(Fowler 2003, p.2)" to "(<a>Fowler 2003</a>, p.2)"
idsDictionnary.forEach((recordId, key) => {
cluster = cluster.replace(key, () => {
const record = graph.records.find(({ id }) => id === recordId);
if (!record) return key;
return `<a href="#${record.id}" title="${escapeQuotes(
record.title,
)}" class="record-link ${
record.id === idToHighlight ? 'highlight' : ''
}">${key}</a>`.trim();
});
});

if (cluster) {
input = input.replace(quoteText, cluster);
}
});
input = convertQuotes(input, bibliography, graph.records, idToHighlight);
}

return input;
Expand Down
61 changes: 61 additions & 0 deletions core/utils/convertQuotes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import extractCitations from './citeExtractor';
import Bibliography from '../models/bibliography';

/**
* @param {string} markdown
* @param {Bibliography} bibliography
*/

function convertQuotes(markdown, bibliography, records, idToHighlight) {
extractCitations(markdown).forEach((quote, index) => {
const originalText = quote.source; // => "[@engelbart1962; quoted by @matuschak2019]"

const idsDictionnary = new Map();

for (const item of quote.citations) {
if (!bibliography.library[item.id]) continue;

// get text to replace for each quote item
const itemText = bibliography.citeproc
.processCitationCluster(
{
citationItems: [item], // => "@engelbart1962"
properties: { noteIndex: index + 1 },
},
[],
[],
)[1][0][1] // => "(Engelbart 1962)"
.slice(1, -1); // => "Engelbart 1962"

idsDictionnary.set(itemText, item.id);
}

// get text to replace for quote (sum of items)
let quoteText = bibliography.citeproc.processCitationCluster(
{
citationItems: quote.citations, // => ["@engelbart1962", "@matuschak2019"]
properties: { noteIndex: index + 1 },
},
[],
[],
)[1][0][1]; // => "(Engelbart, 1962 ; quoted by Matuschak, Nielsen, 2019)"

// replace each item of quote
idsDictionnary.forEach((recordId, key) => {
quoteText = quoteText.replace(key, () => {
const record = records.find(({ id }) => id === recordId);

if (!record) return key;
return `<a href="#${record.id}" title="${record.title}" class="record-link ${record.id === idToHighlight ? 'highlight' : ''}">${key}</a>`;
});
});

// "[@engelbart1962; quoted by @matuschak2019]" =>
// (<a>Engelbart, 1962</a> ; <a>quoted by Matuschak, Nielsen, 2019</a>)
markdown = markdown.replace(originalText, quoteText);
});

return markdown;
}

export default convertQuotes;
153 changes: 153 additions & 0 deletions core/utils/convertQuotes.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import convertQuotes from './convertQuotes';

const mockProcessCitationCluster = jest.fn(() => [undefined, [[undefined, '(Matuschak, 2019)']]]);

const bibliography = {
library: {
matuschak2019: {
id: 'matuschak2019',
author: [
{ family: 'Matuschak', given: 'Andy' },
{ family: 'Nielsen', given: 'Michael' },
],
'citation-key': 'matuschak2019',
issued: { 'date-parts': [[2019]] },
language: 'en',
title: 'How can we develop transformative tools for thought?',
type: 'webpage',
URL: 'https://numinous.productions/ttft/',
},
engelbart1962: {
id: 'engelbart1962',
author: [{ family: 'Engelbart', given: 'Douglas C' }],
'citation-key': 'engelbart1962',
'event-place': 'Stanford',
genre: 'SRI Summary Report',
issued: { 'date-parts': [[1962]] },
language: 'en',
number: 'AFOSR-3223',
publisher: 'Stanford Research Institute',
'publisher-place': 'Stanford',
title: 'Augmenting Human Intellect: A Conceptual Framework',
'title-short': 'Augmenting Human Intellect',
type: 'report',
URL: 'https://www.dougengelbart.org/content/view/138/',
},
},
citeproc: {
processCitationCluster: mockProcessCitationCluster,
},
};

const records = [
{
id: 'matuschak2019',
title: 'Matuschak 2019',
},
{
id: 'engelbart1962',
title: 'Engelbart 1962',
},
];

describe('convertQuotes', () => {
it('should convert one link', () => {
const text = 'Lorem @matuschak2019 ipsum dolor est.';

const result = convertQuotes(text, bibliography, records, 'matuschak2019');

expect(mockProcessCitationCluster).toHaveBeenCalledWith(
{
citationItems: [
{
prefix: undefined,
id: 'matuschak2019',
'suppress-author': false,
locator: undefined,
label: 'page',
suffix: undefined,
},
],
properties: { noteIndex: 1 },
},
[],
[],
);

expect(result).toEqual(
'Lorem (<a href="#matuschak2019" title="Matuschak 2019" class="record-link highlight">Matuschak, 2019</a>) ipsum dolor est.',
);
});

it('should convert two links', () => {
mockProcessCitationCluster
.mockImplementationOnce(() => [undefined, [[undefined, '(Engelbart, 1962)']]])
.mockImplementationOnce(() => [
undefined,
[[undefined, '(quoted by Matuschak, Nielsen, 2019)']],
])
.mockImplementationOnce(() => [
undefined,
[[undefined, '(Engelbart, 1962 ; quoted by Matuschak, Nielsen, 2019)']],
]);

const text = 'Lorem [@engelbart1962; quoted by @matuschak2019] ipsum dolor est.';

const result = convertQuotes(text, bibliography, records, 'matuschak2019');

expect(mockProcessCitationCluster).toHaveBeenCalledWith(
{
citationItems: [
{
prefix: undefined,
id: 'engelbart1962',
'suppress-author': false,
locator: undefined,
label: 'page',
suffix: undefined,
},
],
properties: { noteIndex: 1 },
},
[],
[],
);
expect(mockProcessCitationCluster).toHaveBeenCalledWith(
{
citationItems: [
{
prefix: undefined,
id: 'matuschak2019',
'suppress-author': false,
locator: undefined,
label: 'page',
suffix: undefined,
},
],
properties: { noteIndex: 1 },
},
[],
[],
);

expect(result).toEqual(
'Lorem (<a href="#engelbart1962" title="Engelbart 1962" class="record-link ">Engelbart, 1962</a> ; <a href="#matuschak2019" title="Matuschak 2019" class="record-link highlight">quoted by Matuschak, Nielsen, 2019</a>) ipsum dolor est.',
);
});

it('should not add "highlight" class if unknown record', () => {
const text = 'Lorem @matuschak2019 ipsum dolor est.';

expect(convertQuotes(text, bibliography, records, 'unknown')).toEqual(
'Lorem (<a href="#matuschak2019" title="Matuschak 2019" class="record-link ">Matuschak, 2019</a>) ipsum dolor est.',
);
});

it('should not get anchor if no record', () => {
const text = 'Lorem @matuschak2019 ipsum dolor est.';

expect(convertQuotes(text, bibliography, [], 'matuschak2019')).toEqual(
'Lorem (Matuschak, 2019) ipsum dolor est.',
);
});
});

0 comments on commit 7051c7c

Please sign in to comment.