Skip to content

Commit

Permalink
Merge pull request #4 from cm-ayf/no-position
Browse files Browse the repository at this point in the history
add no position option
  • Loading branch information
cm-ayf authored Jan 20, 2024
2 parents a932981 + 10acf57 commit 289d2a6
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 101 deletions.
5 changes: 3 additions & 2 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {Extension as MicromarkExtension} from 'micromark-util-types';
import type {Extension as FromMarkdownExtension} from 'mdast-util-from-markdown';
import type {Processor} from 'unified';
import {micromarkExtension} from './micromark/index.js';
import {transform} from './transform/index.js';
import {createTransform} from './transform/index.js';
import {fromMarkdownExtension} from './from-markdown.js';

declare module 'unified' {
Expand All @@ -17,6 +17,7 @@ declare module 'unified' {
export interface Options {
allowNoSpaceBeforeName?: boolean;
allowUnderscoreInId?: boolean;
allowNoPosition?: boolean;
}

export default function remarkAttributeList(
Expand All @@ -31,5 +32,5 @@ export default function remarkAttributeList(
data.fromMarkdownExtensions ??= [];
data.fromMarkdownExtensions.push(fromMarkdownExtension);

return transform;
return createTransform(options);
}
133 changes: 71 additions & 62 deletions lib/transform/find-target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,82 +6,91 @@ import type {
BlockInlineAttributeList,
SpanInlineAttributeList,
} from '../mdast.js';
import type {Options} from '../index.js';

export default function findTarget(
node: BlockInlineAttributeList | SpanInlineAttributeList,
index: number,
parent: Parent,
) {
switch (node.type) {
case 'blockInlineAttributeList': {
return (
findTargetHalf(node, index, parent, 'preceding') ??
findTargetHalf(node, index, parent, 'following')
);
}
export function createFindTarget(options?: Options) {
return findTarget;

function findTarget(
node: BlockInlineAttributeList | SpanInlineAttributeList,
index: number,
parent: Parent,
) {
switch (node.type) {
case 'blockInlineAttributeList': {
return (
findTargetHalf(node, index, parent, 'preceding') ??
findTargetHalf(node, index, parent, 'following')
);
}

case 'spanInlineAttributeList': {
const target = findTargetHalf(node, index, parent, 'preceding');
if (target?.type === 'text') return;
return target;
case 'spanInlineAttributeList': {
const target = findTargetHalf(node, index, parent, 'preceding');
if (target?.type === 'text') return;
return target;
}
}
}
}

function findTargetHalf(
node: BlockInlineAttributeList | SpanInlineAttributeList,
index: number,
parent: Parent,
direction: 'preceding' | 'following',
): RootContent | undefined {
const step = {preceding: -1, following: 1}[direction];
let current: BlockInlineAttributeList | SpanInlineAttributeList = node;
function findTargetHalf(
node: BlockInlineAttributeList | SpanInlineAttributeList,
index: number,
parent: Parent,
direction: 'preceding' | 'following',
): RootContent | undefined {
const step = {preceding: -1, following: 1}[direction];
let current: BlockInlineAttributeList | SpanInlineAttributeList = node;

while (between((index += step), 0, parent.children.length)) {
const next = parent.children[index];
assert(next);
assert(current.position);
assert(next.position);
while (between((index += step), 0, parent.children.length)) {
const next = parent.children[index];
assert(next);
assert(current.position);
assert(next.position);

if (
(direction === 'preceding' &&
!isNext(current.type, next.position, current.position)) ||
(direction === 'following' &&
!isNext(current.type, current.position, next.position))
) {
break;
}
if (
(direction === 'preceding' &&
!isNext(current.type, next.position, current.position)) ||
(direction === 'following' &&
!isNext(current.type, current.position, next.position))
) {
break;
}

if (next.type === node.type) {
current = next;
continue;
} else {
return next;
if (next.type === node.type) {
current = next;
continue;
} else {
return next;
}
}
}

return undefined;
}
return undefined;
}

function between(index: number, left: number, right: number) {
return index >= left && index < right;
}
function between(index: number, left: number, right: number) {
return index >= left && index < right;
}

function isNext(
type: 'blockInlineAttributeList' | 'spanInlineAttributeList',
preceding: Position,
following: Position,
) {
switch (type) {
case 'blockInlineAttributeList': {
return following.start.line === preceding.end.line + 1;
function isNext(
type: 'blockInlineAttributeList' | 'spanInlineAttributeList',
preceding: Position,
following: Position,
) {
if (options?.allowNoSpaceBeforeName && (!preceding || !following)) {
return true;
}

case 'spanInlineAttributeList': {
return (
following.start.line === preceding.end.line &&
following.start.column === preceding.end.column
);
switch (type) {
case 'blockInlineAttributeList': {
return following.start.line === preceding.end.line + 1;
}

case 'spanInlineAttributeList': {
return (
following.start.line === preceding.end.line &&
following.start.column === preceding.end.column
);
}
}
}
}
81 changes: 44 additions & 37 deletions lib/transform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,50 @@ import type {Root} from 'mdast';
import {visit} from 'unist-util-visit';
import {ok as assert} from 'devlop';
import {remove} from 'unist-util-remove';
import type {Transform} from 'mdast-util-from-markdown';
import type {Options} from '../index.js';
import Definitions from './definitions.js';
import assignAttributes from './assign-attributes.js';
import findTarget from './find-target.js';

export function transform(tree: Root) {
const definitions = new Definitions();

visit(tree, 'attributeListDefinition', (node) => {
definitions.set(node);
});

visit(
tree,
['blockInlineAttributeList', 'spanInlineAttributeList'] as const,
(node, index, parent) => {
// `typeof node` should be narrowed, but is not, due to bug on `visit`
assert(
node.type === 'blockInlineAttributeList' ||
node.type === 'spanInlineAttributeList',
);
assert(parent);
assert(typeof index === 'number');

const target = findTarget(node, index, parent);
if (!target) return;

const attributes = definitions.resolve(node);

if (attributes.length > 0) assignAttributes(target, attributes);
},
);

remove(tree, [
'attributeListDefinition',
'blockInlineAttributeList',
'spanInlineAttributeList',
]);

return tree;
import {createFindTarget} from './find-target.js';

export function createTransform(options?: Options): Transform {
const findTarget = createFindTarget(options);
return transform;

function transform(tree: Root) {
const definitions = new Definitions();

visit(tree, 'attributeListDefinition', (node) => {
definitions.set(node);
});

visit(
tree,
['blockInlineAttributeList', 'spanInlineAttributeList'] as const,
(node, index, parent) => {
// `typeof node` should be narrowed, but is not, due to bug on `visit`
assert(
node.type === 'blockInlineAttributeList' ||
node.type === 'spanInlineAttributeList',
);
assert(parent);
assert(typeof index === 'number');

const target = findTarget(node, index, parent);
if (!target) return;

const attributes = definitions.resolve(node);

if (attributes.length > 0) assignAttributes(target, attributes);
},
);

remove(tree, [
'attributeListDefinition',
'blockInlineAttributeList',
'spanInlineAttributeList',
]);

return tree;
}
}

0 comments on commit 289d2a6

Please sign in to comment.