Skip to content

Commit

Permalink
Fix the remaining links pointing to (old) alias links
Browse files Browse the repository at this point in the history
  • Loading branch information
Lotes committed May 29, 2024
1 parent 7ce4268 commit bd16a91
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 32 deletions.
6 changes: 3 additions & 3 deletions hugo/content/docs/introduction/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ In this chapter, you'll get a closer look at the requirements developers usually
- [Cross References and Linking](#cross-references-and-linking)
- [Workspace Management](#workspace-management)
- [Editing Support](#editing-support)
- [Try it out!](#try-it-out)
- [Try it out](#try-it-out)

Langium provides out-of-the-box solutions for these problems, with the ability to fine-tune every part of it to fit your domain requirements.

---

## Language Parsing

Programming languages and domain specific languages (DSLs) cannot be parsed using simple regular expressions (RegExp). Instead they require a more sophisticated parsing strategy. To define a custom language in Langium, you interact with a high level representation of your context-free grammar using the [Langium grammar language](/docs/grammar-language), in a similar fashion to EBNF.
Programming languages and domain specific languages (DSLs) cannot be parsed using simple regular expressions (RegExp). Instead they require a more sophisticated parsing strategy. To define a custom language in Langium, you interact with a high level representation of your context-free grammar using the [Langium grammar language](/docs/reference/grammar-language), in a similar fashion to EBNF.

Based on the grammar, Langium is then able to construct a parser which transforms an input string into a semantic model representation. Just as the name suggests, this model captures the essential structure to describe your language.

Expand Down Expand Up @@ -97,7 +97,7 @@ The Langium framework is deeply integrated with the [language server protocol](h

The LSP includes commonly used language features, such as code completion, custom validations/diagnostics, finding references, formatting and many more. This allows for deep IDE integration without binding your language to a single IDE. Langium offers out-of-the-box support for most of these language features, with additional extension points for your domain specific requirements.

## Try it out!
## Try it out

You can try out most of these features using our [showcase](/showcase/) and [playground](/playground/). The languages shown there are written using Langium and integrated in the monaco-editor.

Expand Down
2 changes: 1 addition & 1 deletion hugo/content/docs/learn/workflow/_index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Langium's workflow"
weight: 0
url: /docs/learn/workflow/
url: /docs/learn/workflow
aliases:
- /docs/getting-started
---
Expand Down
2 changes: 1 addition & 1 deletion hugo/content/docs/recipes/builtin-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ For example, TypeScript provides users with typings for globally accessible vari
They are part of the JavaScript runtime, and not defined by any user or a package they might import.
Instead, these features are contributed through what we call builtin libraries.

Loading a builtin library in Langium is very simple. We first start off with defining the source code of the library using the *hello world* language from the [getting started guide](/docs/getting-started):
Loading a builtin library in Langium is very simple. We first start off with defining the source code of the library using the *hello world* language from the [getting started guide](/docs/learn/workflow):

```ts
export const builtinHelloWorld = `
Expand Down
2 changes: 1 addition & 1 deletion hugo/content/docs/recipes/code-bundling.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ aliases:
- /guides/code-bundling
---

When you first create a Langium project using the [Yeoman generator](/docs/learn/workflow/install), it will only contain a plain TypeScript configuration, without any additional build processes.
When you first create a Langium project using the [Yeoman generator](/docs/learn/workflow/scaffold#your-first-example-language), it will only contain a plain TypeScript configuration, without any additional build processes.
However, if you want to make your language available for consumption in a non-development context, you'll want to create a bundle.
It is not absolutely necessary in a Node.js context, since you can always resolve local `node_modules` but it's still recommended [for vscode extensions](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
It improves performance and decreases file size by minifying your code and only including what you actually need.
Expand Down
2 changes: 1 addition & 1 deletion hugo/content/docs/recipes/multiple-languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The entire change touches several files. Let's summarize what needs to be done:

## Our scenario

To keep this guide easy, I will use the `hello-world` project from the [learning section](/docs/learn/workflow).
To keep this guide easy, I will use the [`hello-world` project](/docs/learn/workflow) of the learning section.

Let’s imagine that we have three languages:

Expand Down
4 changes: 2 additions & 2 deletions hugo/content/docs/recipes/scoping/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ In general, the way we resolve references is split into three phases of the docu

In this guide, we'll look at different scoping kinds and styles and see how we can achieve them using Langium:

1. [Qualified Name Scoping](./qualified-name)
2. [Class Member Scoping](./class-member)
1. [Qualified Name Scoping](/docs/recipes/scoping/qualified-name)
2. [Class Member Scoping](/docs/recipes/scoping/class-member)

Note that these are just example implementations for commonly used scoping methods.
The scoping API of Langium is designed to be flexible and extensible for any kind of use case.
2 changes: 1 addition & 1 deletion hugo/content/docs/recipes/scoping/qualified-name.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void main() {
As can be seen, using qualified name scoping is quite helpful in this case. It allows us to reference the `getDocumentation` function through the scope computed & made available by the `Langium` namespace, even though it's not directly accessible within the scope of `main` by itself.
Note that such behavior can also be accomplished using [class member scoping](./class-member).
Note that such behavior can also be accomplished using [class member scoping](/docs/recipes/scoping/class-member).
However, there is one core advantage to using globally available elements:
Compared to member scoping, this type of scoping requires few resources.
The lookup required for qualified name scoping can be done in near constant time with just a bit of additional computation on a **per-document** basis, whereas member scoping needs to do a lot of computation on a **per-reference** basis.
Expand Down
4 changes: 3 additions & 1 deletion hugo/content/docs/reference/grammar-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ aliases:
The grammar language describes the syntax and structure of your language. The [Langium grammar language](https://github.com/eclipse-langium/langium/blob/main/packages/langium/src/grammar/langium-grammar.langium) is implemented using Langium itself and therefore follows the same syntactic rules as any language created with Langium. The grammar language will define the structure of the *abstract syntax tree* (AST) which in Langium is a collection of *TypeScript types* describing the content of a parsed document and organized hierarchically. The individual nodes of the tree are then represented with JavaScript objects at runtime.

In the following, we describe the Langium syntax and document structure.

## Language Declaration

An *entry* Langium grammar file (i.e. a grammar which contains an [entry rule](#the-entry-rule)) always starts with a header which declares the name of the language. For example, a language named `MyLanguage` would be declared with:

```langium
Expand Down Expand Up @@ -80,7 +82,7 @@ Person:
```
In this example, the parser will create an object of type `Person`. This object will have a property `name` which value and type must match the terminal rule `ID` (i.e. the property `name` is of type `string` and cannot start with a digit or special character).

By default, the parser will create an object with an inferred type corresponding to the parser rule name. It is possible to override this behavior by explicitly defining the type of the object to be created. This is done by adding the keyword `returns` followed by a separately declared type, or the keyword `infers` followed by the name of the type to be inferred for this rule (more about this [in the next chapter](../sematic-model)):
By default, the parser will create an object with an inferred type corresponding to the parser rule name. It is possible to override this behavior by explicitly defining the type of the object to be created. This is done by adding the keyword `returns` followed by a separately declared type, or the keyword `infers` followed by the name of the type to be inferred for this rule (more about this [in the next chapter](/docs/reference/semantic-model)):
```langium
Person infers OtherType:
'person' name=ID;
Expand Down
2 changes: 1 addition & 1 deletion hugo/content/docs/reference/semantic-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ interface X extends AstNode {
```

### Assignments
There are three available kinds of [assignments](../grammar-language/#assignments) in a parser rule:
There are three available kinds of [assignments](/docs/reference/grammar-language/#assignments) in a parser rule:

1. `=` for assigning a **single value** to a property, resulting in the property's type to be derived from the right hand side of the assignment.
2. `+=` for assigning **multiple values** to a property, resulting in the property's type to be an array of the right hand side of the assignment.
Expand Down
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"check:links": "ts-node scripts/check-links.ts"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"chalk": "^4.0.0",
"concurrently": "~8.2.1",
"cross-env": "~7.0.3",
"front-matter": "^4.0.2",
Expand Down
58 changes: 38 additions & 20 deletions scripts/check-links.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { glob } from "glob";
import { mkdir, readFile } from "node:fs/promises";
import { readFile } from "node:fs/promises";
import { basename, dirname, resolve, relative } from 'node:path';
import chalk from 'chalk';
import fm from "front-matter";

type Attributes = {
Expand All @@ -11,41 +12,56 @@ type Attributes = {

type MarkdownFile = {
localPath: string;
documentLink: string;
aliases: string[];
links: string[];
}

type LinkType = 'alias'|'document';

const projectDir = dirname(__dirname);
const contentDir = resolve(projectDir, "hugo", "content");

async function main() {
let success = true;
const markdownFiles: MarkdownFile[] = await readMarkdownFiles();
//collect what is there
const setOfUrls = new Set<string>([
const markdownFiles = await readMarkdownFiles();
const setOfUrls = classifyAsDocumentLinksOrAliases(markdownFiles);
//await writeFile("existingLinks.txt", JSON.stringify([...setOfUrls.entries()], null, 2));
return printMissingLinks(markdownFiles, setOfUrls);
}

function classifyAsDocumentLinksOrAliases(markdownFiles: MarkdownFile[]) {
const documentLinks = [
...markdownFiles.map(m => m.documentLink),
'http://langium.org/',
"/showcase",
"/playground"
].map(urlToString));
for (const file of markdownFiles) {
for (const url of file.aliases) {
setOfUrls.add(urlToString(url));
}
}
//check what is missing
].map(urlToString).map(s => [s, 'document'] as const);
const aliases = markdownFiles.flatMap(m => m.aliases).map(urlToString).map(s => [s, 'alias'] as const);
return new Map<string, LinkType>([...documentLinks, ...aliases]);
}

function printMissingLinks(markdownFiles: MarkdownFile[], setOfUrls: Map<string, LinkType>) {
let success: boolean = true;
for (const file of markdownFiles) {
let out = false;
for (const link of file.links) {
if(link.startsWith("http") || link.endsWith(".png") || link.endsWith(".jpg")) {
if (link.startsWith("http") || link.endsWith(".png") || link.endsWith(".jpg")) {
continue;
}
const url = urlToString(link);
if(!setOfUrls.has(url)) {
if(!out) {
if (!setOfUrls.has(url)) {
if (!out) {
console.log(`${relative(contentDir, file.localPath)}:`);
out = true;
}
console.log(`- ${chalk.red("MISSING LINK")}: ${url.toString()}`);
success = false;
} else if(setOfUrls.get(url) === 'alias') {
if (!out) {
console.log(`${relative(contentDir, file.localPath)}:`);
out = true;
}
console.log(`- MISSING LINK: ${url.toString()}`);
console.log(`- ${chalk.yellow("LINK TO ALIAS")}: ${url.toString()}`);
success = false;
}
}
Expand All @@ -65,16 +81,17 @@ async function readMarkdownFiles() {
if (aliases) {
urls = [...urls, ...aliases];
}
let documentLink: string = '';
if (url) {
urls.push(url);
documentLink = url;
} else if (slug) {
urls.push(relative(contentDir, resolve(mdFile, '..', slug)));
documentLink = relative(contentDir, resolve(mdFile, '..', slug));
} else {
const base = basename(mdFile, '.md');
if (["index.md", "_index.md", '_index'].includes(base)) {
urls.push(relative(contentDir, resolve(mdFile, '..')));
documentLink = relative(contentDir, resolve(mdFile, '..'));
} else {
urls.push(relative(contentDir, resolve(mdFile, '..', base)));
documentLink = relative(contentDir, resolve(mdFile, '..', base));
}
}

Expand All @@ -84,6 +101,7 @@ async function readMarkdownFiles() {
//new file
markdownFiles.push({
localPath: mdFile,
documentLink,
aliases: urls,
links
});
Expand Down

0 comments on commit bd16a91

Please sign in to comment.