Do not allow plain links without a path.

This commit is contained in:
Tom Alexander 2023-08-29 15:44:04 -04:00
parent f592b73ae7
commit 56865c68fc
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 100 additions and 34 deletions

View File

@ -0,0 +1,52 @@
non-link text
eww://
rmail://
mhe://
irc://
info://
gnus://
docview://
bibtex://
bbdb://
w3m://
doi://
file+sys://
file+emacs://
shell://
news://
mailto://
https://
http://
ftp://
help://
file://
elisp://
randomfakeprotocl://
non-link text
non-link text
eww:
rmail:
mhe:
irc:
info:
gnus:
docview:
bibtex:
bbdb:
w3m:
doi:
file+sys:
file+emacs:
shell:
news:
mailto:
https:
http:
ftp:
help:
file:
elisp:
randomfakeprotocl:
non-link text

View File

@ -15,7 +15,8 @@ use crate::error::Res;
use crate::parser::object::Entity; use crate::parser::object::Entity;
use crate::parser::util::get_consumed; use crate::parser::util::get_consumed;
const ENTITIES: [&'static str; 413] = [ // TODO: Make this a user-provided variable corresponding to elisp's org-entities
const ORG_ENTITIES: [&'static str; 413] = [
"Agrave", "Agrave",
"agrave", "agrave",
"Aacute", "Aacute",
@ -457,8 +458,7 @@ fn name<'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
// TODO: This should be defined by org-entities and optionally org-entities-user // TODO: This should be defined by org-entities and optionally org-entities-user
for entity in ENTITIES { for entity in ORG_ENTITIES {
// foo
let result = tag_no_case::<_, _, CustomError<_>>(entity)(input); let result = tag_no_case::<_, _, CustomError<_>>(entity)(input);
match result { match result {
Ok((remaining, ent)) => { Ok((remaining, ent)) => {

View File

@ -7,6 +7,7 @@ use nom::character::complete::one_of;
use nom::combinator::eof; use nom::combinator::eof;
use nom::combinator::peek; use nom::combinator::peek;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::OrgSource; use super::org_source::OrgSource;
@ -23,6 +24,33 @@ use crate::parser::util::exit_matcher_parser;
use crate::parser::util::get_consumed; use crate::parser::util::get_consumed;
use crate::parser::util::WORD_CONSTITUENT_CHARACTERS; use crate::parser::util::WORD_CONSTITUENT_CHARACTERS;
// TODO: Make this a user-provided variable corresponding to elisp's org-link-parameters
const ORG_LINK_PARAMETERS: [&'static str; 23] = [
"id",
"eww",
"rmail",
"mhe",
"irc",
"info",
"gnus",
"docview",
"bibtex",
"bbdb",
"w3m",
"doi",
"file+sys",
"file+emacs",
"shell",
"news",
"mailto",
"https",
"http",
"ftp",
"help",
"file",
"elisp",
];
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn plain_link<'r, 's>( pub fn plain_link<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,
@ -73,36 +101,19 @@ pub fn protocol<'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> { ) -> Res<OrgSource<'s>, OrgSource<'s>> {
// TODO: This should be defined by org-link-parameters // TODO: This should be defined by org-link-parameters
let (remaining, proto) = alt(( for link_parameter in ORG_LINK_PARAMETERS {
alt(( let result = tag_no_case::<_, _, CustomError<_>>(link_parameter)(input);
tag_no_case("id"), match result {
tag_no_case("eww"), Ok((remaining, ent)) => {
tag_no_case("rmail"), return Ok((remaining, ent));
tag_no_case("mhe"), }
tag_no_case("irc"), Err(_) => {}
tag_no_case("info"), }
tag_no_case("gnus"), }
tag_no_case("docview"),
tag_no_case("bibtex"), Err(nom::Err::Error(CustomError::MyError(MyError(
tag_no_case("bbdb"), "NoLinkProtocol".into(),
tag_no_case("w3m"), ))))
)),
alt((
tag_no_case("doi"),
tag_no_case("file+sys"),
tag_no_case("file+emacs"),
tag_no_case("shell"),
tag_no_case("news"),
tag_no_case("mailto"),
tag_no_case("https"),
tag_no_case("http"),
tag_no_case("ftp"),
tag_no_case("help"),
tag_no_case("file"),
tag_no_case("elisp"),
)),
))(input)?;
Ok((remaining, proto))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
@ -119,7 +130,10 @@ fn path_plain<'r, 's>(
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context); let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
let (remaining, path) = recognize(many_till(anychar, peek(exit_matcher)))(input)?; let (remaining, path) = recognize(verify(
many_till(anychar, peek(exit_matcher)),
|(children, _exit_contents)| !children.is_empty(),
))(input)?;
Ok((remaining, path)) Ok((remaining, path))
} }