MenuMarkup specification
This post describes an initial (internal used) markup for restaurant menus and other pricelists. It is used to semi-automatically parse hundreds of menus into a structured menu format.
A Ruby MenuMarkup parser gem is available on Github.
MenuMarkup
MenuMarkup is a super simple markup to specify menu data in plain text. When the MenuMarkup is parsed it creates a Menu. A Menu consists of two types: Items and Sections. Items have multiple Prices.
An example menu
Let’s jump right in with an example menu.
# Lines with a # are comments!
# Empty lines are ignored
* Main dishes
The main dishes can be ordered between 17.00 and 21.00.
- Super meat 29.95 euro
This is 500 grams of pure super meat.
- Some other dish
#This dish has the price on a different line. It will be parsed correctly.
12,95
- Daily fish
#This differs every day and the price can also change.
=depends
*Dessert
- Special dessert
#This dessert has multiple sizes and prices.
= small 12,30
= large 23,30
- A desert for 2
= 12,30 per person
- 300 grams of chocolate
#To not make the price 300 we specify an empty price using '='.
=
MenuMarkup is pretty loose. So the following is no problem. You shouldn’t worry about spaces, etc.:
* Starters
This are our starters. Enjoy!
- Lobster 12
- Meatballs
= per person 23,00
Nice round meatbals.
Markup drilldown
MenuMarkup is based on OpenMenu.org Menu information and Single Platform Menu information.
Comments
Lines starting with #
are comments. They are used to include for example the source url of the information.
Sidenotes
In our (mostly automated) menu scraping and parsing flow we add the following by default:
# Tue Jul 03 2012 15:26:13 GMT+0200 (CEST)
# New selection from: http://restaurant.com/menu.pdf
Items
Lines starting with -
are Items. An Item has a title
, description
and a Price.
- The Item Title
The item description is here.
And goes on for many
many
lines..
To further specify use:
Notation | Info |
---|---|
-v- | Vegetarian dish |
-V- | Vegan dish |
-k- | Kosher dish |
-h- | Halal dish |
Specify spicyness | |
-n- | None |
-m- | Mild |
-M- | Medium |
-H- | Hot |
You can combine the letters above. For example:
-v- This is a vegetarian dish.
With a description and a price of 12.30.
-kVH- This is a Kosher Vegan Hot dish :)
12.30
The line above is obviously the price and this will be the description.
The most relevant number will be converted to a Price.
Sidenotes
A title should not be too long so that the Menu will be pleasurable to watch. You can break down titles by searching for “,” “:” “with” “and” “served”.
Sections
Items can be split into Sections. A Section has a title
(single-lined) and a description
. Lines starting with -
are Sections.
- ‘Starters’ (Voorgerechten)
- ‘Main courses’ (Hoofdgerechten)
- ‘Wine’ (Wijn)
Make sure to put the description about the section directly under the Section Title, and not at the end of the section; Example:
*Starters
Starters are served with bread
-Soup
Example:
* The Section Title
The section description is here.
And goes on for many
many
lines..
** A subsection
With more info
*** A subsubsection
Yep very cool!
Sidenotes
When entering the sections make sure they are rather short, so no entire lines. Also make sure there isn’t a “:” behind the section, this is very common in menus but not good for our markup.
If there is a *
at the beginning of an information line in the menu. Make sure you replace it by something else, eg.:
# For example add brackets.
(*) All menu items with a * are not available after 18.00 o'clock.
Prices
Prices are automagically parsed from Items. However sometimes you might need to be more specific about.
To set a special Price use (for example):
=dagprijs
To set multiple Prices using (for example):
=300 gram 12.50 per person
=500 gram 19,00 per person
To set min/max Prices use something like:
=Min 12.50
=Max 19,00
If possible while setting the price, make sure the price is the last item in the line:
-Bread
= 750 gram € 4,50
= 1,5 kilo € 8,95
So not like:
# This is WRONG
-Bread
= € 4,50 750 gram
= € 8,95 1,5 kilo
To specify an empty Price use:
=
Other examples:
=glas 2,50
=bottle 10,00
=1/2 bottle 5,00
=8 pieces 12.-
=30,00 p.p.
Edge cases
If you find a price in front of the item name. You can use:
-12.20
Some title
Some description.
Special Menu Cases
Below you will see some special menu cases that need to be handled in his own way.
Table d'hôte
Sometimes you are presented with a menu with only a few options with a fixed price. You should represent it in the following markup:
*Keuze Menu
=12.50 p.p. alleen per hele tafel
**\Voorgerechten
-Tomaten Soep
-Carpaccio
**\Hoofdgerechten
-Biefstuk
-Kalkoen
**\
-Dame Blance
-Ijsje
the **\
will put the word “or”/“of” in between the dishes to show that it is an option to choose between them.
Rice Tables
Rice Tables are menus with a lot of dishes stuffed in to one option. Proposed markup:
-Rice Table 1
(min. 2 personen)
=22.50 per person
Tod Man Plaa, Viskoekjes
Tom Yam Kai, Thaise pikante soep met kipfilet
Pad Pak Luom Mid,Thaise groenteschotel met cashewnoten
Plaa Sam Rod, Vis filet (tilapia) met chillipepers
Keng Kiou Waan Koeng,Garnalen in groene curry saus
Koffie Of Thee